Categories
Fastify

Add Authentication to Our Fastify App with fastify-auth

Spread the love

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.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *