简体   繁体   中英

Fastify REST-API JWT-Auth Plugin not firing as preHandler

Im setting up a Fastify Rest-Api and wrote a Plugin to encapsulate my authentication logic which is based on JWT. Im using the preHandler Hook on each route that i want to protect but it seems that the preHandler or my plugin just gets ignored since i can just make a request without a token at all and get the data.

I looked up every piece of documentation but still cannot get it running. If i just console.log() my function fastify.authenticate i get an undefined.

This is my plugin customJwtAuth:

const fp = require('fastify-plugin')

async function customJwtAuth(fastify, opts, next) {

//register jwt 
 await fastify.register(require('fastify-jwt'),
    {secret: 'asecretthatsverylongandimportedfromanenvfile'})

fastify.decorate('authenticate', async function(request, reply) {
 try {
   const tokenFromRequest = request.cookies.jwt

  await fastify.jwt.verify(tokenFromRequest, (err, decoded) => {
     if (err) {
       fastify.log.error(err)
       reply.send(err)
    }
     fastify.log.info(`Token verified: ${decoded}`)
  })
  } catch (err) {
  reply.send(err)
  fastify.log.error(err)
  }
 })
next()
}

module.exports = fp(customJwtAuth, {fastify: '>=1.0.0'})

I register this plugin like this in my main server.js file:

  const customJwtAuth = require('./plugin/auth')
  fastify.register(customJwtAuth).after(err => {if (err) throw err})

Then i apply my function like this to the routes:

const fastify = require('fastify')
const productHandler = require('../handler/productHandler')

const productRoutes = [
  {
  method: 'GET',
  url: '/api/product',
  preHandler: [fastify.authenticate],
  handler: productHandler.getProducts
  }, ... ]

The api shouldnt return any Data if the request doesnt include a signed jwt or without a jwt at all.

here to you a working example.

Note that you were calling next() when you were registering the decorator that is wrong.

Your main error was due the [fastify.authenticate] line, because you don't have the decorator in that fastify instance.

//### customAuthJwt.js

const fastifyJwt = require('fastify-jwt')
const fp = require('fastify-plugin')

async function customJwtAuth(fastify, opts, next) {
  fastify.register(fastifyJwt, { secret: 'asecretthatsverylongandimportedfromanenvfile' })
  fastify.decorate('authenticate', async function (request, reply) {
    try {
      // to whatever you want, read the token from cookies for example..
      const token = request.headers.authorization
      await request.jwtVerify()
    } catch (err) {
      reply.send(err)
    }
  })
}

module.exports = fp(customJwtAuth, { fastify: '>=1.0.0' })

//### server.js
const fastify = require('fastify')({ logger: true })
const customJwtAuth = require('./customAuthJwt')

fastify.register(customJwtAuth)

fastify.get('/signup', (req, reply) => {
  // authenticate the user.. are valid the credentials?
  const token = fastify.jwt.sign({ hello: 'world' })
  reply.send({ token })
})


fastify.register(async function (fastify, opts) {
  fastify.addHook('onRequest', fastify.authenticate)
  fastify.get('/', async function (request) {
    return 'hi'
  })
})

fastify.listen(3000)

You get:

curl http://localhost:3000/
{"statusCode":401,"error":"Unauthorized","message":"No Authorization was found in request.headers"}

curl http://localhost:3000/signup
{"token": "eyJhbGciOiJIUzI1NiI..."}

curl 'http://localhost:3000/' -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiI...'
hi

if you're using version 2 of fastify you can use PreHandler, if not you need to user beforeHandler And also, you need to change the routes for something like this

//routes/products.js
const fastify = require('fastify')
const productHandler = require('../handler/productHandler')

module.exports = function (fastify, opts, next) {
    fastify.route({
     method: 'GET',
     url: 'api/product',
     beforeHandler: fastify.auth([
      fastify.authenticate
     ]),
     handler: productHandler.getProducts
    })
    ......
  next()
}

//server.js
....
fastify.register(require('fastify-auth'))
       .register(customJwtAuth)

const customJwtAuth = require('./customAuthJwt')

....
fastify.register(
 require('./routes/products')
)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM