Clerk vs NextAuth vs Auth.js: Which Auth Library for Your Next.js App
Auth is the first thing you build and the hardest to change later. Three dominant options exist — here's when to use each.
The Options
Clerk — Managed auth service
Full authentication UI, user management dashboard, and SDKs. You pay for monthly active users.
Pros: Pre-built UI components, MFA, orgs/teams, user impersonation, zero backend code
Cons: $25+/mo at scale, vendor lock-in, less control
Use when: B2B SaaS where teams/orgs matter, or you want zero auth code
Auth.js (NextAuth v5) — Open source, self-hosted
The standard for Next.js auth. Social providers, credentials, JWTs or database sessions.
Pros: Free, open source, massive ecosystem, works with any database
Cons: You maintain it, less polished UI out of the box
Use when: Standard OAuth flows, want full control, cost matters
Better Auth — Newer open source alternative
Drop-in Clerk-like features with self-hosting: orgs, API keys, MFA, all included.
Pros: Most features, self-hosted, TypeScript-first
Cons: Younger ecosystem
Use when: Want Clerk features without the bill
Auth.js v5 Setup (Most Common)
npm install next-auth@beta @auth/prisma-adapter
// auth.ts
import NextAuth from 'next-auth';
import { PrismaAdapter } from '@auth/prisma-adapter';
import Google from 'next-auth/providers/google';
import GitHub from 'next-auth/providers/github';
import { prisma } from './prisma';
export const { handlers, auth, signIn, signOut } = NextAuth({
adapter: PrismaAdapter(prisma),
providers: [Google, GitHub],
callbacks: {
session({ session, user }) {
session.user.id = user.id;
return session;
},
},
});
// app/api/auth/[...nextauth]/route.ts
import { handlers } from '@/auth';
export const { GET, POST } = handlers;
Protecting Routes
// middleware.ts — protect all /dashboard routes
import { auth } from '@/auth';
export default auth((req) => {
if (!req.auth && req.nextUrl.pathname.startsWith('/dashboard')) {
return Response.redirect(new URL('/login', req.url));
}
});
export const config = { matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'] };
Server Component Auth
import { auth } from '@/auth';
import { redirect } from 'next/navigation';
export default async function DashboardPage() {
const session = await auth();
if (!session) redirect('/login');
return <div>Welcome, {session.user?.name}</div>;
}
Prisma Schema
model User {
id String @id @default(cuid())
email String @unique
name String?
accounts Account[]
sessions Session[]
plan String @default("free")
createdAt DateTime @default(now())
}
model Account { ... } // Standard NextAuth fields
model Session { ... }
Decision Summary
| Need | Choice |
|---|---|
| Teams/orgs, polished UI, fast setup | Clerk |
| Standard OAuth, cost-conscious | Auth.js |
| Clerk features, self-hosted | Better Auth |
Auth.js ships pre-configured (Google + GitHub + email) in the AI SaaS Starter Kit. $99 one-time at whoffagents.com.
Top comments (0)