@fastify/passport
A Fastify-native port of Passport.js that authenticates requests with pluggable strategies, sessions, and typed hooks.
Repository Health
Technical Analysis
@fastify/passport brings the Passport.js authentication ecosystem to Fastify applications. It reimplements Passport’s core Authenticator class and strategy contract as a Fastify plugin, so any of the hundreds of existing Passport strategies (OAuth providers, bearer tokens, local username/password, and more) can protect Fastify routes via preValidation hooks instead of Express middleware.
The library decorates the Fastify request with login, logout, isAuthenticated, and passport helpers, and ships its own session manager built on @fastify/secure-session (with @fastify/session also supported) for persisting login state between requests. Serialization and deserialization of user objects into the session are handled through a chain of registered serializer/deserializer functions, mirroring Passport’s original API so teams migrating from Express keep familiar patterns.
Because it targets Fastify specifically, it is written entirely in TypeScript with first-class typings for strategies, authenticate/authorize options, and the augmented FastifyRequest/FastifyReply interfaces, giving strict-mode TypeScript users compile-time safety that the original Express-based Passport package does not provide.
What You Get
- An
Authenticatorclass exposinguse(),authenticate(),authorize(), and session-serialization APIs compatible with Passport.js conventions - Fastify
preValidationhook integration so authentication runs as part of the standard request lifecycle rather than bolted-on middleware - A built-in session manager wired to
@fastify/secure-session(stateless, encrypted cookies) with@fastify/sessionalso supported for stateful sessions - Request decorators for
login,logout,isAuthenticated, andisUnauthenticatedalongsiderequest.user/request.authInfo - Support for authenticating against multiple strategies in sequence, and for passing one-off strategy instances without global registration
- Full TypeScript typings for strategies, authenticate options, callbacks, and augmented Fastify request/reply interfaces
Common Use Cases
- Protecting Fastify routes with session-based login using a local username/password strategy
- Adding third-party OAuth login (Google, GitHub, Facebook) to a Fastify API via existing
passport-*strategy packages - Building an API server that authenticates stateless requests with bearer-token or basic-auth strategies (
session: false) - Linking a third-party account to an already-authenticated user via
authorize()without disturbing the existing login session - Migrating an Express + Passport application to Fastify while reusing the same strategy packages and serialization logic
Under The Hood
Architecture
The library centers on a single Authenticator class (src/authenticator.ts) that holds a registry of named strategies plus serializer/deserializer/info-transformer stacks; authenticate() and authorize() both construct an AuthenticationRoute (src/authentication-route.ts) that runs the selected strategy against the request as a preValidationAsyncHookHandler, while initialize() returns a fastify-plugin-wrapped setup (src/create-initialize-plugin.ts) that decorates the request with passport, login/logout, and isAuthenticated/isUnauthenticated. Session persistence is delegated to a dedicated SecureSessionManager (src/session-managers/secure-session-manager.ts), keeping session I/O separate from authentication logic; a runStack helper lets serializer/deserializer/transformer chains opt out via a thrown 'pass' sentinel, echoing Passport’s original chain-of-responsibility design translated into async/await.
Tech Stack
Written in TypeScript targeting Node, built on Fastify 5 as a peer framework and fastify-plugin for plugin encapsulation. Runtime dependencies are minimal — @fastify/flash for flash messages and fastify-plugin for registration — while development and testing pull in @fastify/secure-session, @fastify/session, @fastify/cookie, and @fastify/csrf-protection as integration targets, plus real Passport strategy packages (passport-facebook, passport-github2, passport-google-oauth, openid-client) to exercise compatibility. Linting runs through neostandard/ESLint 9, and the package builds via tsc with tstyche for type-level testing.
Code Quality
The repository has an extensive test suite (over twenty files under test/) covering the authenticator, authentication routes, authorization, session strategies, multi-strategy and multi-instance scenarios, CSRF fixation, and ESM interop, run through borp with coverage enforcement plus a separate type-testing pass via tstyche. Core classes carry detailed JSDoc-style comments explaining option semantics, and CI (a shared reusable Fastify workflow) enforces linting and license checks on every push and pull request, indicating a mature, well-governed contribution process.
API Design
The public API deliberately mirrors Passport.js’s original method names and option shapes (use, authenticate, authorize, registerUserSerializer) so teams migrating from Express-based Passport can reuse existing strategy packages with minimal changes, while adapting the calling convention to Fastify’s hook system (preValidation) instead of Express middleware signatures. Overloaded TypeScript signatures for authenticate/authorize give callers flexibility to pass options, a callback, or both, and the augmented FastifyRequest/PassportUser interfaces let consumers declaration-merge their own user types for full type safety without casting.