@fastify/jwt
Version:
JWT utils for Fastify
204 lines (178 loc) • 6.75 kB
text/typescript
import fastify from 'fastify'
import fastifyJwt, { FastifyJWTOptions, FastifyJwtNamespace, JWT, SignOptions, VerifyOptions } from '..'
import { expectAssignable, expectType } from 'tsd'
const app = fastify()
const secretOptions = {
secret: 'supersecret',
publicPrivateKey: {
public: 'publicKey',
private: 'privateKey'
},
secretFnCallback: (_req: any, _token: any, cb: any) => { cb(null, 'supersecret') },
secretFnPromise: (_req: any, _token: any) => Promise.resolve('supersecret'),
secretFnAsync: async (_req: any, _token: any) => 'supersecret',
secretFnBufferCallback: (_req: any, _token: any, cb: any) => { cb(null, Buffer.from('some secret', 'base64')) },
secretFnBufferPromise: (_req: any, _token: any) => Promise.resolve(Buffer.from('some secret', 'base64')),
secretFnBufferAsync: async (_req: any, _token: any) => Buffer.from('some secret', 'base64'),
publicPrivateKeyFn: {
public: (_req: any, _rep: any, cb: any) => { cb(null, 'publicKey') },
private: 'privateKey'
},
publicPrivateKeyFn2: {
public: 'publicKey',
private: (_req: any, _rep: any, cb: any) => { cb(null, 'privateKey') },
}
}
const jwtOptions: FastifyJWTOptions = {
secret: 'supersecret',
sign: {
expiresIn: 3600
},
cookie: {
cookieName: 'jwt',
signed: false
},
verify: {
maxAge: '1 hour',
extractToken: () => 'token',
onlyCookie: false
},
decode: {
complete: true
},
messages: {
badRequestErrorMessage: 'Bad Request',
badCookieRequestErrorMessage: 'Bad Cookie Request',
noAuthorizationInHeaderMessage: 'No Header',
noAuthorizationInCookieMessage: 'No Cookie',
authorizationTokenExpiredMessage: 'Token Expired',
authorizationTokenInvalid: (err) => `${err.message}`,
authorizationTokenUntrusted: 'Token untrusted'
},
trusted: () => false || '' || Buffer.from('foo'),
formatUser: payload => {
const objectPayload = typeof payload === 'string'
? JSON.parse(payload)
: Buffer.isBuffer(payload)
? JSON.parse(payload.toString())
: payload
return { name: objectPayload.userName }
},
namespace: 'security',
jwtVerify: 'securityVerify',
jwtSign: 'securitySign'
}
app.register(fastifyJwt, jwtOptions)
Object.values(secretOptions).forEach((value) => {
app.register(fastifyJwt, { ...jwtOptions, secret: value })
})
app.register(fastifyJwt, { ...jwtOptions, trusted: () => Promise.resolve(false || '' || Buffer.from('foo')) })
app.register(fastifyJwt, {
secret: {
private: {
key: 'privateKey',
passphrase: 'super secret passphrase',
},
public: 'publicKey',
},
sign: { algorithm: 'ES256' },
})
app.register(fastifyJwt, { ...jwtOptions, decoratorName: 'token' })
// expect jwt and its subsequent methods have merged with the fastify instance
expectAssignable<object>(app.jwt)
expectAssignable<Function>(app.jwt.sign)
expectAssignable<Function>(app.jwt.verify)
expectAssignable<Function>(app.jwt.decode)
expectAssignable<Function>(app.jwt.lookupToken)
expectAssignable<FastifyJWTOptions['cookie']>(app.jwt.cookie)
app.addHook('preHandler', async (request, reply) => {
// assert request and reply specific interface merges
expectAssignable<Function>(request.jwtVerify)
expectAssignable<Function>(request.jwtDecode)
expectAssignable<object | string | Buffer>(request.user)
expectAssignable<Function>(reply.jwtSign)
try {
await request.jwtVerify()
} catch (err) {
reply.send(err)
}
})
app.post('/signup', async (req, reply) => {
const token = app.jwt.sign({ user: 'userName' })
reply.send({ token })
})
// define custom payload
// declare module './jwt' {
// interface FastifyJWT {
// payload: {
// user: string
// }
// }
// }
// Custom payload with formatUser
// declare module './jwt' {
// interface FastifyJWT {
// payload: {
// user: string
// }
// user: {
// name: string
// }
// }
// }
expectType<JWT['decode']>(({} as FastifyJwtNamespace<{ namespace: 'security' }>).securityJwtDecode)
expectType<JWT['sign']>(({} as FastifyJwtNamespace<{ namespace: 'security' }>).securityJwtSign)
expectType<JWT['verify']>(({} as FastifyJwtNamespace<{ namespace: 'security' }>).securityJwtVerify)
declare module 'fastify' {
interface FastifyInstance extends FastifyJwtNamespace<{ namespace: 'tsdTest' }> {
}
}
expectType<JWT['decode']>(app.tsdTestJwtDecode)
expectType<JWT['sign']>(app.tsdTestJwtSign)
expectType<JWT['verify']>(app.tsdTestJwtVerify)
expectType<JWT['decode']>(({} as FastifyJwtNamespace<{ namespace: 'security', jwtDecode: 'decode' }>).decode)
expectType<JWT['sign']>(({} as FastifyJwtNamespace<{ namespace: 'security', jwtDecode: 'decode' }>).securityJwtSign)
expectType<JWT['verify']>(({} as FastifyJwtNamespace<{ namespace: 'security', jwtDecode: 'decode' }>).securityJwtVerify)
expectType<JWT['decode']>(({} as FastifyJwtNamespace<{ namespace: 'security', jwtSign: 'decode' }>).securityJwtDecode)
expectType<JWT['sign']>(({} as FastifyJwtNamespace<{ namespace: 'security', jwtSign: 'sign' }>).sign)
expectType<JWT['verify']>(({} as FastifyJwtNamespace<{ namespace: 'security', jwtSign: 'decode' }>).securityJwtVerify)
expectType<JWT['decode']>(({} as FastifyJwtNamespace<{ namespace: 'security', jwtVerify: 'verify' }>).securityJwtDecode)
expectType<JWT['sign']>(({} as FastifyJwtNamespace<{ namespace: 'security', jwtVerify: 'verify' }>).securityJwtSign)
expectType<JWT['verify']>(({} as FastifyJwtNamespace<{ namespace: 'security', jwtVerify: 'verify' }>).verify)
expectType<JWT['decode']>(({} as FastifyJwtNamespace<{ jwtDecode: 'decode' }>).decode)
expectType<JWT['sign']>(({} as FastifyJwtNamespace<{ jwtSign: 'sign' }>).sign)
expectType<JWT['verify']>(({} as FastifyJwtNamespace<{ jwtVerify: 'verify' }>).verify)
let signOptions: SignOptions = {
key: 'supersecret',
algorithm: 'HS256',
mutatePayload: true,
expiresIn: 3600,
notBefore: 0,
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
signOptions = {
key: Buffer.from('supersecret', 'utf-8'),
algorithm: 'HS256',
mutatePayload: true,
expiresIn: 3600,
notBefore: 0,
}
let verifyOptions: VerifyOptions = {
key: 'supersecret',
algorithms: ['HS256'],
complete: true,
cache: true,
cacheTTL: 3600,
maxAge: '1 hour',
onlyCookie: false,
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
verifyOptions = {
key: Buffer.from('supersecret', 'utf-8'),
algorithms: ['HS256'],
complete: true,
cache: 3600,
cacheTTL: 3600,
maxAge: 3600,
onlyCookie: true,
}