diff --git a/apps/web/README.md b/apps/web/README.md index 530fc985..36edb7ed 100644 --- a/apps/web/README.md +++ b/apps/web/README.md @@ -95,6 +95,10 @@ The production CSP admits the exact validated `NEXT_PUBLIC_GATEWAY_URL`; a real Production build pins that value to `https://gateway.trycheatcode.com`, while optimized local QA can use its loopback Wrangler origin. Production additionally admits only Vercel's exact immutable deployment origin. +Google and other social authentication uses Clerk's full-page redirect flow. The callback therefore +finishes through one authoritative navigation instead of a popup attempting to replace the anonymous +client tree after its server identity has changed. Production can keep `Cross-Origin-Opener-Policy` +at `same-origin`; no authentication flow depends on a cross-origin opener relationship. ## Deploy diff --git a/apps/web/next.config.ts b/apps/web/next.config.ts index 7296baeb..6e4fd05e 100644 --- a/apps/web/next.config.ts +++ b/apps/web/next.config.ts @@ -73,7 +73,7 @@ const nextConfig = { { headers: [ { key: "Content-Security-Policy", value: CONTENT_SECURITY_POLICY }, - { key: "Cross-Origin-Opener-Policy", value: "same-origin-allow-popups" }, + { key: "Cross-Origin-Opener-Policy", value: "same-origin" }, { key: "Origin-Agent-Cluster", value: "?1" }, { key: "Permissions-Policy", value: "camera=(), geolocation=(), microphone=()" }, { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" }, diff --git a/apps/web/src/components/auth/auth-modal.tsx b/apps/web/src/components/auth/auth-modal.tsx index 6ad79eb0..c047fdef 100644 --- a/apps/web/src/components/auth/auth-modal.tsx +++ b/apps/web/src/components/auth/auth-modal.tsx @@ -7,6 +7,10 @@ import { clerkAuthAppearance } from "./clerk-auth-appearance"; export type AuthMode = "sign-in" | "sign-up"; +// OAuth changes the authenticated server identity. A full-page redirect gives Clerk and Next.js +// one authoritative navigation instead of reconciling a popup callback into an anonymous tree. +const AUTH_OAUTH_FLOW = "redirect" as const; + interface AuthModalProps { open: boolean; id?: string | undefined; @@ -75,7 +79,7 @@ function AuthModalContent({ appearance={clerkAuthAppearance} fallbackRedirectUrl={redirectPath} forceRedirectUrl={redirectPath} - oauthFlow="popup" + oauthFlow={AUTH_OAUTH_FLOW} routing="hash" /> ) : ( @@ -83,7 +87,7 @@ function AuthModalContent({ appearance={clerkAuthAppearance} fallbackRedirectUrl={redirectPath} forceRedirectUrl={redirectPath} - oauthFlow="popup" + oauthFlow={AUTH_OAUTH_FLOW} routing="hash" /> )}