fastify-jwt icon indicating copy to clipboard operation
fastify-jwt copied to clipboard

feat: add `validateDecoded` option for JWT payload validation

Open williamfds opened this issue 7 months ago • 0 comments

This PR introduces a new validateDecoded option to the @fastify/jwt plugin.

It allows developers to define custom validation logic that runs after the JWT is decoded and verified, but before assigning request.user. This enables scenarios where claims alone are insufficient, such as:

  • Checking flags (e.g., isVerified)

  • Validating roles or permissions

  • Applying business rules or JSON Schema validation

  • Performing async checks (e.g., database lookups)

Example: synchronous usage

fastify.register(jwt, {
  secret: 'supersecret',
  validateDecoded: (payload) => {
    if (!payload.admin) {
      throw new Error('Not authorized')
    }
  }
})

Example: asynchronous usage

fastify.register(jwt, {
 secret: 'supersecret',
 validateDecoded: async (payload) => {
   const isAllowed = await someCheck(payload.userId)
   if (!isAllowed) {
     throw new Error('Blocked by validation')
   }
 }
})

Implementation notes

This change includes the following:

  • Adds validateDecoded(payload) support to plugin options

  • Executed after token verification in request.jwtVerify()

  • If validation fails, responds with 400 Bad Request

  • Includes test coverage for both sync and async cases

  • Type definitions updated (types/jwt.d.ts)

  • Documentation updated in README.md

Related

  • Closes #316

Checklist

williamfds avatar May 29 '25 00:05 williamfds