Clerk: redirect loop after authentication [2026 fix]

Clerk redirect loop caused by misconfigured callback URLs or middleware ordering. Fix: verify CLERK_REDIRECT_URL matches your deployment domain exactly.

Clerk: Redirect Loop After Authentication [2026 Fix]

TL;DR

Cause: Your CLERK_REDIRECT_URL environment variable doesn't match your actual deployment domain or middleware is processing redirects before Clerk completes authentication.

Fix: Set CLERK_REDIRECT_URL=https://yourdomain.com (exact match, no trailing slash) and ensure Clerk middleware runs *before* custom auth logic.

---

Exact Error Messages You'll See

``` 1. GET /api/auth/callback?code=XXX&state=YYY HTTP/1.1 → GET / HTTP/1.1 (infinite redirect chain)

2. Error: Invalid redirect_uri. The redirect_uri does not match any configured URLs.

3. [Clerk] Callback handler failed: redirect_uri parameter missing or invalid

4. POST /api/auth/callback 308 - middleware redirect loop detected

5. UnauthorizedError: Could not verify JWT. Session invalid or expired (after redirect loop) ```

---

Broken Code → Fixed Side by Side

Problem 1: Environment Variable Mismatch

❌ BROKEN (.env.production): ```env CLERK_PUBLISHABLE_KEY=pk_live_abc123xyz CLERK_SECRET_KEY=sk_live_def456uvw CLERK_REDIRECT_URL=http://localhost:3000 NEXT_PUBLIC_CLERK_REDIRECT_URL=localhost:3000 ```

✅ FIXED (.env.production): ```env CLERK_PUBLISHABLE_KEY=pk_live_abc123xyz CLERK_SECRET_KEY=sk_live_def456uvw CLERK_REDIRECT_URL=https://yourdomain.com NEXT_PUBLIC_CLERK_REDIRECT_URL=https://yourdomain.com ```

Why: The redirect URI in your environment must *exactly* match what's configured in [Clerk Dashboard](https://dashboard.clerk.com) → Applications → Allowed Redirect URLs. Protocol (https), domain, and port must all match. At 2am, 90% of cases are localhost in production config.

---

Problem 2: Middleware Processing Order (Next.js)

❌ BROKEN (middleware.ts): ```typescript import { authMiddleware } from "@clerk/nextjs/server"; import { customAuthCheck } from "@/lib/auth";

export const middleware = (req) => { customAuthCheck(req); // Runs FIRST - blocks Clerk callback return authMiddleware()(req); };

export const config = { matcher: ["/(.*)"], }; ```

✅ FIXED (middleware.ts): ```typescript import { authMiddleware } from "@clerk/nextjs/server"; import { customAuthCheck } from "@/lib/auth";

export const middleware = authMiddleware((auth, req) => { // Clerk processes callback FIRST if (req.nextUrl.pathname.startsWith("/api/auth/")) { return; // Let Clerk handle all auth callbacks } customAuthCheck(req); // Now safe to run custom logic });

export const config = { matcher: [ "/((?!_next|static|.*\\.png|.*\\.jpg).*)", "/api/(.*)", ], }; ```

Why: Custom middleware running *before* authMiddleware can intercept the /api/auth/callback request, preventing Clerk from completing the OAuth flow. Always wrap custom logic *inside* the Clerk middleware function.

---

Problem 3: Cookie Domain Mismatch (Multi-Domain Setup)

❌ BROKEN (ClerkProvider setup): ```tsx <ClerkProvider publishableKey={process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY} // Missing or wrong domain config > {children} </ClerkProvider> ```

✅ FIXED (app.tsx or _app.tsx): ```tsx <ClerkProvider publishableKey={process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY} domain={process.env.NEXT_PUBLIC_CLERK_DOMAIN || "yourdomain.com"} isSatellite={process.env.NEXT_PUBLIC_CLERK_IS_SATELLITE === "true"} > {children} </ClerkProvider> ```

Why: If you're using multiple subdomains (auth.yourdomain.com + app.yourdomain.com), Clerk needs explicit domain config so session cookies work across all properties. Without it, auth succeeds on one domain but fails on redirect to another.

---

Still Broken? Check These Too

1. Vercel/Hosting Deploy Mismatch — Is CLERK_REDIRECT_URL set in your hosting platform's environment variables? Hardcoded .env won't override. Log in to Vercel/Netlify/AWS and verify production env vars match your dashboard config.

2. Clerk Dashboard Allowed URLs — Go to [Clerk Dashboard](https://dashboard.clerk.com) → Applications → Your app → scroll to *Allowed Redirect URLs*. Add your exact production URL (including https://). If you deployed to a preview domain, add that too.

3. Session Token Expiration During Redirect — If you're redirecting to a protected route immediately after auth, the session token may not be validated in time. Add a 500ms delay or use Clerk's useAuth() hook to check isLoaded before rendering protected content. See [related](/?guide=clerk-session-verification) troubleshooting.

---

Version Note

This guide covers @clerk/nextjs v5.0+ and @clerk/remix v2.0+. Behavior differs significantly from v4.x regarding middleware. If you're on v4, ensure you're using withClerkMiddleware() instead of authMiddleware(). I'm uncertain if older Clerk SDK versions had different redirect handling — please verify your version with npm list @clerk/nextjs.

---

Official Docs

  • [Clerk Redirect URLs Documentation](https://clerk.com/docs/references/nextjs/auth-middleware)
  • [Environment Variables Setup](https://clerk.com/docs/deployments/clerk-env-variables)
  • Related Guides

  • [Clerk JWT verification errors](/?guide=clerk-jwt-invalid)
  • [Debugging Clerk session state](/?guide=clerk-session-invalid)
  • ---

    Found a different variation? Drop it in the comments. We're updating this guide in real-time based on the 2am incidents we see.

    🔥 0d
    LIVE
    ↓ PlanetScale rage spiking •⚠ Vercel pricing complaints •↑ Railway gaining fast •↑ Supabase happiness rising •↑ Resend loved by devs •↓ PlanetScale rage spiking •⚠ Vercel pricing complaints •↑ Railway gaining fast •↑ Supabase happiness rising
    DEVELOPER PAIN RADAR // Loading...

    Developers complain.
    Opportunities appear.

    We track what developers are struggling with today — and what opportunities that creates.

    —
    guides today
    —
    avg happiness
    🔥 Pain
    📖 Guides
    🔭 Explore
    👤 Mine
    🔥 Pain Radar — rage scores today
    ↗ share
    💡 Opportunity Feed — pain = market gap
    📈 Tool Momentum
    all scores →
    📖 Latest Guide
    all guides →
    📖 All Guides
    📊 Tool Scores
    + Submit
    📰 Hacker News
    ➕ Submit a Tool
    ← back