# @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.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 Call API ;
}
```
```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.