<arch.design/>
libraryself-hostedMonolithopen source

Passport.js

The original Node.js authentication middleware — 500+ strategies

www.passportjs.org

Overview

Passport.js is the original authentication middleware for Node.js, released in 2011. It introduced the strategy pattern for authentication — each provider (local, OAuth, SAML, LDAP) is a separate pluggable strategy. With 500+ strategies available, it covers virtually every auth scenario.

Passport doesn't prescribe sessions or token management — it integrates with Express session middleware (express-session) or sets a req.user after validation, leaving the rest to you. This makes it extremely flexible but requires wiring up several pieces yourself.

Despite being over a decade old, Passport remains the dominant choice for Express and Fastify applications. The ecosystem of strategies for enterprise protocols (SAML, LDAP, Kerberos) is unmatched.

Architecture fit

self-hostedMonolith

Best suited to run inside your main application process alongside your app logic and database.

Key features

500+ authentication strategies (local, OAuth, SAML, LDAP, OIDC…)
Plugs into any Express-compatible middleware chain
req.user populated after successful authentication
Works with express-session for stateful sessions
Works with JWT strategies for stateless APIs
SAML and LDAP strategies for enterprise SSO
Maintains user serialization/deserialization for sessions

Trade-offs

+

Largest strategy ecosystem — covers SAML, LDAP, Kerberos, OIDC

Callback-heavy API design — predates async/await

+

Battle-tested since 2011, extremely stable

Wires multiple packages — passport + session + strategy

+

Framework-agnostic (Express, Fastify, Koa)

Not designed for Next.js App Router or Edge runtime

+

Best choice for enterprise SSO in Node.js backends

No built-in UI, organizations, or modern auth primitives

When to use

  • Express or Fastify REST APIs
  • Enterprise SAML/LDAP/Kerberos SSO requirements
  • Migrating a legacy Node.js app with existing Passport setup
  • Need a specific strategy that only Passport has

When NOT to use

  • New Next.js projects — Auth.js, Better Auth, or Clerk are better fits
  • Edge runtime or serverless (Passport needs Node.js APIs)
  • Apps that need organizations, API keys, or passkeys built-in

Implementation

TypeScript
// Express setup with local + GitHub strategies
import passport from "passport";
import { Strategy as LocalStrategy } from "passport-local";
import { Strategy as GitHubStrategy } from "passport-github2";
import session from "express-session";

// Session serialization
passport.serializeUser((user, done) => done(null, user.id));
passport.deserializeUser(async (id, done) => {
  const user = await db.user.findUnique({ where: { id } });
  done(null, user);
});

// Local strategy (email + password)
passport.use(new LocalStrategy({ usernameField: "email" },
  async (email, password, done) => {
    const user = await db.user.findUnique({ where: { email } });
    if (!user || !await bcrypt.compare(password, user.passwordHash))
      return done(null, false, { message: "Invalid credentials" });
    return done(null, user);
  }
));

// GitHub OAuth strategy
passport.use(new GitHubStrategy(
  { clientID: process.env.GITHUB_ID!, clientSecret: process.env.GITHUB_SECRET!, callbackURL: "/auth/github/callback" },
  async (accessToken, refreshToken, profile, done) => {
    const user = await db.user.upsert({
      where: { githubId: profile.id },
      create: { githubId: profile.id, email: profile.emails?.[0].value },
      update: {},
    });
    return done(null, user);
  }
));

// Middleware wiring
app.use(session({ secret: process.env.SESSION_SECRET!, resave: false, saveUninitialized: false }));
app.use(passport.initialize());
app.use(passport.session());

// Routes
app.post("/auth/login", passport.authenticate("local", { successRedirect: "/", failureRedirect: "/login" }));
app.get("/auth/github", passport.authenticate("github", { scope: ["user:email"] }));
app.get("/auth/github/callback", passport.authenticate("github", { successRedirect: "/" }));

// Protect a route
app.get("/dashboard", (req, res) => {
  if (!req.isAuthenticated()) return res.redirect("/login");
  res.json({ user: req.user });
});

In production

LinkedIn

Uses Passport's OAuth strategies in their developer ecosystem APIs

Express ecosystem

Dominant auth solution for Express apps, used by hundreds of thousands of Node.js projects

Other frameworks

← Back to Authentication