With the fastify-auth library, we can add authentication to our Fastify app quickly.
In this article, we’ll look at how to use the library to add authentication to our Fastify app.
Install
We can install the library by running:
npm i fastify-auth
Add Authentication
We can add authentication to our app by writing:
const fastify = require('fastify')({
logger: true
})
fastify
.decorate('verifyJWTandLevel', (request, reply, done) => {
done()
})
.decorate('verifyUserAndPassword', (request, reply, done) => {
console.log(request, reply)
done()
})
.register(require('fastify-auth'))
.after(() => {
fastify.route({
method: 'POST',
url: '/auth-multiple',
preHandler: fastify.auth([
fastify.verifyJWTandLevel,
fastify.verifyUserAndPassword
]),
handler: (req, reply) => {
req.log.info('Auth route')
reply.send({ hello: 'world' })
}
})
})
fastify.get('/', function (request, reply) {
reply.send({ hello: 'world' })
})
fastify.listen(3000, '0.0.0.0', function (err, address) {
if (err) {
fastify.log.error(err)
process.exit(1)
}
fastify.log.info(`server listening on ${address}`)
})
We call decorate
to add our authentication handlers to our app.
The callback has the request
with the request data.
reply
lets us set the response.
done
is a function we call to call the next middleware.
If there’s an error, we pass in an Error
instance to the done
function.
We call the register
method to register the fasify-auth
plugin.
When we make a POST request to the auth-multiple
route, we see the request
and reply
logged.
The routes that are registered in the after
callback will have the auth handlers available.
They’re run since we set them to the preHandler
property to add the array of auth handlers to run.
The default relationship is an OR relationship.
If we want both handlers to be valid before running the route handler, then we write:
const fastify = require('fastify')({
logger: true
})
fastify
.decorate('verifyJWTandLevel', (request, reply, done) => {
console.log(request, reply)
done()
})
.decorate('verifyUserAndPassword', (request, reply, done) => {
console.log(request, reply)
done()
})
.register(require('fastify-auth'))
.after(() => {
fastify.route({
method: 'POST',
url: '/auth-multiple',
preHandler: fastify.auth([
fastify.verifyJWTandLevel,
fastify.verifyUserAndPassword
], {
relation: 'and'
}),
handler: (req, reply) => {
req.log.info('Auth route')
reply.send({ hello: 'world' })
}
})
})
fastify.get('/', function (request, reply) {
reply.send({ hello: 'world' })
})
fastify.listen(3000, '0.0.0.0', function (err, address) {
if (err) {
fastify.log.error(err)
process.exit(1)
}
fastify.log.info(`server listening on ${address}`)
})
Fastify-auth supports promises returned by the functions.
So we can use async
and await
in our auth handler callbacks:
const fastify = require('fastify')({
logger: true
})
fastify
.decorate('asyncVerifyJWTandLevel', async function (request, reply) {
console.log('asyncVerifyJWTandLevel');
await validation()
})
.decorate('asyncVerifyUserAndPassword', function (request, reply) {
console.log('asyncVerifyUserAndPassword');
return Promise.resolve()
})
.register(require('fastify-auth'))
.after(() => {
fastify.route({
method: 'POST',
url: '/auth-multiple',
preHandler: fastify.auth([
fastify.asyncVerifyJWTandLevel,
fastify.asyncVerifyUserAndPassword
]),
handler: (req, reply) => {
req.log.info('Auth route')
reply.send({ hello: 'world' })
}
})
})
fastify.get('/', function (request, reply) {
reply.send({ hello: 'world' })
})
fastify.listen(3000, '0.0.0.0', function (err, address) {
if (err) {
fastify.log.error(err)
process.exit(1)
}
fastify.log.info(`server listening on ${address}`)
})
We use async
and await
with the asyncVerifyJWTandLevel
handler.
And we return a promise within the asyncVerifyUserAndPassword
handler.
Conclusion
We can add our own auth logic easily to our Fastify app with the fastify-auth plugin.