From 89aaa7b36d3108b6bbbab316f56e2cc71d5ce712 Mon Sep 17 00:00:00 2001 From: Ryan Salazar Date: Sat, 9 May 2026 09:52:56 +0000 Subject: [PATCH] supabase browser client: match server cookie attributes (SameSite=Lax, no Secure) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The browser-side createBrowserClient was writing cookies with 'Secure; SameSite=None' while the server-side createServerClient writes the same cookie names with 'SameSite=Lax' (no Secure flag — Next.js cookies().set() default). When the wp-login API set the auth cookie via NextResponse, the browser stored it with SameSite=Lax. Then the browser supabase client (via AuthContext or any subsequent auth call) tried to re-write the cookie via document.cookie with Secure;SameSite=None. Browsers can't reconcile this — depending on Chrome/Safari/Firefox version, you get either: - duplicate cookies that confuse session detection - the JS write silently failing because Secure;SameSite=None has additional constraints - the existing Lax cookie getting clobbered with attributes that conflict with same-site navigation Net effect: AuthContext on /contributor doesn't reliably see the session even though the cookie exists, so /contributor's '!loading && !user → router.push(/login)' check bounces the user back to /client-login. Looks like login failed. Fix: align the JS-side cookie attributes with the server-side defaults (SameSite=Lax, no Secure). Both writes now produce the same cookie shape, no conflict. --- src/lib/supabase/client.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/lib/supabase/client.tsx b/src/lib/supabase/client.tsx index 5dd8528..565c725 100644 --- a/src/lib/supabase/client.tsx +++ b/src/lib/supabase/client.tsx @@ -17,7 +17,12 @@ export function createClient() { setAll(cookiesToSet: Array<{ name: string; value: string; options?: any }>) { if (typeof document === 'undefined') return; cookiesToSet.forEach(({ name, value, options }) => { - let cookieString = `${name}=${encodeURIComponent(value)}; Path=${options?.path || '/'}; Secure; SameSite=None`; + // Match server-side cookie attributes. Server uses Next.js + // cookies().set(), which defaults to SameSite=Lax with no + // Secure flag. Writing the same cookie name with different + // SameSite/Secure from JS produces conflicting state in the + // browser cookie store and breaks AuthContext on /contributor. + let cookieString = `${name}=${encodeURIComponent(value)}; Path=${options?.path || '/'}; SameSite=Lax`; if (options?.maxAge) cookieString += `; max-age=${options.maxAge}`; if (options?.domain) cookieString += `; domain=${options.domain}`; if (options?.expires) cookieString += `; expires=${options.expires}`;