Auth.js (NextAuth v5)
Setup, providers, session strategies, adapters.
Auth.js (formerly NextAuth.js) is the most-installed auth library in the Next.js world. v5 cleaned up the API, dropped support for legacy runtimes, and embraced the App Router. In ten minutes you can have email, Google, GitHub, and Discord login working with sessions, CSRF, and cookies all handled for you.
Install & secrets
pnpm add next-auth@beta
npx auth secret # writes AUTH_SECRET to .env.localEvery provider also needs its own client ID and secret in .env.local:
AUTH_SECRET=your-generated-secret
AUTH_GITHUB_ID=Iv1.xxx
AUTH_GITHUB_SECRET=xxx
AUTH_GOOGLE_ID=xxx.apps.googleusercontent.com
AUTH_GOOGLE_SECRET=xxxThe auth.ts hub
One file exports everything: the handlers for the route, the auth() function to read the session on the server, and signIn/signOut for client/server actions.
import NextAuth from "next-auth";
import GitHub from "next-auth/providers/github";
import Google from "next-auth/providers/google";
import { PrismaAdapter } from "@auth/prisma-adapter";
import { prisma } from "@/server/db";
export const { handlers, signIn, signOut, auth } = NextAuth({
adapter: PrismaAdapter(prisma),
providers: [GitHub, Google],
session: { strategy: "database" },
callbacks: {
session({ session, user }) {
session.user.id = user.id;
return session;
},
},
});Wire up the route handler
export { GET, POST } from "@/auth/handlers";
// Or, if you exported handlers from auth.ts:
// export { GET, POST } from "@/auth";Session strategies: JWT vs database
- JWT (default): session lives entirely in a signed cookie. No DB lookup per request. You cannot easily revoke. Great for edge runtimes.
- Database: session row stored via an adapter. Requires a DB call per request but is revocable and trivially extensible. Pairs naturally with Prisma/Drizzle.
Reading the session in a Server Component
import { auth } from "@/auth";
import { redirect } from "next/navigation";
export default async function Dashboard() {
const session = await auth();
if (!session) redirect("/login");
return <h1>Hi, {session.user.name}</h1>;
}Protecting routes with middleware (proxy in Next 16)
export { auth as middleware } from "@/auth";
export const config = {
matcher: ["/dashboard/:path*", "/account/:path*"],
};Sign in & out
// Server Action
"use server";
import { signIn, signOut } from "@/auth";
export async function loginWithGitHub() {
await signIn("github", { redirectTo: "/dashboard" });
}
export async function logout() {
await signOut({ redirectTo: "/" });
}Adapters
Adapters connect Auth.js to a database. The most common in 2026:
@auth/prisma-adapter@auth/drizzle-adapter@auth/supabase-adapter, plus adapters for Mongo, Firebase, Convex, Neon, Turso, etc.
Each adapter expects a few tables (User, Account, Session, VerificationToken). The Prisma adapter has the schema in its README, copy-paste it.
Quiz
What does `npx auth secret` do?
Recap
- Install
next-auth@beta, runnpx auth secret, add provider env vars. - Centralize everything in
auth.ts: exportshandlers,auth,signIn,signOut. - JWT sessions are stateless and edge-friendly. Database sessions are revocable and richer.
- Adapters wire Auth.js to your DB. Prisma and Drizzle are the most common.
- Protect server components with
await auth()+redirect; protect groups of routes via middleware.