Clerk: redirect loop after authentication [2026 fix]
Clerk redirect loop caused by missing or mismatched redirect URI in dashboard. Add exact callback URL to allowed redirects.
Clerk: Redirect Loop After Authentication - 2am Emergency Fix
TL;DR
Cause: Your app's callback URL doesn't match Clerk's allowed redirect URIs in the dashboard. Fix: Addhttp://localhost:3000/auth/callback (or your prod domain) to Clerk dashboard → Applications → Allowed redirect URIs.---
Console Error Messages (Real Output)
You'll see one or more of these in your browser console or server logs at 2am:
``` Error: Redirect URI mismatch. The redirect_uri parameter does not match the list of allowed URIs for this client. ```
``` Error: Authentication succeeded but redirect failed. URI not whitelisted: http://localhost:3000/auth/callback ```
``` [Clerk] Invalid redirect URL. Expected one of: [https://example.com/auth/callback] but got: http://localhost:3000/auth/callback ```
``` Infinite redirect detected. User authenticated but session not persisted. Check NEXT_PUBLIC_CLERK_REDIRECT_URL environment variable. ```
``` TypeError: Cannot read property 'sessionId' of undefined at ClerkProvider.getSession (clerk.browser.js:1247) ```
---
Broken Code → Fixed Code
Problem Setup (Next.js Example)
BROKEN: ```typescript // pages/auth/callback.ts - exists but not whitelisted import { handleRedirectCallback } from '@clerk/nextjs/server';
export default async function handler(req, res) { return handleRedirectCallback(req, res); }
// .env.local NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xxxxx CLERK_SECRET_KEY=sk_test_xxxxx // ❌ Missing: NEXT_PUBLIC_CLERK_REDIRECT_URL ```
FIXED: ```typescript // pages/auth/callback.ts - same file, now with proper env import { handleRedirectCallback } from '@clerk/nextjs/server';
export default async function handler(req, res) { return handleRedirectCallback(req, res); }
// .env.local NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xxxxx CLERK_SECRET_KEY=sk_test_xxxxx NEXT_PUBLIC_CLERK_REDIRECT_URL=http://localhost:3000/auth/callback // For production: https://yourdomain.com/auth/callback ```
Dashboard Configuration (Critical)
BROKEN: Clerk Dashboard → Applications → Settings → Redirect URIs ``` Allowed redirect URIs: (empty or missing localhost entry) ```
FIXED: Clerk Dashboard → Applications → Settings → Redirect URIs ``` Allowed redirect URIs: http://localhost:3000/auth/callback https://yourdomain.com/auth/callback https://www.yourdomain.com/auth/callback ```
React/Vanilla JS (Non-Next.js)
BROKEN: ```javascript // index.js const clerk = new Clerk({ publishableKey: 'pk_test_xxxxx', // ❌ Missing redirect_uri config });
await clerk.authenticate(); ```
FIXED: ```javascript // index.js const clerk = new Clerk({ publishableKey: 'pk_test_xxxxx', redirect_uri: 'http://localhost:3000/auth/callback', });
await clerk.authenticate();
// Also add to dashboard (same as above) ```
---
Immediate Troubleshooting Checklist
1. Verify dashboard redirect URIs exist — Copy your exact URL from browser address bar and paste into Clerk dashboard. Match protocols (http vs https), domains, and ports exactly.
2. Environment variable sync — Restart your dev server after adding NEXT_PUBLIC_CLERK_REDIRECT_URL. Changes to .env.local don't hot-reload.
3. Check middleware configuration — If using clerkMiddleware(), ensure /auth/callback is NOT protected:
```typescript
export const config = {
matcher: ['/((?!.*\..*|_next).*)', '/', '/(api|trpc)(.*)']
// auth/callback should be publicly accessible
};
```
4. Verify session persistence — Ensure cookies are enabled and SameSite policy allows cross-domain if applicable.
---
Still Broken? Check These Too
1. Wildcard/localhost mismatch
Clerk doesn't accept wildcard URIs like http://*.localhost:3000/auth/callback. Add the exact hostname.
2. Port forwarding issues
If using ngrok/Tunnelmole for testing, your redirect URI must be the tunnel URL: https://abc123.ngrok.io/auth/callback, and this must be in the dashboard.
3. Multiple Clerk applications Ensure you're editing the correct Application in the Clerk dashboard. Copy your Publishable Key and verify it matches the app you're configuring.
4. Old Clerk SDK version
We're uncertain about pre-2024 SDK behavior with redirect handling. Verify you're on the latest: npm install @clerk/nextjs@latest
5. Origin header blocked Some reverse proxies strip the Origin header. Check your nginx/Apache config isn't removing it.
---
Related Guides
Official Documentation
---
Why This Happens
Clerk's OAuth-like flow requires explicit URI whitelisting for security. When you authenticate, Clerk redirects back to your app with an auth code. If that callback URL isn't registered in the dashboard, Clerk rejects it and loops back to the login page instead.
This is intentional CSRF protection—but it means 2am is when you discover you forgot to add localhost to the dashboard after merging production code that changed the callback path.
---
Found a different variation? Drop it in the comments below—this guide gets updated with real production issues.