
Node.js Auth in 2026: Passport.js Is Dead, Here's What Replaced It
April 11, 2026
Passport.js still pulls around 4 million weekly npm downloads. But every greenfield project I review in 2026 uses something else. The nodejs authentication landscape now splits into three camps: managed services (Clerk, Auth0), self-hosted libraries (Better Auth, Arctic), and framework-native solutions (Auth.js). Each camp makes real trade-offs. This post walks through what happened to Passport, what replaced it, and when you should pick each option.
Why Passport.js Lost Momentum#
Passport is not broken. It still works, and millions of production apps run on it. But the library was designed for a different era of Node.js, one where callbacks were standard, Express dominated, and OAuth providers numbered in the dozens. The core architecture has not kept up.
The strategy pattern requires you to wire up serialization, deserialization, session middleware, and provider-specific callbacks in a precise order. Get the order wrong and requests silently timeout. The done() callback swallows errors in ways that are hard to debug. None of this is typed. You end up writing the same 80 lines of boilerplate for every project.
Modern alternatives handle registration, login, password reset, MFA, and OAuth in a single package. Passport gives you the OAuth handshake and expects you to build everything else. That was fine in 2015. In 2026, it is a hard sell when Better Auth ships all of that with a single auth.handler() call.
- No built-in TypeScript support or type-safe sessions
- Requires separate packages for every OAuth provider (500+ strategy packages, many unmaintained)
- No password reset, email verification, or MFA out of the box
- Callback-based API in an async/await world
- Last major release (0.7.0) did not address architectural issues
Managed Auth: Clerk, Auth0, Descope#
Managed services handle auth entirely outside your codebase. You drop in an SDK, configure providers in a dashboard, and get pre-built UI components for sign-in, sign-up, and user management. No database schemas to maintain, no session logic to write.
Clerk is the one I reach for on most new projects. It ships React components that just work, organization management for multi-tenant SaaS, and a generous free tier of 50,000 monthly active users as of February 2026. After that, you pay $0.02 per user on the Pro plan. The DX is genuinely good. You can go from zero to working Google OAuth in under 15 minutes.
Auth0 remains the enterprise standard. If your client requires SOC 2 compliance documentation, SAML federation, or custom RBAC policies, Auth0 has the deepest feature set. The trade-off is price and complexity. Configuration sprawls across Actions, Rules, and Hooks in ways that take time to learn.
Descope is the newer player targeting B2B SaaS. It ships a visual flow builder for auth workflows and handles multi-tenant management out of the box. Worth evaluating if you need drag-and-drop passwordless flows without writing custom logic.
import { ClerkProvider } from '@clerk/nextjs';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<ClerkProvider>
<html lang="en">
<body>{children}</body>
</html>
</ClerkProvider>
);
}
Tip: Managed auth makes sense when auth is not your product. If you are building a SaaS app and auth is plumbing, pay for Clerk. If auth is your product (identity platform, custom SSO), self-host.
Self-Hosted Libraries: Better Auth, Arctic, Oslo#
Self-hosted means you own the database, the sessions, and the user table. No third-party dashboard, no per-user pricing, no vendor lock-in. The trade-off is that you maintain it.
Better Auth is the library I recommend for most self-hosted setups. It is TypeScript-first, framework-agnostic, and ships email/password, social login, MFA, and organization support in a single package. It uses your database directly through adapters for Drizzle, Prisma, and raw SQL. With roughly 2 million weekly npm downloads, it has crossed the threshold from "interesting new project" to "production-viable option."
You might remember Lucia. It was the darling of the self-hosted auth world until it was deprecated in late 2024. The maintainer archived the project because the database adapter model was too rigid. Lucia now exists purely as an educational resource. If you are still running Lucia v3, you have until early 2025 maintenance support. After that, migrate to Better Auth or roll your own using the patterns Lucia documented.
import { betterAuth } from 'better-auth';
import { drizzleAdapter } from 'better-auth/adapters/drizzle';
import { db } from './db';
export const auth = betterAuth({
database: drizzleAdapter(db),
emailAndPassword: { enabled: true },
socialProviders: {
google: {
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
},
},
});
Arctic and Oslo fill a different niche. Built by the same developer behind Lucia (Pilcrow Labs), Arctic is a lightweight OAuth 2.0 client library with support for 50+ providers. Oslo handles the crypto primitives: TOTP, WebAuthn, ECDSA, hashing. If you want to build auth from scratch but skip reimplementing the OAuth handshake and token verification, these two libraries are the building blocks.
Framework-Native: Auth.js and Nuxt Auth#
Auth.js (formerly NextAuth.js) took a different approach. Instead of being framework-agnostic, it integrates deeply with your framework's routing, middleware, and session model. Version 5 exports everything from a single NextAuth() call. No separate auth options file. Providers auto-detect environment variables prefixed with AUTH_.
The tight integration is both the strength and the weakness. Auth.js works beautifully with Next.js 16 server components and middleware. But if you later move to Hono, Fastify, or a non-framework API, you are rewriting your auth layer. I have done that migration. It took two full days on a mid-sized app.
import NextAuth from 'next-auth';
import Google from 'next-auth/providers/google';
export const { handlers, auth, signIn, signOut } = NextAuth({
providers: [Google],
});
As of September 2025, Auth.js is now maintained under the Better Auth organization. That signals where the ecosystem is headed. Auth.js will keep working for existing projects, but the forward momentum is clearly with Better Auth as the self-hosted standard.
Decision Matrix#
Pick your camp based on three questions. Who owns the user data? How much do you want to maintain? What is your budget at 100k users?
npm Weekly Downloads in Thousands (April 2026, approximate)
- Prototype or SaaS MVP where auth is plumbing: use Clerk. Ship in an afternoon, worry about it later.
- Production app where you own user data: use Better Auth with your existing database. Full control, zero per-user cost.
- Next.js app that will stay Next.js: Auth.js v5 integrates cleanly and has the smallest surface area to learn.
- Custom auth flows or identity as a product: use Arctic + Oslo as building blocks. You write the logic, they handle the crypto.
- Enterprise with compliance requirements: Auth0 or Descope. The audit trails and SAML support are worth the premium.
One pattern I see in teams that pick wrong: they choose managed auth for a product that needs deep user-table customization, then fight the vendor's data model for months. Or they self-host when the entire team is three people who should be building features instead of debugging session invalidation. Match the tool to the constraint, not the hype.
TL;DR: Passport.js still works but belongs to a previous era. For new projects in 2026, use Clerk if you want zero maintenance, Better Auth if you want full ownership, or Auth.js if your framework is Next.js and will stay that way. The tools you choose matter less than matching them to your actual constraints.