fix(auth): address PR review and OAuth state-loss bugs

- proxy: await getUser() so refreshed session cookies land on the response
- callback: gate on AUTH_ENABLED, reject non-relative next (open redirect)
- page: snapshot + resume form and style image across the OAuth redirect;
  require login before the style-image vision parse
- play: wire authResolveRef so login retries the action that hit 401;
  dismissing the modal no longer re-fires it
- server: wrap cookie setAll in try/catch for read-only contexts

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
yuanzonghao
2026-06-13 19:27:51 +08:00
parent 87a2f93edb
commit 89a5c54065
5 changed files with 237 additions and 41 deletions
+18 -1
View File
@@ -1,10 +1,27 @@
import { type NextRequest, NextResponse } from "next/server";
import { AUTH_ENABLED } from "@/lib/supabase/config";
import { createClient } from "@/lib/supabase/server";
// Only allow same-origin relative paths. Rejects `//evil.com`, `/\evil.com`,
// and absolute URLs that would otherwise turn `${origin}${next}` into an
// open redirect (CWE-601).
function safeNext(raw: string | null): string {
if (!raw || !raw.startsWith("/")) return "/";
if (raw.startsWith("//") || raw.startsWith("/\\")) return "/";
return raw;
}
export async function GET(request: NextRequest) {
const { searchParams, origin } = request.nextUrl;
// Auth not configured: nothing can legitimately hit this route, so just
// bounce home instead of constructing a Supabase client from blank env vars.
if (!AUTH_ENABLED) {
return NextResponse.redirect(`${origin}/`);
}
const code = searchParams.get("code");
const next = searchParams.get("next") ?? "/";
const next = safeNext(searchParams.get("next"));
if (code) {
const supabase = await createClient();