11 KiB
description
| description |
|---|
| Troubleshooting guide for common Auth0 OAuth issues |
OAuth Troubleshooting Guide
Solutions for common Auth0 OAuth problems.
Quick Start
/oauth-troubleshoot [issue]
Common issues:
callback-mismatch- Callback URL doesn't matchtoken-expired- Access token expiredcors-error- CORS error when calling APIsilent-auth- Silent authentication not workingscope-error- Scope not in tokenmfa-required- MFA login failinglogout-not-clearing- Session not cleared on logoutsocial-login-fails- Social login buttons not working
Issue: Callback URL Mismatch
Error: "Unable to process redirect request" or "Invalid redirect_uri"
Cause: Redirect URL in Auth0 doesn't match your app's callback URL
Solution:
-
Check your app's callback URL:
// React <Auth0Provider authorizationParams={{ redirect_uri: window.location.origin + '/callback' }} > // Next.js AUTH0_CALLBACK_URL=http://localhost:3000/api/auth/callback -
Update Auth0 Dashboard:
Auth0 Dashboard → Applications → Your App → Settings Allowed Callback URLs: http://localhost:3000/callback OR http://localhost:3000/api/auth/callback (Must EXACTLY match your app!) -
Common mistakes:
- Including query params:
/callback?foo=bar(wrong!) - Using
http://vshttps:// - Port number mismatch:
:3000vs:3001 - Missing trailing slash inconsistency
- Including query params:
-
Test:
# Verify URL matches exactly echo "App uses: window.location.origin + '/callback'" echo "Current: $CALLBACK_URL"
Issue: Access Token Expired
Error: API returns 401 Unauthorized
Cause: Access token expired (default 10 minutes)
Solution:
-
Use Auth0 SDK (auto-refresh):
// React const { getAccessTokenSilently } = useAuth0() const token = await getAccessTokenSilently() // Auto-refreshes if expired // Next.js const session = await getSession() // SDK handles refresh const token = session.accessToken -
Verify token expiration:
Auth0 Dashboard → Applications → Settings → Token Expiration Should be: 600 (10 minutes) Refresh Token Expiration: 2592000 (30 days) Refresh Token Rotation: Enabled ✅ -
Manual refresh (if needed):
async function getRefreshToken() { const response = await fetch(`https://${AUTH0_DOMAIN}/oauth/token`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ client_id: CLIENT_ID, client_secret: CLIENT_SECRET, refresh_token: refreshToken, grant_type: 'refresh_token' }) }) const { access_token } = await response.json() return access_token } -
Test:
# Decode token to check expiration # Visit https://jwt.io and paste your access token # Look at "exp" claim (Unix timestamp)
Issue: CORS Error Calling API
Error: "Access to XMLHttpRequest blocked by CORS policy"
Cause 1: Backend CORS not configured for frontend origin
Solution 1 (Express/Node.js):
import cors from 'cors'
// Allow specific origins
app.use(cors({
origin: ['http://localhost:3000', 'https://myapp.com'],
credentials: true // Important for cookies
}))
// Or check origin dynamically
app.use(cors({
origin: function(origin, callback) {
if (ALLOWED_ORIGINS.includes(origin)) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
}
}))
Cause 2: Auth0 domain not in allowed origins
Solution 2 (Auth0 Dashboard):
Auth0 Dashboard → Applications → Settings
Allowed Web Origins:
http://localhost:3000 (for development)
https://myapp.com (for production)
(Allows Auth0 calls from these origins)
Cause 3: Missing credentials in request
Solution 3:
// Make sure credentials are included
fetch('/api/items', {
headers: { Authorization: `Bearer ${token}` },
credentials: 'include' // Important for cookies
})
Test:
# Test CORS
curl -H "Origin: http://localhost:3000" \
-H "Access-Control-Request-Method: GET" \
http://localhost:3001/api/items
# Should include Access-Control-Allow-Origin header
Issue: Silent Authentication Fails
Error: Silent auth not working, user must login again
Cause 1: Cache location wrong
Solution 1:
// WRONG ❌
new Auth0Provider({
cacheLocation: 'localStorage' // Can't do silent auth in localStorage
})
// RIGHT ✅
new Auth0Provider({
cacheLocation: 'memory' // For SPAs
})
Cause 2: Refresh token not rotated
Solution 2:
Auth0 Dashboard → Applications → Settings
Refresh Token Rotation: Enabled ✅
Refresh Token Expiration Absolute: 2592000 (30 days)
Cause 3: Third-party cookies blocked
Solution 3 (for local development):
Browser → Settings → Privacy → Cookies
Allow cookies (at least for localhost)
Test:
// Test silent auth
async function testSilentAuth() {
const token = await getAccessTokenSilently()
console.log('Silent auth worked:', token)
}
Issue: Scope Not in Token
Error: Token doesn't include required scope
Cause 1: Scope not requested during login
Solution 1:
// WRONG ❌
Auth0Provider({
// No scope specified
})
// RIGHT ✅
Auth0Provider({
authorizationParams: {
scope: 'openid profile email read:items write:items'
}
})
Cause 2: Scope not configured in Auth0
Solution 2:
Auth0 Dashboard → APIs → Your API → Scopes
Add:
+ read:items (Read access)
+ write:items (Write access)
+ delete:items (Delete access)
Cause 3: User not consented to scope
Solution 3:
Auth0 Dashboard → Connections → Settings
Require consent: Off (for internal apps)
Or allow user to accept scopes during login
Test:
// Decode token to check scopes
const decoded = jwt_decode(token)
console.log('Scopes:', decoded.scope)
Issue: MFA Login Failing
Error: "MFA is required" but MFA setup failed
Cause 1: MFA not configured
Solution 1:
Auth0 Dashboard → Connections → Authenticators
Enable:
✓ Google Authenticator
✓ SMS (optional)
✓ Email OTP
Require MFA: Off/On (depending on policy)
Cause 2: User hasn't set up MFA method
Solution 2:
Users must register MFA before login:
1. First login (without MFA)
2. Prompted to set up authenticator
3. Scan QR code or enter backup codes
4. Subsequent logins require MFA
Cause 3: Recovery codes not working
Solution 3:
If user loses authenticator:
1. User clicks "Can't scan?"
2. Gets backup codes
3. Use one code to login
4. Setup new authenticator
Or admin can reset MFA:
Auth0 Dashboard → Users → Select user → Actions → Reset authenticators
Test:
# Test MFA flow
# 1. Enable MFA in Auth0
# 2. Create test user
# 3. Login → should prompt for authenticator setup
Issue: Logout Not Clearing Session
Error: User clicks logout but remains logged in
Cause 1: Wrong logout URL
Solution 1 (React):
// WRONG ❌
logout() // Doesn't redirect or clear Auth0 session
// RIGHT ✅
logout({
logoutParams: {
returnTo: window.location.origin // Redirect after logout
}
})
Cause 2: Logout URL not in Auth0 allowlist
Solution 2:
Auth0 Dashboard → Applications → Settings
Allowed Logout URLs:
http://localhost:3000
https://myapp.com
(Must match where user is redirected after logout)
Cause 3: Session still active server-side
Solution 3 (Next.js):
// API route for logout
export default async function handler(req, res) {
await clearSession(res) // Auth0 SDK clears session
res.redirect('/')
}
// Or explicitly
import { getSession } from '@auth0/nextjs-auth0'
export const GET = async (req) => {
const session = await getSession()
if (session) {
await logout(req) // Clears Auth0 session
}
}
Test:
# Test logout
# 1. Login successfully
# 2. Click logout
# 3. Check:
# - Redirected to home
# - Cookies cleared
# - New login required
Issue: Social Login Not Working
Error: Social login button doesn't work or redirects to error
Cause 1: Social connection not enabled for app
Solution 1:
Auth0 Dashboard → Connections → Social → Google
Under "Select Applications":
Toggle: Your App → Enable ✅
(Same for Facebook, GitHub, etc.)
Cause 2: Social app credentials wrong
Solution 2 (Google example):
Auth0 Dashboard → Connections → Social → Google
Google OAuth2 settings:
Client ID: __________ (from Google Cloud Console)
Client Secret: __________ (from Google Cloud Console)
Get credentials:
1. Google Cloud Console: https://console.cloud.google.com
2. Create new project
3. Enable Google+ API
4. Create OAuth 2.0 Client ID
5. Copy Client ID and Secret to Auth0
Cause 3: Redirect URI not configured in social app
Solution 3:
Google Cloud Console:
Authorized redirect URIs:
https://YOUR_DOMAIN/login/callback
Facebook App Settings:
Valid OAuth Redirect URIs:
https://YOUR_DOMAIN/login/callback
GitHub:
Authorization callback URL:
https://YOUR_DOMAIN/login/callback
Test:
# Test social login
# 1. Visit login page
# 2. Click "Login with Google"
# 3. Should redirect to Google
# 4. After signin, should return to app
General Debugging Techniques
1. Check Auth0 Logs
Auth0 Dashboard → Logs
Shows all auth events with:
- User email
- Event type (login, logout, error)
- Timestamp
- Error details
2. Inspect Token
// In browser console
const token = await auth0.getAccessTokenSilently()
// Decode at jwt.io
// Or programmatically
import jwt_decode from 'jwt-decode'
const decoded = jwt_decode(token)
console.log(decoded)
3. Check Request Headers
# In browser DevTools → Network tab
# Select API request
# Check headers:
# Authorization: Bearer {token}
# Content-Type: application/json
4. Enable Debug Mode
// React
<Auth0Provider
domain={domain}
clientId={clientId}
logoutParams={{ returnTo: 'http://localhost:3000' }}
onError={(error) => console.error('Auth0 Error:', error)}
>
Still Having Issues?
- Check Auth0 Logs: Auth0 Dashboard → Logs (shows actual errors)
- Run security audit:
/oauth-security-audit - Review implementation:
/oauth-implement [framework] - Check Auth0 docs: https://auth0.com/docs
- Contact support: https://support.auth0.com
Status: Troubleshooting guide ready!