# @auth0/nextjs-auth0 The Auth0 Next.js SDK is a library for implementing user authentication in Next.js applications. It provides seamless integration with Auth0's identity platform, supporting both the App Router and Pages Router architectures. The SDK handles the complete authentication lifecycle including login, logout, session management, and token refresh with minimal configuration. The library offers server-side session management using encrypted cookies, automatic access token refresh, and support for advanced features like DPoP (Demonstrating Proof-of-Possession), Multi-Factor Authentication (MFA), Connected Accounts, and Client-Initiated Backchannel Authentication. It works with Next.js 14, 15, and 16, supporting both Edge and Node.js runtimes. ## Auth0Client - Server-Side Client The `Auth0Client` class is the main entry point for server-side authentication. It provides methods for session management, token retrieval, and protected route handling. ```typescript // lib/auth0.ts import { Auth0Client } from "@auth0/nextjs-auth0/server"; export const auth0 = new Auth0Client({ domain: process.env.AUTH0_DOMAIN, clientId: process.env.AUTH0_CLIENT_ID, clientSecret: process.env.AUTH0_CLIENT_SECRET, secret: process.env.AUTH0_SECRET, appBaseUrl: process.env.APP_BASE_URL, authorizationParameters: { scope: "openid profile email offline_access", audience: "https://api.example.com" }, session: { rolling: true, absoluteDuration: 60 * 60 * 24 * 30, inactivityDuration: 60 * 60 * 24 * 7 } }); ``` ## middleware() - Authentication Middleware Handles authentication routes automatically. Must be called in your middleware file to mount `/auth/login`, `/auth/logout`, `/auth/callback`, and other auth routes. ```typescript // middleware.ts (Next.js 15) import type { NextRequest } from "next/server"; import { auth0 } from "./lib/auth0"; export async function middleware(request: NextRequest) { return await auth0.middleware(request); } export const config = { matcher: [ "/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)" ] }; ``` ```typescript // proxy.ts (Next.js 16) import { auth0 } from "./lib/auth0"; export async function proxy(request: Request) { return await auth0.middleware(request); } export const config = { matcher: [ "/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)" ] }; ``` ## getSession() - Retrieve User Session Returns the current user's session data including user profile and tokens. Works in Server Components, Server Actions, Route Handlers, and Pages Router. ```typescript // App Router - Server Component import { auth0 } from "@/lib/auth0"; export default async function ProfilePage() { const session = await auth0.getSession(); if (!session) { return
Not authenticated
; } return (

Welcome, {session.user.name}!

Email: {session.user.email}

User ID: {session.user.sub}

{JSON.stringify(session.user, null, 2)}
); } ``` ```typescript // Pages Router - getServerSideProps import type { GetServerSideProps } from "next"; import { auth0 } from "@/lib/auth0"; export const getServerSideProps: GetServerSideProps = async (ctx) => { const session = await auth0.getSession(ctx.req); if (!session) { return { redirect: { destination: "/auth/login", permanent: false } }; } return { props: { user: session.user } }; }; export default function Profile({ user }) { return

Welcome, {user.name}!

