Clerk: redirect loop after authentication [2026 fix]

Redirect loop after Clerk auth caused by missing or misconfigured redirect URL in dashboard. Add exact callback URL to Allowed redirect URLs.

Clerk: Redirect Loop After Authentication - Emergency Fix

TL;DR

Cause: Your Clerk dashboard's "Allowed redirect URLs" doesn't match your app's actual callback route. Fix: Add http://localhost:3000/auth/callback (or your production URL) to Clerk dashboard → Application → Allowed redirect URLs, then restart your dev server.

---

Exact Error Messages

You'll see one or more of these in your browser console or server logs:

``` [Clerk] Redirect URI mismatch: 'http://localhost:3000/auth/callback' not in allowed list ```

``` Error: Invalid redirect_uri. The provided redirect_uri is not in the list of allowed URIs ```

``` Infinite redirect loop detected. User authenticated but cannot return to application. ```

``` [ClerkProvider] User session exists but redirect back to app fails - possible CORS or redirect configuration issue ```

``` window.location.href loop: /sign-in → /auth/callback → /sign-in → /auth/callback... ```

---

Broken Code vs. Fixed Code

❌ BROKEN: Incomplete Clerk Configuration

```javascript // pages/auth/callback.js or app/auth/callback/route.js import { handleRedirectCallback } from '@clerk/nextjs';

export default function AuthCallback() { // Missing proper error handling + redirect URL not in dashboard return handleRedirectCallback(); } ```

Problem: Your callback route exists, but Clerk dashboard doesn't know about it.

✅ FIXED: Complete Configuration

Step 1: Update callback route

```javascript // pages/auth/callback.js (Next.js Pages Router) import { handleRedirectCallback } from '@clerk/nextjs'; import { useEffect } from 'react'; import { useRouter } from 'next/router';

export default function AuthCallback() { const router = useRouter();

useEffect(() => { handleRedirectCallback(); }, []);

return <div>Completing sign in...</div>; } ```

OR for App Router:

```typescript // app/auth/callback/route.ts import { handleRedirectCallback } from '@clerk/nextjs/server'; import { NextRequest, NextResponse } from 'next/server';

export async function GET(req: NextRequest) { const response = await handleRedirectCallback(); return response || NextResponse.redirect(new URL('/dashboard', req.url)); } ```

Step 2: Add to Clerk Dashboard

1. Go to [Clerk Dashboard](https://dashboard.clerk.com) 2. Select your application 3. Navigate to Settings → URLs 4. In Allowed redirect URLs, add: - Development: http://localhost:3000/auth/callback - Production: https://yourdomain.com/auth/callback 5. Click Save 6. Restart your dev server

Step 3: Verify ClerkProvider wrapper (if using React)

```javascript // _app.js or app/layout.js import { ClerkProvider } from '@clerk/nextjs';

export default function RootLayout({ children }) { return ( <ClerkProvider publishableKey={process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY} > {children} </ClerkProvider> ); } ```

---

Still Broken? Check These Too

1. Multiple conflicting redirect URLs

If you have both http://localhost:3000/auth/callback AND http://127.0.0.1:3000/auth/callback in your allowed list, Clerk may reject one. Use consistent localhost naming or remove duplicates.

2. Environment variable mismatch

Your NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY or CLERK_SECRET_KEY might point to a different Clerk application than where you added the redirect URL. Verify they match the dashboard application you're configuring.

3. Middleware intercepts callback route

If using Clerk's built-in middleware, it might redirect before your callback handler runs. Check [related: Clerk middleware configuration](/?guide=clerk-middleware) and ensure your callback route is not protected:

```javascript // middleware.ts export const config = { matcher: [ '/((?!auth/callback|_next/static|_next/image|favicon.ico).*)', ], }; ```

---

Quick Checklist

  • [ ] Callback route exists and matches dashboard URL exactly
  • [ ] Restarted dev server after dashboard changes (critical!)
  • [ ] Using correct NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY for this application
  • [ ] ClerkProvider wraps your entire app
  • [ ] No trailing slashes mismatch (/callback vs /callback/)
  • [ ] HTTPS in production, HTTP in localhost
  • [ ] Cleared browser cache and cookies
  • ---

    Related Issues

  • [Clerk authentication not persisting across pages](/?guide=clerk-session-persistence) — Session exists but gets cleared on redirect
  • [CORS errors with Clerk](/?guide=clerk-cors-fix) — When you see Access-Control-Allow-Origin blocks
  • ---

    Official Documentation

    📖 [Clerk Authentication Flow - Official Docs](https://clerk.com/docs/references/nextjs/clerk-provider) 📖 [Redirect URIs Configuration](https://clerk.com/docs/deployments/set-up-your-application#configuring-your-application-urls)

    ---

    Found a different variation? Drop it in the comments

    This guide covers Next.js + Clerk v4+. If you hit this with a different stack (SvelteKit, Remix, Astro) or older Clerk versions, please comment the exact error and setup below—we'll add your solution to this guide.

    🔥 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