diff --git a/backend/app/security.py b/backend/app/security.py index 9f660f2..496f07c 100644 --- a/backend/app/security.py +++ b/backend/app/security.py @@ -55,10 +55,27 @@ def set_auth_cookie(response: Response, token: str, max_age_seconds: int) -> Non def clear_auth_cookie(response: Response) -> None: + """Clear auth cookie with explicit expiry to ensure removal.""" + # Delete with same settings used when setting (required for proper removal) response.delete_cookie( key=AUTH_COOKIE_NAME, path="/", domain=cookie_domain(), + secure=True, + httponly=True, + samesite="lax", + ) + # Also set with max_age=0 as fallback (some browsers need this) + response.set_cookie( + key=AUTH_COOKIE_NAME, + value="", + max_age=0, + expires=0, + path="/", + domain=cookie_domain(), + secure=True, + httponly=True, + samesite="lax", ) diff --git a/frontend/src/lib/store.ts b/frontend/src/lib/store.ts index 2694e6b..d588f5f 100644 --- a/frontend/src/lib/store.ts +++ b/frontend/src/lib/store.ts @@ -106,17 +106,46 @@ export const useStore = create((set, get) => ({ // They can then log in manually via the login page }, - logout: () => { - api.logout() + logout: async () => { + try { + // Call backend to clear HttpOnly cookie + await api.logout() + } catch { + // Continue with client-side cleanup even if backend call fails + } + + // Clear all client-side state set({ user: null, isAuthenticated: false, domains: [], subscription: null, + isLoading: false, }) - // Redirect to landing page + + // Clear ALL client-side storage if (typeof window !== 'undefined') { - window.location.href = '/' + // Clear localStorage + try { + localStorage.clear() + } catch { /* ignore */ } + + // Clear sessionStorage + try { + sessionStorage.clear() + } catch { /* ignore */ } + + // Clear any cookies we can access from JS (non-HttpOnly) + document.cookie.split(';').forEach(cookie => { + const name = cookie.split('=')[0].trim() + if (name) { + document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/` + document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=.pounce.ch` + } + }) + + // Force redirect to landing page with cache-busting + window.location.href = '/?logout=' + Date.now() } },