Fix magic link redirect to localhost behind a reverse proxy

After verifying the link, /auth/confirm built its redirect from
request.nextUrl. Behind a proxy or tunnel a route handler sees the
address the server is bound to (localhost:4322), so the browser was
sent off the public domain and away from the session cookie it had
just been given. Build the redirect from NEXT_PUBLIC_SITE_URL instead,
the same value the magic link email already uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-05 08:56:53 +02:00
co-authored by Claude Opus 5.5
parent 95ccf21d12
commit 48cecfff7f
+6 -4
View File
@@ -1,6 +1,7 @@
import { NextResponse, type NextRequest } from "next/server";
import { z } from "zod";
import { serverEnv } from "@/lib/env.server";
import { createClient } from "@/lib/supabase/server";
const otpTypeSchema = z.enum(["magiclink", "email", "signup", "invite", "recovery", "email_change"]);
@@ -23,8 +24,9 @@ export async function GET(request: NextRequest) {
signedIn = !error;
}
const url = request.nextUrl.clone();
url.pathname = signedIn ? "/admin" : "/login";
url.search = signedIn ? "" : "?error=link";
return NextResponse.redirect(url);
// Built from the configured site URL, not request.nextUrl: behind a reverse proxy or
// tunnel a route handler sees the address the server is bound to (e.g. localhost:4322),
// and redirecting there leaves the session cookie behind on the public domain.
const path = signedIn ? "/admin" : "/login?error=link";
return NextResponse.redirect(`${serverEnv.NEXT_PUBLIC_SITE_URL}${path}`);
}