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