Production Auth Issue — Cookie Exists but Middleware Redirects (Next.js App Router + Better Auth)

Hi everyone :waving_hand:

I’m running into a production-only auth issue with Next.js App Router + middleware + Better Auth.

Everything works perfectly in local dev, but in production users get redirected to /login even though the session cookie clearly exists.


:magnifying_glass_tilted_left: Setup

  • Next.js (App Router)

  • Middleware (proxy.ts)

  • Better Auth (Google OAuth)

  • Deployed on Vercel

  • Domain: https://www.flexnightlife.com

  • Cookie name in production: __Secure-better-auth.session_token


:white_check_mark: What Works

After Google login:

  • OAuth completes successfully

  • Cookie is created

  • In DevTools → Application → Cookies I see:

__Secure-better-auth.session_token
Domain: www.flexnightlife.com
Path: /
Secure: true
HttpOnly: true
SameSite: Lax

So the session cookie definitely exists.


:cross_mark: The Problem

When navigating to:

/dashboard/organization

I get:

307 redirect → /login

In Network tab I see:

  • Next-Router-Prefetch: 1

  • Rsc: 1

  • No Cookie header present in request

So middleware sees no cookie and redirects.


:brain: My Middleware

export function proxy(request: NextRequest) {
  const sessionCookie =
    request.cookies.get("better-auth.session_token") ??
    request.cookies.get("_Secure-better-auth.session_token") ??
    request.cookies.get("__Secure-better-auth.session_token") ??
    request.cookies.getAll().find((c) =>
      c.name.endsWith("better-auth.session_token")
    );

  if (!sessionCookie?.value) {
    return NextResponse.redirect(new URL("/login", request.url));
  }

  return NextResponse.next();
}

export const config = {
  matcher: ["/dashboard/:path*"],
};

I also tried skipping prefetch requests:

if (request.headers.get("next-router-prefetch") === "1") {
  return NextResponse.next();
}

Still not working.


:warning: Important Observation

In production:

  • The prefetch request to /dashboard/... does not include cookies.

  • Middleware runs.

  • It redirects to /login.

  • Navigation ends up redirecting even though user is logged in.

In local dev this never happens.


:puzzle_piece: Questions

  1. Is this expected behavior for RSC prefetch requests in production?

  2. Should middleware skip auth checks for RSC/prefetch?

  3. Is this a known limitation of middleware + App Router?

  4. Is there a better pattern for auth protection in App Router?


:bullseye: Expected Behavior

If user is authenticated (valid session cookie exists),
navigating to /dashboard should not redirect.


If anyone has run into this with:

  • Next.js 14+

  • Vercel

  • Better Auth / Auth.js / custom auth

  • App Router middleware

I’d really appreciate guidance :folded_hands:


If you want, I can also give you:

  • A shorter Discord-style version

  • A StackOverflow-formatted version

  • Or a more technical deep-dive version for the Next.js repo

Just tell me where you’re planning to post it.

I had a very similar problem with the redirect and just fixed it.
Your proxy file looks correct which was one of my problems.
The changes I made:
First: I had the backend variable BETTER_AUTH_URL set to the wrong url. Should be your frontend url.
Second: changed how I was routing (Not router.push())

const commentsUrl = `/api/comments`
const response = await fetch(commentsUrl, {
        credentials: "include",
      });

Feel free to check out my github repo with the implementation.

I also created a claude skill after debugging all my better-auth problems.