@fastify/passport

Passport Strategies in Fastify

@fastify/passport

The @fastify/passport plugin brings the entire Passport strategy ecosystem to Fastify, layered on top of @fastify/session.

4 min read Level 3/5 #fastify#passport#oauth
What you'll learn
  • Install @fastify/passport with session support
  • Configure a strategy such as local or Google OAuth
  • Protect routes with passport.authenticate

Passport has hundreds of authentication strategies — Local, Google, GitHub, SAML, OIDC. @fastify/passport lets you use them with Fastify’s plugin model and sessions.

Install

npm install @fastify/passport @fastify/session @fastify/cookie passport-local

Initialise

import fastifyPassport from '@fastify/passport'
import { Strategy as LocalStrategy } from 'passport-local'

await app.register(fastifyPassport.initialize())
await app.register(fastifyPassport.secureSession())

fastifyPassport.use(
  'local',
  new LocalStrategy(async (email, password, done) => {
    const user = await app.db.user.findUnique({ where: { email } })
    if (!user || !(await verify(user.passwordHash, password))) {
      return done(null, false)
    }
    done(null, user)
  }),
)

fastifyPassport.registerUserSerializer(async (user: { id: string }) => user.id)
fastifyPassport.registerUserDeserializer(async (id: string) => {
  return app.db.user.findUnique({ where: { id } })
})

Authenticate Routes

app.post(
  '/login',
  {
    preValidation: fastifyPassport.authenticate('local', {
      successRedirect: '/dashboard',
      failureRedirect: '/login?err=1',
    }),
  },
  async () => null,
)

app.get(
  '/me',
  { preHandler: (req, reply, done) => (req.isAuthenticated() ? done() : reply.code(401).send()) },
  async (req) => req.user,
)

The user becomes available on request.user after authentication, just like upstream Passport.

@fastify/csrf-protection →