### Installation Source: https://github.com/fastify/fastify-jwt/blob/main/README.md Install the @fastify/jwt plugin using npm. ```APIDOC ## Install ``` npm i @fastify/jwt ``` ``` -------------------------------- ### Fixing Missing @fastify/cookie Plugin for Cookie Mode Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/errors.md This example shows the correct setup for JWT cookie mode by first registering the @fastify/cookie plugin and then the JWT plugin. ```javascript fastify.register(require('@fastify/cookie')) fastify.register(jwt, { secret: 'secret', cookie: { cookieName: 'token', signed: false } }) ``` -------------------------------- ### Complete Fastify JWT Configuration Example Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/configuration.md A comprehensive example demonstrating various configuration options for the @fastify/jwt plugin, including secret management, sign/verify options, cookie support, custom validation, and error message customization. ```javascript const { readFileSync } = require('node:fs') const path = require('node:path') const fastify = require('fastify')() const jwt = require('@fastify/jwt') fastify.register(require('@fastify/cookie')) fastify.register(jwt, { // Required secret: { private: readFileSync(path.join(__dirname, 'keys/private.pem'), 'utf8'), public: readFileSync(path.join(__dirname, 'keys/public.pem'), 'utf8') }, // Sign options sign: { algorithm: 'RS256', expiresIn: '7d', iss: 'my-app', aud: 'my-users' }, // Verify options verify: { algorithms: ['RS256'], maxAge: '30d', allowedIss: 'my-app', allowedAud: 'my-users', cache: 1000 }, // Decode options decode: { complete: false, checkTyp: 'JWT' }, // Cookie support cookie: { cookieName: 'access_token', signed: true }, // Custom validation trusted: async (request, decodedToken) => { const user = await db.users.findById(decodedToken.userId) return user && user.isActive }, // Transform user formatUser: (payload) => ({ id: payload.userId, email: payload.email, roles: payload.roles || [] }), // Custom names decoratorName: 'user', jwtSign: 'signToken', jwtVerify: 'verifyToken', // Error messages messages: { authorizationTokenExpiredMessage: 'Session expired', authorizationTokenInvalid: (err) => `Invalid token: ${err.message}` } }) fastify.listen({ port: 3000 }, (err) => { if (err) throw err console.log('Server running on port 3000') }) ``` -------------------------------- ### JWT Signing Example Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/api-reference/plugin-factory.md Example of signing a JWT using the reply.jwtSign() decorator, which is added by the @fastify/jwt plugin. ```javascript const token = await reply.jwtSign({ id: 123, username: 'testuser' }); ``` -------------------------------- ### Fastify JWT Signing and Verification Example Source: https://github.com/fastify/fastify-jwt/blob/main/README.md Demonstrates how to register the @fastify/jwt plugin, sign a JWT with a payload, and verify it. This example includes setting a secret dynamically and making HTTP requests to trigger the signing and verification endpoints. ```javascript const fastify = require('fastify')() const jwt = require('@fastify/jwt') const request = require('request') fastify.register(jwt, { secret: function (request, reply, callback) { // do something callback(null, 'supersecret') } }) fastify.post('/sign', function (request, reply) { reply.jwtSign(request.body.payload, function (err, token) { return reply.send(err || { 'token': token }) }) }) fastify.get('/verify', function (request, reply) { request.jwtVerify(function (err, decoded) { return reply.send(err || decoded) }) }) fastify.listen({ port: 3000 }, function (err) { if (err) fastify.log.error(err) fastify.log.info(`Server live on port: ${fastify.server.address().port}`) // sign payload and get JWT request({ method: 'POST', headers: { 'Content-Type': 'application/json' }, body: { payload: { foo: 'bar' } }, uri: `http://localhost:${fastify.server.address().port}/sign`, json: true }, function (err, response, body) { if (err) fastify.log.error(err) fastify.log.info(`JWT token is ${body.token}`) // verify JWT request({ method: 'GET', headers: { 'Content-Type': 'application/json', authorization: 'Bearer ' + body.token }, uri: 'http://localhost:' + fastify.server.address().port + '/verify', json: true }, function (err, response, body) { if (err) fastify.log.error(err) fastify.log.info(`JWT verified. Foo is ${body.foo}`) }) }) }) ``` -------------------------------- ### Basic Fastify JWT Setup Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/README.md Registers the @fastify/jwt plugin and sets up basic sign and verify endpoints for JWT authentication. ```javascript const fastify = require('fastify')() const jwt = require('@fastify/jwt') // Register plugin fastify.register(jwt, { secret: 'supersecret' }) // Sign endpoint fastify.post('/login', async (request, reply) => { const token = await reply.jwtSign({ userId: 123 }) reply.send({ token }) }) // Protected endpoint fastify.addHook('onRequest', async (request, reply) => { try { await request.jwtVerify() } catch (err) { reply.status(401).send(err) } }) fastify.get('/protected', (request, reply) => { reply.send({ user: request.user }) }) fastify.listen({ port: 3000 }) ``` -------------------------------- ### Install @fastify/jwt Source: https://github.com/fastify/fastify-jwt/blob/main/README.md Install the @fastify/jwt package using npm. This is the first step to integrate JWT functionality into your Fastify application. ```bash npm i @fastify/jwt ``` -------------------------------- ### Registering JWT Plugin with Unique Namespaces Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/errors.md This example demonstrates the correct way to register multiple JWT plugins by assigning unique namespaces to avoid conflicts. ```javascript fastify.register(jwt, { secret: 'secret1', namespace: 'auth' }) fastify.register(jwt, { secret: 'secret2', namespace: 'api' }) ``` -------------------------------- ### Complete Namespace Example with Multiple Handlers Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/api-reference/namespaces-and-patterns.md Demonstrates registering and using multiple JWT handlers for different purposes (user authentication, API keys, service-to-service communication) with custom configurations and endpoints. ```javascript const fastify = require('fastify')() const jwt = require('@fastify/jwt') // User authentication handler fastify.register(jwt, { secret: 'user-secret', namespace: 'auth', jwtSign: 'signUserToken', jwtVerify: 'verifyUserToken', sign: { expiresIn: '7d' }, verify: { maxAge: '30d' } }) // API key handler fastify.register(jwt, { secret: 'api-secret', namespace: 'api', jwtSign: 'signApiKey', jwtVerify: 'verifyApiKey', sign: { expiresIn: '365d' } }) // Service-to-service handler fastify.register(jwt, { secret: 'service-secret', namespace: 'service', jwtSign: 'signServiceToken', jwtVerify: 'verifyServiceToken' }) // User login endpoint fastify.post('/auth/login', async (request, reply) => { const userToken = await reply.signUserToken({ userId: request.body.userId, type: 'user' }) reply.send({ token: userToken }) }) // API key generation fastify.post('/api/keys/generate', async (request, reply) => { const apiKey = await reply.signApiKey({ appId: request.body.appId, type: 'api' }) reply.send({ key: apiKey }) }) // Verify user endpoint fastify.get('/auth/verify', async (request, reply) => { const decoded = await request.verifyUserToken() reply.send({ verified: true, payload: decoded }) }) // Verify API key endpoint fastify.get('/api/verify', async (request, reply) => { const decoded = await request.verifyApiKey() reply.send({ verified: true, payload: decoded }) }) ``` -------------------------------- ### JWT Decoding Example Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/api-reference/plugin-factory.md Example of decoding a JWT directly using the request.jwtDecode() decorator without necessarily verifying its signature. ```javascript const decoded = await request.jwtDecode(); ``` -------------------------------- ### Fastify JWT Setup with RSA Keys Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/README.md Configures @fastify/jwt to use RSA keys for signing and verification, specifying the private and public key file paths. ```javascript const { readFileSync } = require('node:fs') const path = require('node:path') fastify.register(jwt, { secret: { private: readFileSync(path.join(__dirname, 'private.key'), 'utf8'), public: readFileSync(path.join(__dirname, 'public.key'), 'utf8') }, sign: { algorithm: 'RS256' } }) ``` -------------------------------- ### JWT Verification Example Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/api-reference/plugin-factory.md Example of verifying a JWT using the request.jwtVerify() decorator, typically used in an onRequest hook to authenticate requests. ```javascript server.get('/protected', { onRequest: [server.authenticate] }, async (request, reply) => { // Access decoded user payload via request.user (or custom decoratorName) reply.send(request.user); }); ``` -------------------------------- ### Dual Token Setup with Access and Refresh Tokens Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/api-reference/namespaces-and-patterns.md Configure Fastify JWT to manage both access and refresh tokens using different secrets and namespaces. This setup allows for short-lived access tokens and longer-lived refresh tokens. ```javascript fastify.register(jwt, { secret: { private: privateKey, public: publicKey }, sign: { algorithm: 'RS256' }, namespace: 'access', jwtSign: 'signAccessToken', jwtVerify: 'verifyAccessToken', decoratorName: 'user' }) fastify.register(jwt, { secret: refreshSecret, namespace: 'refresh', jwtSign: 'signRefreshToken', jwtVerify: 'verifyRefreshToken' }) fastify.post('/login', async (request, reply) => { const userId = request.body.userId const accessToken = await reply.signAccessToken( { userId, type: 'access' }, { expiresIn: '15m' } ) const refreshToken = await reply.signRefreshToken( { userId, type: 'refresh' }, { expiresIn: '7d' } ) reply.setCookie('refresh_token', refreshToken, { httpOnly: true, secure: true, sameSite: 'strict', maxAge: 7 * 24 * 60 * 60 * 1000 }) reply.send({ accessToken }) }) fastify.post('/refresh', async (request, reply) => { try { // Verify refresh token from cookie await request.verifyRefreshToken({ verify: { onlyCookie: true } }) const userId = request.user.userId const newAccessToken = await reply.signAccessToken( { userId, type: 'access' }, { expiresIn: '15m' } ) reply.send({ accessToken: newAccessToken }) } catch (err) { reply.status(401).send({ error: 'Invalid refresh token' }) } }) fastify.addHook('onRequest', async (request, reply) => { // Only verify access token for protected routes if (!request.url.startsWith('/refresh') && !request.url.startsWith('/login')) { try { await request.verifyAccessToken() } catch (err) { reply.status(401).send(err) } } }) ``` -------------------------------- ### Complete Fastify JWT Import and Usage Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/api-reference/module-exports.md Demonstrates a full example of importing Fastify and JWT, configuring JWT options, registering the plugin, and using JWT signing and verification within a route. Includes custom type declarations for the JWT payload and user. ```typescript import Fastify from 'fastify' import jwt, { fastifyJwt } from '@fastify/jwt' import type { FastifyJWTOptions, JWT, SignPayloadType, UserType } from '@fastify/jwt' // Custom types declare module '@fastify/jwt' { interface FastifyJWT { payload: { userId: number; email: string } user: { id: number; email: string } } } const fastify = Fastify() const options: FastifyJWTOptions = { secret: 'secret', sign: { expiresIn: '7d' } } fastify.register(jwt, options) fastify.get('/test', async (request, reply) => { // All types are properly inferred const token: string = await reply.jwtSign({ userId: 1, email: 'user@example.com' }) await request.jwtVerify() const user: UserType = request.user // Properly typed reply.send({ user, token }) }) ``` -------------------------------- ### Registering JWT Plugin with RSA Algorithm Using Key Pair Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/errors.md This example shows the correct way to register the JWT plugin with an RSA algorithm by providing a secret object containing both private and public keys. ```javascript fastify.register(jwt, { secret: { private: privateKeyString, public: publicKeyString }, sign: { algorithm: 'RS256' } }) ``` -------------------------------- ### Key Rotation Management Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/api-reference/namespaces-and-patterns.md Implement a key rotation strategy using a manager class to handle multiple keys and rotate the active key. This example shows adding keys, rotating, and resolving them. ```javascript class KeyRotationManager { constructor() { this.currentKeyId = 'key-v1' this.keys = new Map() } addKey(id, secret) { this.keys.set(id, secret) } rotateKey() { const version = parseInt(this.currentKeyId.split('-v')[1]) + 1 this.currentKeyId = `key-v${version}` } async resolveKey(keyId) { return this.keys.get(keyId) } } const keyManager = new KeyRotationManager() keyManager.addKey('key-v1', 'secret-1') fastify.register(jwt, { secret: async (request, tokenOrHeader) => { const keyId = tokenOrHeader.kid const key = await keyManager.resolveKey(keyId) if (!key) { throw new Error('Key not found') } return key } }) // In your rotation scheduled task // keyManager.addKey('key-v2', 'secret-2') // keyManager.rotateKey() ``` -------------------------------- ### Basic Cookie-Based JWT Authentication Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/api-reference/namespaces-and-patterns.md Set up JWT authentication using cookies for storage. This example demonstrates logging in, setting an unsigned cookie, and verifying tokens on incoming requests. ```javascript const fastify = require('fastify')() const jwt = require('@fastify/jwt') fastify.register(require('@fastify/cookie')) fastify.register(jwt, { secret: 'secret', cookie: { cookieName: 'access_token', signed: false } }) fastify.post('/login', async (request, reply) => { const token = await reply.jwtSign({ userId: request.body.userId }) reply.setCookie('access_token', token, { httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'strict', maxAge: 7 * 24 * 60 * 60 * 1000 // 7 days }) reply.send({ message: 'Logged in' }) }) fastify.addHook('onRequest', async (request, reply) => { try { await request.jwtVerify() } catch (err) { reply.status(401).send(err) } }) fastify.get('/profile', (request, reply) => { reply.send({ user: request.user }) }) ``` -------------------------------- ### Register @fastify/jwt Plugin and Sign JWT Source: https://github.com/fastify/fastify-jwt/blob/main/README.md Register the @fastify/jwt plugin with Fastify, providing a secret key. This example demonstrates how to sign a JWT and send it as a response. ```javascript const fastify = require('fastify')() fastify.register(require('@fastify/jwt'), { secret: 'supersecret' }) fastify.post('/signup', (req, reply) => { // some code const token = fastify.jwt.sign({ payload }) reply.send({ token }) }) fastify.listen({ port: 3000 }, err => { if (err) throw err }) ``` -------------------------------- ### Fastify JWT Registration Examples Source: https://github.com/fastify/fastify-jwt/blob/main/README.md Demonstrates various ways to register the fastify-jwt plugin with different secret configurations, including string secrets, function-based secrets, and object-based secrets with RSA or ECDSA keys. It also shows how to configure verify-only mode. ```APIDOC ## Fastify JWT Registration Examples ### Description This section provides examples of how to register the `@fastify/jwt` plugin with different secret configurations. It covers using string secrets, function-based secrets (sync and async), and object-based secrets with RSA and ECDSA keys. It also illustrates the "verify-only" mode where only a public key is provided. ### Method `fastify.register(jwt, options)` ### Endpoint N/A (Plugin Registration) ### Parameters #### Request Body (Options for `fastify.register`) - **secret** (string | function | object) - The secret key or a function to retrieve it. Can be a string, a function returning a string/promise, or an object containing `private` and `public` keys for asymmetric cryptography. - **sign** (object) - Options for signing JWTs (e.g., algorithm, issuer). ### Request Example ```javascript const fastify = require('fastify')() const jwt = require('@fastify/jwt') // Secret as a string fastify.register(jwt, { secret: 'supersecret' }) // Secret as a function with callback fastify.register(jwt, { secret: function (request, token, callback) { callback(null, 'supersecret') } }) // Secret as an object of RSA keys (verify-only mode) fastify.register(jwt, { secret: { public: process.env.JWT_ISSUER_PUBKEY } }) ``` ### Response N/A (Plugin Registration) ``` -------------------------------- ### Combining Multiple Authorization Guards Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/api-reference/namespaces-and-patterns.md Implement a comprehensive authorization strategy by chaining multiple checks within the `trusted` option. This example demonstrates checking token blacklisting, user activity, subscription status, and IP whitelisting. ```javascript fastify.register(jwt, { secret: 'secret', trusted: async (request, decodedToken) => { // Check 1: Is token blacklisted? const isBlacklisted = await tokenBlacklist.has(decodedToken.jti) if (isBlacklisted) return false // Check 2: Is user still active? const user = await db.users.findById(decodedToken.userId) if (!user || !user.isActive) return false // Check 3: Has subscription expired? if (user.subscriptionEndsAt < Date.now()) return false // Check 4: IP whitelist if (user.ipWhitelist && !user.ipWhitelist.includes(request.ip)) { return false } return decodedToken // All checks passed } }) ``` -------------------------------- ### JWT Decoding (Complete Structure) Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/README.md Demonstrates decoding a JWT token to get the complete structure, including header, payload, and signature. ```javascript // Get complete structure const complete = fastify.jwt.decode(token, { complete: true }) // { header: {...}, payload: {...}, signature: '...' } ``` -------------------------------- ### Configure RSA Certificates without Passphrase Source: https://github.com/fastify/fastify-jwt/blob/main/example/UsingCertificates.md Generates a 2048-bit RSA key pair and registers it in Fastify using the RS256 algorithm. This setup assumes the private key is not encrypted with a passphrase. ```shell openssl genrsa -out private.key 2048 openssl rsa -in private.key -out public.key -outform PEM -pubout ``` ```javascript const { readFileSync } = require('node:fs') const fastify = require('fastify')() const jwt = require('@fastify/jwt') fastify.register(jwt, { secret: { private: readFileSync('path/to/private.key', 'utf8'), public: readFileSync('path/to/public.key', 'utf8') }, sign: { algorithm: 'RS256' } }) ``` -------------------------------- ### FastifyJwtNamespace Type Example Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/types.md Illustrates how to use the FastifyJwtNamespace helper type for typing multiple JWT namespaces within a Fastify instance. This allows for distinct JWT configurations and operations. ```typescript declare module 'fastify' { interface FastifyInstance extends FastifyJwtNamespace<{ namespace: 'security' }> {} } // Now fastify.securityJwtVerify, fastify.securityJwtSign, etc. are typed ``` -------------------------------- ### GET /verify Source: https://github.com/fastify/fastify-jwt/blob/main/README.md Verifies a JWT token provided in the Authorization header or cookie. ```APIDOC ## GET /verify ### Description Verifies the JWT token provided in the request. It supports verification via the Authorization header or cookies if configured. ### Method GET ### Endpoint /verify ### Parameters #### Headers - **Authorization** (string) - Required - Format: 'Bearer ' ### Response #### Success Response (200) - **decoded** (Object) - The decoded payload of the verified JWT. #### Response Example { "foo": "bar", "iat": 1620000000 } ``` -------------------------------- ### Integrate JWT Verification with @fastify/auth Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/api-reference/common-patterns.md Combine Fastify JWT verification with @fastify/auth to create protected routes. This example demonstrates how to verify a JWT and then check for specific user roles. ```javascript const fastify = require('fastify')() const auth = require('@fastify/auth') const jwt = require('@fastify/jwt') fastify.register(jwt, { secret: 'secret' }) fastify.register(auth) // Verify JWT const verifyJWT = async (request, reply) => { await request.jwtVerify() } // Check admin role const checkAdmin = async (request, reply) => { if (!request.user.roles?.includes('admin')) { throw new Error('Admin role required') } } fastify.post('/admin-action', {onRequest: fastify.auth([verifyJWT, checkAdmin]) }, async (request, reply) => { reply.send({ action: 'completed' }) } ) ``` -------------------------------- ### JWT Verification and Usage with Fastify Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/api-reference/request-reply-methods.md Demonstrates global and route-specific JWT verification using Fastify's onRequest hook and route handlers. Includes examples for Promise-based and callback-based verification, custom verification options, and handling refresh tokens. ```javascript const fastify = require('fastify')() const jwt = require('@fastify/jwt') fastify.register(jwt, { secret: 'supersecret' }) // Global verification hook fastify.addHook('onRequest', async (request, reply) => { try { await request.jwtVerify() } catch (err) { reply.status(401).send(err) } }) // Verify specific route with Promise fastify.get('/protected', async (request, reply) => { await request.jwtVerify() reply.send({ message: 'Access granted', user: request.user }) }) // Verify with custom options fastify.get('/verify-custom', async (request, reply) => { const decoded = await request.jwtVerify({ verify: { algorithms: ['HS256'] } }) reply.send(decoded) }) // Verify with callback fastify.get('/verify-callback', (request, reply) => { request.jwtVerify((err, decoded) => { if (err) reply.status(401).send(err) else reply.send({ verified: true, user: request.user }) }) }) // Only verify cookie (for refresh token patterns) fastify.post('/refresh', async (request, reply) => { const refreshPayload = await request.jwtVerify({ verify: { onlyCookie: true } }) const newToken = await reply.jwtSign({ userId: refreshPayload.userId }) reply.send({ token: newToken }) }) ``` -------------------------------- ### JWT Authentication with Cookies Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/api-reference/common-patterns.md Configure @fastify/jwt to use cookies for storing and retrieving JWTs. This example shows how to set up JWT signing and cookie handling for a login endpoint. ```javascript const fastify = require('fastify')() const cookie = require('@fastify/cookie') const jwt = require('@fastify/jwt') fastify.register(cookie) fastify.register(jwt, { secret: 'secret', cookie: { cookieName: 'access_token', signed: true } }) fastify.post('/login', async (request, reply) => { const token = await reply.jwtSign({ userId: 1 }) reply.setCookie('access_token', token, { httpOnly: true, secure: true, sameSite: 'strict' }) reply.send({ message: 'Logged in' }) }) ``` -------------------------------- ### Activity Logging Decorator Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/api-reference/common-patterns.md Implement a decorator `logActivity` to record user actions after JWT verification. This example logs request details and uses an `onResponse` hook to update activity status. ```javascript fastify.decorate('logActivity', async (request, reply) => { await request.jwtVerify() const activity = { userId: request.user.id, method: request.method, path: request.url, timestamp: new Date(), ip: request.ip } await db.activities.create(activity) }) fastify.addHook('onResponse', async (request, reply) => { if (request.user) { // User is authenticated, log the activity await db.activities.update(request.user.id, { statusCode: reply.statusCode, responseTime: reply.getResponseTime() }) } }) ``` -------------------------------- ### FastifyJWT Module Augmentation Example Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/types.md Demonstrates how to extend the FastifyJWT interface to customize payload and user types for type safety. This is useful for defining custom claims and user information. ```typescript import '@fastify/jwt' declare module '@fastify/jwt' { interface FastifyJWT { payload: { userId: number email: string roles: string[] } user: { id: number email: string roles: string[] } } } // Now SignPayloadType and UserType are automatically typed with the above ``` -------------------------------- ### Fastify JWT Authentication Setup Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/api-reference/request-reply-methods.md Registers the @fastify/jwt plugin with a secret and a custom user format function. An onRequest hook is added to verify JWTs on incoming requests. ```javascript const fastify = require('fastify')() const jwt = require('@fastify/jwt') fastify.register(jwt, { secret: 'supersecret', formatUser: (payload) => ({ id: payload.userId, email: payload.email, role: payload.role || 'user' }) }) fastify.addHook('onRequest', async (request) => { try { await request.jwtVerify() } catch (err) { // User not set if verification fails } }) fastify.get('/profile', (request, reply) => { if (!request.user) { return reply.status(401).send({ error: 'Not authenticated' }) } reply.send({ profile: { id: request.user.id, email: request.user.email, role: request.user.role } }) }) ``` -------------------------------- ### Custom Rate Limiting per User Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/api-reference/common-patterns.md Create a custom decorator `checkRateLimit` that verifies JWT and enforces rate limits based on user ID. This example limits requests to 100 per minute per user. ```javascript const userRequestCounts = new Map() fastify.decorate('checkRateLimit', async (request, reply) => { await request.jwtVerify() const userId = request.user.id const now = Date.now() const count = userRequestCounts.get(userId) || [] // Remove old requests (older than 1 minute) const recent = count.filter(time => now - time < 60000) if (recent.length > 100) { return reply.status(429).send({ error: 'Rate limit exceeded' }) } recent.push(now) userRequestCounts.set(userId, recent) }) fastify.get('/api/data', { onRequest: [fastify.checkRateLimit] }, (request, reply) => { reply.send({ data: 'secret' }) } ) ``` -------------------------------- ### Configure Fastify JWT Options Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/api-reference/jwt-decorator.md Illustrates how to register the JWT plugin with custom `sign` and `verify` options, and how to access and modify these options. ```javascript const fastify = require('fastify')() const jwt = require('@fastify/jwt') fastify.register(jwt, { secret: 'supersecret', sign: { algorithm: 'HS256', expiresIn: '7d', iss: 'api.example.com' }, verify: { allowedIss: 'api.example.com', algorithms: ['HS256'] } }) fastify.get('/options', (request, reply) => { // Access registered options const options = fastify.jwt.options console.log('Sign algorithm:', options.sign.algorithm) console.log('Verify maxAge:', options.verify.maxAge) // Clone and modify options const modifiedVerify = Object.assign({}, options.verify) modifiedVerify.allowedAud = 'custom-audience' reply.send({ originalOptions: options, modified: modifiedVerify }) }) ``` -------------------------------- ### GET Request Without Authorization Header Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/errors.md This scenario triggers an error when no 'Authorization' header is present, and no cookie or custom token extraction is configured. ```javascript GET /api/data // No Authorization header, no cookie, no custom extractor // Error: No Authorization was found in request.headers ``` -------------------------------- ### Reply Decorator for Namespaced JWT Signing Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/api-reference/module-exports.md An optional namespaced signing method is created when the 'namespace' option is provided. Examples include 'reply.authJwtSign()' or 'reply.apiJwtSign()'. ```typescript created when: namespace option is provided example names: authJwtSign, apiJwtSign, customJwtSign ``` -------------------------------- ### JWT Verification with Options Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/README.md Illustrates verifying a JWT token with specific options, such as allowed algorithms and maximum token age. ```javascript // With options const decoded = fastify.jwt.verify(token, { algorithms: ['HS256'], maxAge: '7d' }) ``` -------------------------------- ### Request Decorator for Namespaced JWT Decode Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/api-reference/module-exports.md An optional namespaced decode method is created when the 'namespace' option is provided. Examples include 'request.authJwtDecode()' or 'request.apiJwtDecode()'. ```typescript created when: namespace option is provided example names: authJwtDecode, apiJwtDecode, customJwtDecode ``` -------------------------------- ### Request Decorator for Namespaced JWT Verification Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/api-reference/module-exports.md An optional namespaced verification method is created when the 'namespace' option is provided. Examples include 'request.authJwtVerify()' or 'request.apiJwtVerify()'. ```typescript created when: namespace option is provided example names: authJwtVerify, apiJwtVerify, customJwtVerify ``` -------------------------------- ### Sign and Verify JWT Tokens Source: https://github.com/fastify/fastify-jwt/blob/main/README.md Demonstrates how to sign a payload to generate a token and verify it using both synchronous and asynchronous approaches. ```javascript const token = fastify.jwt.sign({ foo: 'bar' }) // synchronously const decoded = fastify.jwt.verify(token) // asynchronously fastify.jwt.verify(token, (err, decoded) => { if (err) fastify.log.error(err) fastify.log.info(`Token verified. Foo is ${decoded.foo}`) }) ``` -------------------------------- ### Verify JWT Token with Options Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/api-reference/jwt-decorator.md Demonstrates JWT verification with specific options, such as allowed algorithms and maximum token age, using fastify.jwt.verify. ```javascript const decoded = fastify.jwt.verify(token, { algorithms: ['HS256'], maxAge: '7d' }) ``` -------------------------------- ### Configure JWT with Cookies in Fastify Source: https://github.com/fastify/fastify-jwt/blob/main/README.md Demonstrates how to register the JWT plugin with cookie support and set secure cookies for token storage. It includes setting up the cookie plugin and verifying tokens via the onRequest hook. ```javascript const fastify = require('fastify')() const jwt = require('@fastify/jwt') fastify.register(jwt, { secret: 'foobar', cookie: { cookieName: 'token', signed: false } }) fastify.register(require('@fastify/cookie')) fastify.get('/cookies', async (request, reply) => { const token = await reply.jwtSign({ name: 'foo', role: ['admin', 'spy'] }) reply .setCookie('token', token, { domain: 'your.domain', path: '/', secure: true, httpOnly: true, sameSite: true }) .code(200) .send('Cookie sent') }) fastify.addHook('onRequest', (request) => request.jwtVerify()) fastify.get('/verifycookie', (request, reply) => { reply.send({ code: 'OK', message: 'it works!' }) }) fastify.listen({ port: 3000 }, err => { if (err) throw err }) ``` -------------------------------- ### Configure RSA Certificates with Passphrase Source: https://github.com/fastify/fastify-jwt/blob/main/example/UsingCertificates.md Generates a 2048-bit RSA key pair encrypted with a passphrase and registers it in Fastify. The configuration object requires a passphrase property alongside the private key string. ```shell openssl genrsa -des3 -out private.pem 2048 openssl rsa -in private.pem -outform PEM -pubout -out public.pem ``` ```javascript const { readFileSync } = require('node:fs') const fastify = require('fastify')() const jwt = require('@fastify/jwt') fastify.register(jwt, { secret: { private: { key: readFileSync('path/to/private.pem', 'utf8'), passphrase: 'super secret passphrase' }, public: readFileSync('path/to/public.pem', 'utf8') }, sign: { algorithm: 'RS256' } }) ``` -------------------------------- ### Register JWT with Specific Signing Algorithm Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/README.md Registers the JWT plugin and specifies the signing algorithm to be used, for example, 'RS256' for RSA signatures. This is crucial when working with asymmetric keys. ```javascript fastify.register(jwt, { secret: keys, sign: { algorithm: 'RS256' } // Specify algorithm }) ``` -------------------------------- ### Package.json Exports Configuration Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/api-reference/module-exports.md Configuration within 'package.json' specifying the main entry point and type definitions for the Fastify JWT package. ```json { "main": "index.js", "types": "types/index.d.ts", "type": "commonjs" } ``` -------------------------------- ### Basic Usage: Plugin Registration and JWT Signing Source: https://github.com/fastify/fastify-jwt/blob/main/README.md Register the @fastify/jwt plugin with a secret and demonstrate how to sign a JWT. ```APIDOC ## Usage Register as a plugin. This will decorate your `fastify` instance with the following methods: `decode`, `sign`, and `verify`; refer to their documentation to find out how to use the utilities. It will also register `request.jwtVerify` and `reply.jwtSign`. You must pass a `secret` when registering the plugin. ```js const fastify = require('fastify')() fastify.register(require('@fastify/jwt'), { secret: 'supersecret' }) fastify.post('/signup', (req, reply) => { // some code const token = fastify.jwt.sign({ payload }) reply.send({ token }) }) fastify.listen({ port: 3000 }, err => { if (err) throw err }) ``` ``` -------------------------------- ### Access and Manage JWT Options Source: https://github.com/fastify/fastify-jwt/blob/main/README.md Illustrates how to register the JWT plugin with specific configurations and access or modify those options at runtime via fastify.jwt.options. ```javascript const { readFileSync } = require('node:fs') const path = require('node:path') const fastify = require('fastify')() const jwt = require('@fastify/jwt') fastify.register(jwt, { secret: { private: readFileSync(`${path.join(__dirname, 'certs')}/private.key`), public: readFileSync(`${path.join(__dirname, 'certs')}/public.key`) }, sign: { algorithm: 'RS256', aud: 'foo', iss: 'example.tld' }, verify: { allowedAud: 'foo', allowedIss: 'example.tld', } }) fastify.get('/', (request, reply) => { const globalOptions = fastify.jwt.options let modifiedVerifyOptions = Object.assign({}, fastify.jwt.options.verify) modifiedVerifyOptions.allowedAud = 'bar' modifiedVerifyOptions.allowedSub = 'test' return { globalOptions, modifiedVerifyOptions } }) ``` -------------------------------- ### Attribute-Based Access Control (ABAC) - Own Profile Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/api-reference/common-patterns.md Implement ABAC by defining a policy function that checks attributes for access control. This example demonstrates checking if a user can edit their own profile. ```javascript fastify.register(jwt, { secret: 'secret' }) fastify.decorate('authorize', (policy) => { return async (request, reply) => { await request.jwtVerify() const allowed = await policy(request, request.user) if (!allowed) { return reply.status(403).send({ error: 'Forbidden' }) } } }) // Policy: Only can edit own profile const canEditProfile = (request, user) => { return user.id === parseInt(request.params.userId) } fastify.patch('/users/:userId', {onRequest: [fastify.authorize(canEditProfile)] }, async (request, reply) => { // Update user profile } ) ``` -------------------------------- ### Testing JWT Protected Routes Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/api-reference/common-patterns.md Demonstrates how to test routes protected by JWT authentication using Fastify's `inject` method. It covers scenarios with no token, a valid token, and an invalid token. ```javascript const test = require('node:test') const assert = require('node:assert') const fastify = require('fastify')() const jwt = require('@fastify/jwt') fastify.register(jwt, { secret: 'test-secret' }) fastify.get('/protected', { onRequest: [fastify.authenticate] }, (request, reply) => { reply.send({ user: request.user }) } ) test('protected route requires valid token', async () => { // No token const response1 = await fastify.inject({ method: 'GET', url: '/protected' }) assert.strictEqual(response1.statusCode, 401) // Valid token const token = fastify.jwt.sign({ userId: 1 }) const response2 = await fastify.inject({ method: 'GET', url: '/protected', headers: { authorization: `Bearer ${token}` } }) assert.strictEqual(response2.statusCode, 200) // Invalid token const response3 = await fastify.inject({ method: 'GET', url: '/protected', headers: { authorization: 'Bearer invalid' } }) assert.strictEqual(response3.statusCode, 401) }) ``` -------------------------------- ### Attribute-Based Access Control (ABAC) - Database Lookup Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/api-reference/common-patterns.md An ABAC policy example involving a database lookup to determine access rights. This policy checks if the user is the post author or an admin. ```javascript fastify.register(jwt, { secret: 'secret' }) fastify.decorate('authorize', (policy) => { return async (request, reply) => { await request.jwtVerify() const allowed = await policy(request, request.user) if (!allowed) { return reply.status(403).send({ error: 'Forbidden' }) } } }) // Policy with database lookup const canDeletePost = async (request, user) => { const post = await db.posts.findById(request.params.postId) return post.authorId === user.id || user.roles.includes('admin') } fastify.delete('/posts/:postId', {onRequest: [fastify.authorize(canDeletePost)] }, async (request, reply) => { // Delete post } ) ``` -------------------------------- ### Fastify JWT with TypeScript Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/README.md Demonstrates setting up @fastify/jwt in a TypeScript Fastify application, including payload type augmentation and token signing. ```typescript import Fastify from 'fastify' import jwt, { FastifyJWTOptions } from '@fastify/jwt' declare module '@fastify/jwt' { interface FastifyJWT { payload: { userId: number; email: string } user: { id: number; email: string } } } const fastify = Fastify() fastify.register(jwt, { secret: 'secret', sign: { expiresIn: '7d' } } as FastifyJWTOptions) fastify.get('/test', async (request, reply) => { const token = await reply.jwtSign({ userId: 1, email: 'user@example.com' }) return { token } }) ``` -------------------------------- ### Handling Incorrect Authorization Header Format Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/errors.md Requests with an Authorization header that does not start with 'Bearer ' or has too many parts will result in a 'Format is Authorization: Bearer [token]' error. Ensure the header follows the correct format. ```javascript // Missing Bearer prefix GET /api/data Authorization: MyToken abc123def456 // Error: Format is Authorization: Bearer [token] // Too many parts Authorization: Bearer token extra-part // Error: Format is Authorization: Bearer [token] ``` -------------------------------- ### Create Authentication Plugin for Route Protection Source: https://github.com/fastify/fastify-jwt/blob/main/README.md Create a reusable Fastify plugin that encapsulates JWT authentication logic. This plugin can then be used to protect specific routes. ```javascript const fp = require("fastify-plugin") module.exports = fp(async function(fastify, opts) { fastify.register(require("@fastify/jwt"), { secret: "supersecret" }) fastify.decorate("authenticate", async function(request, reply) { try { await request.jwtVerify() } catch (err) { reply.send(err) } }) }) ``` -------------------------------- ### JWT Signing with Options Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/README.md Illustrates signing a JWT payload with additional options, such as expiration time and signing algorithm. ```javascript // With options const token = fastify.jwt.sign( { userId: 1 }, { expiresIn: '7d', algorithm: 'RS256' } ) ``` -------------------------------- ### Configure Fastify JWT with Different Secret Types Source: https://github.com/fastify/fastify-jwt/blob/main/README.md Demonstrates registering fastify-jwt with various secret configurations, including string secrets, callback functions, promises, async functions, RSA/ECDSA key pairs, and verify-only mode with a public key. This covers different authentication strategies and key management approaches. ```javascript const { readFileSync } = require('node:fs') const path = require('node:path') const fastify = require('fastify')() const jwt = require('@fastify/jwt') // secret as a string fastify.register(jwt, { secret: 'supersecret' }) // secret as a function with callback fastify.register(jwt, { secret: function (request, token, callback) { // do something callback(null, 'supersecret') } }) // secret as a function returning a promise fastify.register(jwt, { secret: function (request, token) { return Promise.resolve('supersecret') } }) // secret as an async function fastify.register(jwt, { secret: async function (request, token) { return 'supersecret' } }) // secret as an object of RSA keys (without passphrase) // the files are loaded as strings fastify.register(jwt, { secret: { private: readFileSync(`${path.join(__dirname, 'certs')}/private.key`, 'utf8'), public: readFileSync(`${path.join(__dirname, 'certs')}/public.key`, 'utf8') }, sign: { algorithm: 'RS256' } }) // secret as an object of P-256 ECDSA keys (with a passphrase) // the files are loaded as buffers fastify.register(jwt, { secret: { private: { key: readFileSync(`${path.join(__dirname, 'certs')}/private.pem`), passphrase: 'super secret passphrase' }, public: readFileSync(`${path.join(__dirname, 'certs')}/public.pem`) }, sign: { algorithm: 'ES256' } }) // secret as an object with RSA public key // fastify-jwt is configured in VERIFY-ONLY mode fastify.register(jwt, { secret: { public: process.env.JWT_ISSUER_PUBKEY } }) ``` -------------------------------- ### Decoding JWT without Verification in Fastify Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/api-reference/request-reply-methods.md Shows how to decode a JWT from a request without verifying its signature using `request.jwtDecode()`. Includes examples for Promise-based and callback-based decoding, decoding with complete token structure, and examining claims before verification. ```javascript const fastify = require('fastify')() const jwt = require('@fastify/jwt') fastify.register(jwt, { secret: 'supersecret' }) // Decode without verification fastify.post('/inspect-token', async (request, reply) => { try { const decoded = await request.jwtDecode() reply.send({ message: 'Token decoded (not verified)', payload: decoded }) } catch (err) { reply.status(400).send({ error: 'Invalid token format' }) } }) // Decode with complete token structure fastify.get('/token-info', async (request, reply) => { const decoded = await request.jwtDecode({ decode: { complete: true } }) reply.send({ header: decoded.header, payload: decoded.payload, signature: decoded.signature }) }) // Using callback fastify.post('/decode-callback', (request, reply) => { request.jwtDecode((err, decoded) => { if (err) reply.status(400).send(err) else reply.send({ decoded }) }) }) // Examine claims before verification fastify.get('/check-issuer', async (request, reply) => { const decoded = await request.jwtDecode() if (decoded.iss !== 'my-server') { return reply.status(401).send({ error: 'Invalid issuer' }) } // Now verify with issuer requirement const verified = await request.jwtVerify({ verify: { allowedIss: 'my-server' } }) reply.send(verified) }) ``` -------------------------------- ### Asynchronous JWT Signing with Callback Source: https://github.com/fastify/fastify-jwt/blob/main/_autodocs/README.md Demonstrates asynchronous JWT payload signing using a callback function to handle the resulting token or error. ```javascript // Asynchronous fastify.jwt.sign({ userId: 1 }, (err, token) => { if (err) console.error(err) else console.log(token) }) ```