Плагин REST-API JWT-Auth Fastify не работает как preHandler
Я настраиваю Fastify Rest-Api и написал плагин для инкапсуляции моей логики аутентификации, основанной на JWT. Я использую preHandler Hook на каждом маршруте, который я хочу защитить, но кажется, что preHandler или мой плагин просто игнорируются, так как я могу просто сделать запрос без токена и получить данные.
Я просмотрел каждую часть документации, но все еще не могу запустить ее. Если я просто console.log() моя функция fastify.authenticate, я получаю неопределенное.
Это мой плагин 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'})
Я зарегистрировал этот плагин, как это в моем основном файле server.js:
const customJwtAuth = require('./plugin/auth')
fastify.register(customJwtAuth).after(err => {if (err) throw err})
Затем я применяю свою функцию следующим образом:
const fastify = require('fastify')
const productHandler = require('../handler/productHandler')
const productRoutes = [
{
method: 'GET',
url: '/api/product',
preHandler: [fastify.authenticate],
handler: productHandler.getProducts
}, ... ]
API не должен возвращать какие-либо данные, если запрос не включает в себя подписанный JWT или вообще без JWT.
2 ответа
Вот вам рабочий пример.
Обратите внимание, что вы звонили next()
когда вы регистрировали декоратор, это неправильно.
Ваша главная ошибка произошла из-за [fastify.authenticate]
линии, потому что у вас нет декоратора в этом экземпляре fastify.
//### 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)
Ты получаешь:
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
Если вы используете версию 2 fastify, вы можете использовать PreHandler, если вам не нужен пользователь beforeHandler, а также вам нужно изменить маршруты для чего-то подобного
//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')
)