Authentication
If you add properties to the req object by Hooks, you can use AdditionalRequest to extend the type of the controller.
- fastify-jwt
- fastify-auth
- express-jwt
- express-passport
cd server
npm install fastify-jwt
server/service/app.ts
import Fastify from 'fastify'
import fastifyJwt from 'fastify-jwt'
import server from './$server'
const fastify = Fastify()
fastify.register(fastifyJwt, { secret: process.env.JWT_SECRET })
server(fastify, { basePath: '/api/v1' })
fastify.listen(3000)
server/api/token/controller.ts
import { defineController } from './$relay'
import { validateUser } from '$/service/user'
export default defineController((fastify) => ({
post: ({ body }) =>
validateUser(body.id, body.pass)
? { status: 201, body: { token: fastify.jwt.sign({ id: body.id }) } }
: { status: 401 }
}))
server/api/user/hooks.ts
import { defineHooks } from './$relay'
export type AdditionalRequest = {
user: {
id: string
}
}
export default defineHooks(() => ({
onRequest: (request, reply) =>
request.jwtVerify().catch((err) => reply.send(err))
}))
server/api/user/controller.ts
import { defineController } from './$relay'
import { getUserNameById } from '$/service/user'
export default defineController(() => ({
// user was added by AdditionalRequest of ./hooks.ts
get: async ({ user }) => ({ status: 200, body: await getUserNameById(user.id) })
}))
cd server
npm install fastify-auth
server/service/app.ts
import Fastify from 'fastify'
import fastifyAuth from 'fastify-auth'
import server from './$server'
const fastify = Fastify()
fastify.register(fastifyAuth).after(() => {
server(fastify, { basePath: '/api/v1' })
})
fastify.listen(3000)
server/api/user/hooks.ts
import { defineHooks } from './$relay'
import { getUserIdByToken } from '$/service/user'
export type AdditionalRequest = {
user: {
id: string
}
}
export default defineHooks((fastify) => ({
preHandler: fastify.auth([
(req, _, done) => {
const user =
typeof req.headers.token === 'string' &&
getUserIdByToken(req.headers.token)
if (user) {
// eslint-disable-next-line
// @ts-expect-error
req.user = user
done()
} else {
done(new Error('Unauthorized'))
}
}
])
}))
server/api/user/controller.ts
import { defineController } from './$relay'
import { getUserNameById } from '$/service/user'
export default defineController(() => ({
// user was added by AdditionalRequest of ./hooks.ts
get: async ({ user }) => ({ status: 200, body: await getUserNameById(user.id) })
}))
cd server
npm install express-jwt
npm install @types/express-jwt @types/jsonwebtoken --save-dev
server/api/token/controller.ts
import jwt from 'jsonwebtoken'
import { defineController } from './$relay'
import { validateUser } from '$/service/user'
export default defineController(() => ({
post: ({ body }) =>
validateUser(body.id, body.pass)
? { status: 201, body: { token: jwt.sign({ id: body.id }, process.env.JWT_SECRET) } }
: { status: 401 }
}))
server/api/user/hooks.ts
import jwt from 'express-jwt'
import { defineHooks } from './$relay'
export type AdditionalRequest = {
user: {
id: string
}
}
export default defineHooks(() => ({
onRequest: jwt({ secret: process.env.JWT_SECRET, algorithms: ['HS256'] })
}))
server/api/user/controller.ts
import { defineController } from './$relay'
import { getUserNameById } from '$/service/user'
export default defineController(() => ({
// user was added by AdditionalRequest of ./hooks.ts
get: async ({ user }) => ({ status: 200, body: await getUserNameById(user.id) })
}))
cd server
npm install passport passport-trusted-header
npm install @types/passport --save-dev
server/api/user/hooks.ts
import passport from 'passport'
import { defineHooks } from './$relay'
import { getUserIdByToken } from '$/service/user'
export type AdditionalRequest = {
user: {
id: string
}
}
passport.use(
// eslint-disable-next-line
new (require('passport-trusted-header').Strategy)(
{ headers: ['token'] },
// eslint-disable-next-line
(headers: { token: string }, done: Function) => {
done(null, getUserIdByToken(headers.token))
}
)
)
export default defineHooks(() => ({
onRequest: [
passport.initialize(),
passport.authenticate('trusted-header', { session: false })
]
}))
server/api/user/controller.ts
import { defineController } from './$relay'
import { getUserNameById } from '$/service/user'
export default defineController(() => ({
// user was added by AdditionalRequest of ./hooks.ts
get: async ({ user }) => ({ status: 200, body: await getUserNameById(user.id) })
}))