; } ``` ```typescript // Middleware usage import { NextRequest, NextResponse } from "next/server"; import { auth0 } from "@/lib/auth0"; export async function middleware(request: NextRequest) { const authRes = await auth0.middleware(request); if (request.nextUrl.pathname.startsWith("/auth")) { return authRes; } const session = await auth0.getSession(request); if (!session) { return NextResponse.redirect(new URL("/auth/login", request.nextUrl.origin)); } return authRes; } ``` ## getAccessToken() - Retrieve Access Token Returns an access token for calling external APIs. Automatically refreshes expired tokens when a refresh token is available. ```typescript // App Router - Route Handler import { NextResponse } from "next/server"; import { auth0 } from "@/lib/auth0"; export async function GET() { try { const { token, expiresAt, scope } = await auth0.getAccessToken(); // Call external API const response = await fetch("https://api.example.com/data", { headers: { Authorization: `Bearer ${token}` } }); const data = await response.json(); return NextResponse.json(data); } catch (error) { return NextResponse.json({ error: "Failed to get token" }, { status: 401 }); } } ``` ```typescript // Force token refresh const { token } = await auth0.getAccessToken({ refresh: true }); ``` ```typescript // Multi-Resource Refresh Tokens (MRRT) - Different audiences const defaultToken = await auth0.getAccessToken(); const analyticsToken = await auth0.getAccessToken({ audience: "https://analytics-api.example.com", scope: "read:analytics" }); const adminToken = await auth0.getAccessToken({ audience: "https://admin-api.example.com" }); ``` ```typescript // Middleware with token refresh import { NextRequest, NextResponse } from "next/server"; import { auth0 } from "@/lib/auth0"; export async function middleware(request: NextRequest) { const authRes = await auth0.middleware(request); if (request.nextUrl.pathname.startsWith("/auth")) { return authRes; } const session = await auth0.getSession(request); if (!session) { return NextResponse.redirect(new URL("/auth/login", request.nextUrl.origin)); } // Get token with request/response for proper cookie handling const accessToken = await auth0.getAccessToken(request, authRes); return authRes; } ``` ## updateSession() - Modify User Session Updates the session with custom data. Changes are persisted in the session cookie. ```typescript // App Router - Route Handler import { NextResponse } from "next/server"; import { auth0 } from "@/lib/auth0"; export async function POST() { const session = await auth0.getSession(); if (!session) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } await auth0.updateSession({ ...session, user: { ...session.user, customField: "custom value", lastUpdated: Date.now() } }); return NextResponse.json({ success: true }); } ``` ```typescript // Middleware usage export async function middleware(request: NextRequest) { const authRes = await auth0.middleware(request); const session = await auth0.getSession(request); if (session) { await auth0.updateSession(request, authRes, { ...session, user: { ...session.user, lastActivity: Date.now() } }); } return authRes; } ``` ## withPageAuthRequired() - Protect Pages Higher-order function that protects pages from unauthenticated access. Redirects to login if no session exists. ```typescript // App Router - Protected Server Component import { auth0 } from "@/lib/auth0"; export default auth0.withPageAuthRequired( async function ProtectedPage() { const { user } = await auth0.getSession(); return
Hello {user.name}!
; }, { returnTo: "/dashboard" } ); ``` ```typescript // Pages Router - Protected Page import { auth0 } from "@/lib/auth0"; export default function Profile({ user }) { return
Hello {user.name}
; } export const getServerSideProps = auth0.withPageAuthRequired(); ``` ```typescript // Client-Side Protection "use client"; import { withPageAuthRequired } from "@auth0/nextjs-auth0"; export default withPageAuthRequired(function ProtectedPage({ user }) { return
Hello, {user.name}!
; }); ``` ## withApiAuthRequired() - Protect API Routes Protects API routes, returning 401 for unauthenticated requests. ```typescript // App Router - Protected Route Handler import { NextResponse } from "next/server"; import { auth0 } from "@/lib/auth0"; export const GET = auth0.withApiAuthRequired(async function handler(req) { const { user } = await auth0.getSession(req); return NextResponse.json({ message: "Protected data", userId: user.sub }); }); ``` ```typescript // Pages Router - Protected API Route import { auth0 } from "@/lib/auth0"; export default auth0.withApiAuthRequired(async function handler(req, res) { const { user } = await auth0.getSession(req); res.json({ secret: "Protected data", userId: user.sub }); }); ``` ## useUser() - Client-Side User Hook React hook for accessing user data on the client side. Uses SWR for caching and revalidation. ```typescript "use client"; import { useUser } from "@auth0/nextjs-auth0"; export default function UserProfile() { const { user, isLoading, error } = useUser(); if (isLoading) return
Loading...
; if (error) return
Error: {error.message}
; if (!user) return Login; return (
{user.name}

{user.name}

{user.email}

Logout
); } ``` ## Auth0Provider - Context Provider Wraps your application to provide user context. Optionally accepts an initial user from the server to avoid client-side fetch. ```typescript // app/layout.tsx import { Auth0Provider } from "@auth0/nextjs-auth0"; import { auth0 } from "@/lib/auth0"; export default async function RootLayout({ children }) { const session = await auth0.getSession(); return ( {children} ); } ``` ## getAccessToken() - Client Helper Client-side helper for fetching access tokens via the `/auth/access-token` endpoint. ```typescript "use client"; import { getAccessToken } from "@auth0/nextjs-auth0"; export default function ApiCaller() { const callApi = async () => { try { const token = await getAccessToken(); const response = await fetch("https://api.example.com/data", { headers: { Authorization: `Bearer ${token}` } }); const data = await response.json(); console.log(data); } catch (error) { console.error("Failed to get access token:", error); } }; return ; } ``` ```typescript // Get full response with expiration info const tokenSet = await getAccessToken({ includeFullResponse: true }); console.log(tokenSet.token, tokenSet.expires_in, tokenSet.expires_at); ``` ## startInteractiveLogin() - Programmatic Login Initiates the login flow programmatically from server-side code. ```typescript // app/api/custom-login/route.ts import { NextRequest } from "next/server"; import { auth0 } from "@/lib/auth0"; export async function GET(req: NextRequest) { return auth0.startInteractiveLogin({ returnTo: "/dashboard", authorizationParameters: { screen_hint: "signup", audience: "https://api.example.com", scope: "openid profile email read:data" } }); } ``` ## beforeSessionSaved Hook - Customize Session Hook to modify session data before it's persisted. Useful for adding custom claims or filtering data. ```typescript import { Auth0Client, filterDefaultIdTokenClaims } from "@auth0/nextjs-auth0/server"; export const auth0 = new Auth0Client({ async beforeSessionSaved(session, idToken) { return { ...session, user: { ...filterDefaultIdTokenClaims(session.user), roles: session.user["https://myapp.com/roles"], permissions: session.user["https://myapp.com/permissions"] } }; } }); ``` ## onCallback Hook - Handle Auth Callback Hook for custom logic after authentication completes. Handles errors and redirects. ```typescript import { NextResponse } from "next/server"; import { Auth0Client } from "@auth0/nextjs-auth0/server"; export const auth0 = new Auth0Client({ async onCallback(error, context, session) { const appBaseUrl = context.appBaseUrl ?? process.env.APP_BASE_URL; if (error) { console.error("Auth error:", error.message); return NextResponse.redirect( new URL(`/error?message=${encodeURIComponent(error.message)}`, appBaseUrl) ); } // Log successful login console.log("User logged in:", session.user.sub); return NextResponse.redirect( new URL(context.returnTo || "/dashboard", appBaseUrl) ); } }); ``` ## DPoP (Demonstrating Proof-of-Possession) Enhanced security feature that binds access tokens to cryptographic key pairs, preventing token theft. ```typescript import { Auth0Client } from "@auth0/nextjs-auth0/server"; import { generateKeyPair } from "oauth4webapi"; const dpopKeyPair = await generateKeyPair("ES256"); export const auth0 = new Auth0Client({ useDPoP: true, dpopKeyPair, dpopOptions: { clockTolerance: 60, retry: { delay: 200, jitter: true } } }); ``` ```typescript // Making DPoP-protected requests with fetcher const fetcher = await auth0.createFetcher(undefined, { baseUrl: "https://api.example.com" }); const response = await fetcher.fetchWithAuth("/protected-resource", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ data: "example" }) }); ``` ## createFetcher() - Authenticated HTTP Client Creates a configured fetcher for making authenticated API requests with automatic token handling and optional DPoP. ```typescript // App Router import { auth0 } from "@/lib/auth0"; export async function GET() { const fetcher = await auth0.createFetcher(undefined, { baseUrl: "https://api.example.com", useDPoP: true }); const response = await fetcher.fetchWithAuth("/users", { method: "GET", headers: { "Content-Type": "application/json" } }); return Response.json(await response.json()); } ``` ```typescript // With custom access token factory const fetcher = await auth0.createFetcher(req, { baseUrl: "https://api.example.com", getAccessToken: async (options) => { const accessToken = await auth0.getAccessToken(req, { ...options, audience: "https://special-api.example.com" }); return accessToken.token; } }); ``` ## MFA (Multi-Factor Authentication) Server and client APIs for handling MFA step-up authentication flows. ```typescript // Server-side MFA handling import { NextResponse } from "next/server"; import { auth0, MfaRequiredError } from "@auth0/nextjs-auth0/server"; export async function GET() { try { const { token } = await auth0.getAccessToken({ audience: "https://high-security-api.example.com" }); return NextResponse.json({ token }); } catch (error) { if (error instanceof MfaRequiredError) { // Return MFA token for client to handle return NextResponse.json(error.toJSON(), { status: 403 }); } throw error; } } ``` ```typescript // MFA verification flow const authenticators = await auth0.mfa.getAuthenticators({ mfaToken }); const challenge = await auth0.mfa.challenge({ mfaToken, challengeType: "otp", authenticatorId: authenticators[0].id }); await auth0.mfa.verify({ mfaToken, otp: "123456" }); ``` ```typescript // Client-side MFA import { mfa } from "@auth0/nextjs-auth0/client"; await mfa.verify({ mfaToken, otp: userEnteredCode }); ``` ## getAccessTokenForConnection() - Federated Identity Tokens Retrieves access tokens for connected identity providers (Google, Facebook, etc.). ```typescript import { auth0 } from "@/lib/auth0"; export async function GET() { try { const { token, expiresAt } = await auth0.getAccessTokenForConnection({ connection: "google-oauth2" }); // Use token to call Google APIs const response = await fetch("https://www.googleapis.com/calendar/v3/calendars/primary/events", { headers: { Authorization: `Bearer ${token}` } }); return Response.json(await response.json()); } catch (error) { return Response.json({ error: "Failed to get connection token" }, { status: 500 }); } } ``` ## connectAccount() - Link External Accounts Initiates the flow to connect additional identity providers to a user's account. ```typescript import { auth0 } from "@/lib/auth0"; export async function GET() { return auth0.connectAccount({ connection: "github", scopes: ["openid", "profile", "read:user"], returnTo: "/profile/connected-accounts" }); } ``` ## customTokenExchange() - RFC 8693 Token Exchange Exchanges external tokens for Auth0 tokens using Custom Token Exchange. ```typescript import { auth0 } from "@/lib/auth0"; export async function exchangeLegacyToken(legacyToken: string) { const result = await auth0.customTokenExchange({ subjectToken: legacyToken, subjectTokenType: "urn:acme:legacy-token", audience: "https://api.example.com", scope: "read:data write:data" }); return { accessToken: result.accessToken, expiresIn: result.expiresIn, tokenType: result.tokenType }; } ``` ## getTokenByBackchannelAuth() - CIBA Authentication Authenticates using Client-Initiated Backchannel Authentication for push-based login. ```typescript import { auth0 } from "@/lib/auth0"; const response = await auth0.getTokenByBackchannelAuth({ bindingMessage: "Approve login to MyApp", loginHint: { sub: "auth0|user123" }, requestedExpiry: 300 }); console.log(response.tokenSet.accessToken); ``` ## Database Sessions Configure custom session storage for scalability and control. ```typescript import { Auth0Client } from "@auth0/nextjs-auth0/server"; export const auth0 = new Auth0Client({ sessionStore: { async get(id) { return await redis.get(`session:${id}`); }, async set(id, session) { await redis.set(`session:${id}`, JSON.stringify(session), { ex: 60 * 60 * 24 * 7 }); }, async delete(id) { await redis.del(`session:${id}`); }, async deleteByLogoutToken({ sid, sub }) { if (sid) await redis.del(`session:${sid}`); if (sub) await redis.del(`user-sessions:${sub}`); } } }); ``` ## generateSessionCookie() - Testing Helper Generates session cookies for testing purposes. ```typescript import { generateSessionCookie } from "@auth0/nextjs-auth0/testing"; const sessionCookie = await generateSessionCookie( { user: { sub: "auth0|test-user-123", name: "Test User", email: "test@example.com" }, tokenSet: { accessToken: "test-access-token", refreshToken: "test-refresh-token", expiresAt: Math.floor(Date.now() / 1000) + 3600 } }, { secret: process.env.AUTH0_SECRET } ); // Use in tests const response = await fetch("/api/protected", { headers: { Cookie: `__session=${sessionCookie}` } }); ``` ## Authentication Routes The SDK mounts these routes automatically via the middleware: ``` /auth/login - Initiates login flow /auth/logout - Logs out user /auth/callback - Handles OAuth callback /auth/profile - Returns user profile (JSON) /auth/access-token - Returns access token (JSON) /auth/backchannel-logout - Handles back-channel logout ``` ```html Login Sign Up Login to Dashboard Logout Logout with redirect Logout from IdP ``` ## Summary The Auth0 Next.js SDK provides a comprehensive authentication solution for Next.js applications. Primary use cases include protecting server-rendered pages and API routes, managing user sessions with automatic token refresh, and integrating with external APIs using access tokens. The SDK seamlessly handles both App Router and Pages Router patterns, making it suitable for new and existing Next.js projects. For complex authentication scenarios, the SDK supports advanced features like DPoP for enhanced security, MFA step-up authentication for sensitive operations, and Connected Accounts for identity provider linking. Integration patterns typically involve creating an Auth0Client instance in a shared module, configuring middleware for route protection, and using hooks like `useUser()` and helpers like `getAccessToken()` throughout the application. The SDK's session management automatically handles token refresh, rolling sessions, and cookie security, allowing developers to focus on application logic rather than authentication implementation details.