Clerk: redirect loop after authentication [2026 fix]
Redirect loop after Clerk login caused by misconfigured redirect URIs or stale middleware. Clear your allowed origins and verify callback URLs match exactly.
Clerk: Redirect Loop After Authentication - Emergency Fix
TL;DR
Cause: Your Clerk redirect URIs don't match your actual app URLs (including protocol, domain, and port). Fix: Update your Clerk dashboard allowed origins to match your app's exact callback URL.---
Exact Console Error Messages
Watch for these in your browser console, server logs, and Clerk logs:
``` 1. "Error: redirect_uri_mismatch: The redirect_uri does not match any of the allowed URIs"
2. "GET /api/auth/callback?code=xyz - 307 Temporary Redirect" (repeating)
3. "Warning: useAuth() returned null; user is not authenticated but callback succeeded"
4. "ReferenceError: __clerk_internal_redirect is not defined"
5. "POST https://[your-instance].clerk.accounts.com/oauth/authorize - 400 Bad Request" ```
The 307 loop (see error #2) is the smoking gun—your app keeps redirecting to Clerk, which redirects back, creating an infinite loop.
---
Broken Code vs. Exact Fix
❌ BROKEN: Mismatched Redirect URIs
Dashboard Configuration: ``` Allowed Origins: https://myapp.com Redirect URLs: https://myapp.com/auth/callback ```
Your code (middleware): ```javascript // nextjs/middleware.ts import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';
const isPublicRoute = createRouteMatcher([ '/', '/sign-in(.*)', '/sign-up(.*)', ]);
export default clerkMiddleware((auth, req) => { if (!isPublicRoute(req)) { auth().protect(); // Breaks if callback URL is wrong } }); ```
Production app running on: https://myapp.com:3000 or http://localhost:3000 during testing
→ Mismatch! Dashboard says https://myapp.com but your app is https://myapp.com:3000
---
✅ FIXED: Exact URI Match
Step 1: Update Clerk Dashboard
Go to: Clerk Dashboard → Settings → Allowed Origins & Redirect URLs
``` Allowed Origins: - https://myapp.com - https://myapp.com:3000 - http://localhost:3000
Redirect URLs: - https://myapp.com/api/auth/callback - https://myapp.com:3000/api/auth/callback - http://localhost:3000/api/auth/callback ```
Step 2: Verify your environment variables match
```bash
.env.local
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_live_... CLERK_SECRET_KEY=sk_live_... NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/dashboard NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/onboarding ```Step 3: Keep your middleware simple (unchanged)
```javascript // nextjs/middleware.ts - No changes needed if config is correct import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';
const isPublicRoute = createRouteMatcher([ '/', '/sign-in(.*)', '/sign-up(.*)', '/api/webhook(.*)', // Clerk webhooks must be public ]);
export default clerkMiddleware((auth, req) => { if (!isPublicRoute(req)) { auth().protect(); } });
export const config = { matcher: [ '/((?!_next|static|.*\\..*|favicon).*)', ], }; ```
Step 4: Clear browser cache and restart dev server
```bash
Kill your dev server
npm run dev (or yarn dev, etc.)
```Why this works: Clerk compares the redirect_uri parameter from your sign-in button against the dashboard whitelist byte-for-byte. Port numbers, protocols (http vs https), and subdomains all matter.
---
Still Broken? Check These Too
Issue #1: Stale middleware cache
.next/ folder and node_modules/.cacheIssue #2: Wrong callback route in your sign-in component
<SignIn /> component, check redirectUrl propNEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL<SignIn redirectUrl="/dashboard" /> must point to an authenticated routeIssue #3: Webhook signature validation failing silently
CLERK_WEBHOOK_SECRET in environment/api/webhooks/clerk route---
Version Uncertainty Note
This guide covers Clerk SDK v4.x and v5.x (2024-2026). If you're on v3 or earlier, callback URL configuration differs slightly—check your installed version with npm list @clerk/nextjs. The redirect loop symptom remains consistent across versions, but the configuration UI location may differ in older dashboards.
---
External Reference
📖 [Clerk Official Docs: Redirect URIs](https://clerk.com/docs/deployments/configure-allowed-origins)
🔗 [Related: Set up sign-in/sign-up routes](/?guide=clerk-setup)
🔗 [Related: Clerk session management](/?guide=clerk-sessions)
---
Found a different variation? Drop it in the comments — if your redirect loop has a different root cause (e.g., custom domain routing, reverse proxy issues, or regional deployment quirks), share it below to help other developers at 2am.