Documentation Index Fetch the complete documentation index at: https://mintlify.com/auth0/nextjs-auth0/llms.txt
Use this file to discover all available pages before exploring further.
This guide provides solutions for common issues you may encounter when using the Auth0 Next.js SDK.
Authentication Issues
Infinite redirect loop
Symptoms: Browser keeps redirecting between /auth/login and /auth/callback.
Causes & Solutions:
Missing callback URL in Auth0 Dashboard
Ensure your callback URL is registered in the Auth0 Dashboard:
Go to Applications
Select your application
Add your callback URL to Allowed Callback URLs :
Local: http://localhost:3000/auth/callback
Production: https://yourdomain.com/auth/callback
Add your logout URL to Allowed Logout URLs :
Local: http://localhost:3000
Production: https://yourdomain.com
Middleware matcher too restrictive
If your middleware matcher excludes /auth/* routes, authentication won’t work. // Wrong - excludes auth routes
export const config = {
matcher: [ "/dashboard/:path*" ]
};
// Correct - includes all routes except static files
export const config = {
matcher: [
"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)"
]
};
Base path misconfiguration
If using Next.js basePath, ensure NEXT_PUBLIC_BASE_PATH is set: NEXT_PUBLIC_BASE_PATH=/dashboard
Auth routes will be at /dashboard/auth/login, /dashboard/auth/callback, etc.
”Invalid state” error
Error code: invalid_state
Causes & Solutions:
Cookie not persisting between requests
The transaction cookie must persist during the OAuth flow. Check:
Browser allows cookies
No aggressive cookie blockers
sameSite cookie setting is compatible with your domain setup
Fix for cross-domain issues: const auth0 = new Auth0Client ({
session: {
cookie: {
sameSite: "none" , // For cross-domain
secure: true // Required with sameSite=none
}
}
});
Clock skew between client and server
Large time differences can cause state validation to fail. Fix: Synchronize system clocks or increase transaction cookie duration:const auth0 = new Auth0Client ({
transactionCookie: {
duration: 900 // 15 minutes instead of default 10
}
});
Concurrent authentication attempts
Multiple tabs or windows attempting login simultaneously. Fix: Ensure enableParallelTransactions is enabled (default):const auth0 = new Auth0Client ({
enableParallelTransactions: true // Default, supports concurrent flows
});
Session not persisting after login
Symptoms: User successfully logs in but getSession() returns null.
Causes & Solutions:
Session cookies have a 4KB size limit. Large ID tokens or custom claims can exceed this. Check: Inspect cookies in browser DevToolsFix 1 - Use stateful sessions: import { Auth0Client , AbstractSessionStore } from "@auth0/nextjs-auth0/server" ;
import { Redis } from "ioredis" ;
class RedisSessionStore extends AbstractSessionStore {
// Implement get/set/delete
}
const auth0 = new Auth0Client ({
sessionStore: new RedisSessionStore ()
});
Fix 2 - Reduce token size:
Remove unnecessary custom claims
Use namespace in claim names
Request fewer scopes
beforeSessionSaved hook error
If your beforeSessionSaved hook throws an error, the session won’t be saved. Fix: Add error handling:const auth0 = new Auth0Client ({
beforeSessionSaved : async ( session ) => {
try {
// Your custom logic
return session ;
} catch ( error ) {
console . error ( "beforeSessionSaved error:" , error );
return session ; // Still save the session
}
}
});
Secure cookies won’t be sent over HTTP connections. Check: Are you accessing via http:// with secure: true?Fix for local development: const auth0 = new Auth0Client ({
session: {
cookie: {
secure: process . env . NODE_ENV === "production"
}
}
});
Note: Never use secure: false in production with dynamic base URLs.
Token Issues
”Missing refresh token” error
Error code: missing_refresh_token
Causes & Solutions:
offline_access scope not requested
Refresh tokens require the offline_access scope. Fix: const auth0 = new Auth0Client ({
authorizationParameters: {
scope: "openid profile email offline_access"
}
});
Refresh tokens disabled in Auth0
Check your Auth0 Application settings:
Go to Applications
Select your application
Go to Advanced Settings > Grant Types
Enable Refresh Token
Social connection doesn't support refresh tokens
Some social providers don’t issue refresh tokens. Check: Auth0 Dashboard > Authentication > SocialWorkaround: Use silent authentication or re-authentication when tokens expire.
Access token expired
Symptoms: API calls fail with 401 Unauthorized.
Solutions:
Automatic refresh (server-side)
The SDK automatically refreshes tokens server-side if a refresh token is available: // Automatically refreshes if expired
const { token } = await auth0 . getAccessToken ();
Refresh tokens slightly before they expire: const auth0 = new Auth0Client ({
tokenRefreshBuffer: 60 // Refresh 60 seconds before expiry
});
If refresh fails, prompt user to re-authenticate: import { AccessTokenError , AccessTokenErrorCode } from "@auth0/nextjs-auth0/errors" ;
try {
const { token } = await auth0 . getAccessToken ();
} catch ( error ) {
if ( error . code === AccessTokenErrorCode . FAILED_TO_REFRESH_TOKEN ) {
redirect ( "/auth/login" );
}
}
MFA required unexpectedly
Error code: mfa_required
Causes & Solutions:
Tenant requires MFA step-up
Some API audiences may require MFA even if the user already authenticated. Handle MFA step-up: import { MfaRequiredError } from "@auth0/nextjs-auth0/errors" ;
try {
const { token } = await auth0 . getAccessToken ({
audience: "https://api.example.com"
});
} catch ( error ) {
if ( error instanceof MfaRequiredError ) {
// Redirect to MFA challenge
redirect ( `/mfa?token= ${ error . mfa_token } ` );
}
}
Long-lived sessions may trigger MFA re-verification. Check: Auth0 Dashboard > Security > Multi-factor Auth > PoliciesFix: Implement MFA step-up flow in your application.
Configuration Issues
SDK configuration warnings
Symptoms: Console warnings about missing configuration.
Solutions:
Missing required environment variables
Ensure all required variables are set: AUTH0_DOMAIN=your-tenant.us.auth0.com
AUTH0_CLIENT_ID=your-client-id
AUTH0_CLIENT_SECRET=your-client-secret
AUTH0_SECRET=your-32-char-secret
Generate AUTH0_SECRET:
Domain should not include protocol or path: # Wrong
AUTH0_DOMAIN=https://your-tenant.us.auth0.com/
# Correct
AUTH0_DOMAIN=your-tenant.us.auth0.com
App base URL misconfiguration
For dynamic environments, omit APP_BASE_URL: // For preview deployments
const auth0 = new Auth0Client ();
// SDK infers base URL from request
For static production URLs: APP_BASE_URL=https://app.example.com
“Discovery failed” error
Error code: discovery_error
Causes & Solutions:
Check your domain is correct and accessible: curl https://YOUR_DOMAIN/.well-known/openid-configuration
Should return OIDC configuration JSON.
Network/firewall blocking Auth0
Ensure your server can reach Auth0:
Check firewall rules
Verify DNS resolution
Test connectivity: ping your-tenant.us.auth0.com
Increase timeout for slow networks: const auth0 = new Auth0Client ({
httpTimeout: 10000 // 10 seconds
});
Next.js Specific Issues
Middleware not running
Symptoms: Auth routes don’t work.
Solutions:
Next.js 15:
File: middleware.ts in project root (or src/middleware.ts if using src/ directory)
Next.js 16:
File: proxy.ts in project root (or src/proxy.ts)
Note: middleware.ts still works but only on Edge runtime
Ensure matcher includes auth routes: export const config = {
matcher: [
"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)"
]
};
Multiple middleware files
Only one middleware file is supported. Combine logic: export async function middleware ( request : NextRequest ) {
// Auth0 middleware
const authResponse = await auth0 . middleware ( request );
if ( authResponse ) return authResponse ;
// Your custom middleware
return customMiddleware ( request );
}
Client-side useUser returns undefined
Symptoms: useUser() hook returns undefined after successful login.
Solutions:
Wrap your app with Auth0Provider: // app/layout.tsx
import { Auth0Provider } from "@auth0/nextjs-auth0/client" ;
export default function RootLayout ({ children }) {
return (
< html >
< body >
< Auth0Provider >
{ children }
</ Auth0Provider >
</ body >
</ html >
);
}
useUser in Server Component
useUser is a client hook. Use getSession in Server Components:// Server Component
import { auth0 } from "@/lib/auth0" ;
export default async function Page () {
const session = await auth0 . getSession ();
// ...
}
// Client Component
"use client" ;
import { useUser } from "@auth0/nextjs-auth0/client" ;
export function UserProfile () {
const { user } = useUser ();
// ...
}
Build errors with DPoP
Symptoms: Build fails when using DPoP features.
Solutions:
Edge runtime compatibility
DPoP requires Node.js runtime. Configure route segment: // app/api/route.ts
export const runtime = "nodejs" ; // Not "edge"
CryptoKey objects can’t be serialized. Load keys at runtime: // Don't do this at module level
const dpopKeyPair = await generateKeyPair ( "ES256" );
// Do this - use environment variables
const auth0 = new Auth0Client ({
useDPoP: true
// Keys loaded from AUTH0_DPOP_PUBLIC_KEY and AUTH0_DPOP_PRIVATE_KEY
});
Slow authentication
Solutions:
Enable connection caching
Reuse OIDC discovery and JWKS: // Auth0Client caches discovery by default
// Ensure you're instantiating once and reusing
// lib/auth0.ts
export const auth0 = new Auth0Client ();
Remove unnecessary scopes
Use shorter custom claim names
Avoid large custom claims
Use stateful sessions for large sessions
Store session data in Redis/database instead of cookies: const auth0 = new Auth0Client ({
sessionStore: new RedisSessionStore ()
});
High memory usage
Solutions:
Instantiate Auth0Client once
Create a single instance and reuse: // Good - lib/auth0.ts
export const auth0 = new Auth0Client ();
// Bad - creating new instance per request
export function getAuth0 () {
return new Auth0Client ();
}
Disable rolling sessions if not needed
Reduces session writes: const auth0 = new Auth0Client ({
session: {
rolling: false
}
});
Note: This may impact security. See Session Configuration .
Debugging Tips
Check browser console and server logs: // Add logging in hooks
const auth0 = new Auth0Client ({
beforeSessionSaved : async ( session ) => {
console . log ( "Saving session:" , session );
return session ;
},
onCallback : async ( req , session , state ) => {
console . log ( "Callback:" , { session , state });
return { session };
}
});
Use browser DevTools:
Open DevTools > Application/Storage
Look for cookies:
Session: appSession (default name)
Transaction: auth_verification
Check size, expiry, flags (HttpOnly, Secure, SameSite)
View authentication logs in Auth0 Dashboard:
Go to Monitoring > Logs
Filter by application
Look for failed login attempts, errors
Verify OIDC configuration
Test discovery endpoint: curl https://YOUR_DOMAIN/.well-known/openid-configuration
Verify:
authorization_endpoint
token_endpoint
jwks_uri
Supported grant_types
Getting Help
If you’re still experiencing issues:
Check existing issues: GitHub Issues
Search documentation: Auth0 Docs
Ask the community: Auth0 Community
Report bugs: New Issue
When reporting issues, include:
SDK version (@auth0/nextjs-auth0 version)
Next.js version
Node.js version
Minimal reproduction code
Error messages with stack traces
Steps to reproduce