diff --git a/src/webapp/hooks/useAuth.tsx b/src/webapp/hooks/useAuth.tsx index 46e699b2..f198ddea 100644 --- a/src/webapp/hooks/useAuth.tsx +++ b/src/webapp/hooks/useAuth.tsx @@ -49,11 +49,10 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => { // Give it time for cookies to be properly set if (query.isError && !query.isLoading && pathname !== '/') { // Add a small delay for Safari iOS cookie handling - const isSafariIOS = - /iPad|iPhone|iPod/.test(navigator.userAgent) && - /Safari/.test(navigator.userAgent) && - !/Chrome/.test(navigator.userAgent); - + const isSafariIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && + /Safari/.test(navigator.userAgent) && + !/Chrome/.test(navigator.userAgent); + if (isSafariIOS) { setTimeout(() => { // Re-check auth status before logging out @@ -62,7 +61,7 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => { logout(); } }); - }, 2000); // Increase to 2 seconds for PWA context + }, 1000); } else { logout(); } diff --git a/src/webapp/lib/auth/dal.ts b/src/webapp/lib/auth/dal.ts index d5b7d7cb..3c08b60f 100644 --- a/src/webapp/lib/auth/dal.ts +++ b/src/webapp/lib/auth/dal.ts @@ -1,6 +1,5 @@ import type { GetProfileResponse } from '@/api-client/ApiClient'; import { cache } from 'react'; -import { isPWA } from './pwa-cookie-handler'; const appUrl = process.env.NEXT_PUBLIC_APP_URL || 'http://127.0.0.1:4000'; @@ -21,9 +20,6 @@ export const verifySessionOnClient = cache( const response = await fetch(`${appUrl}/api/auth/me`, { method: 'GET', credentials: 'include', // HttpOnly cookies sent automatically - headers: { - 'X-PWA-Context': isPWA() ? 'true' : 'false', - }, }); if (!response.ok) { diff --git a/src/webapp/lib/auth/pwa-cookie-handler.ts b/src/webapp/lib/auth/pwa-cookie-handler.ts deleted file mode 100644 index 210d8b54..00000000 --- a/src/webapp/lib/auth/pwa-cookie-handler.ts +++ /dev/null @@ -1,33 +0,0 @@ -export const isPWA = () => { - if (typeof window === 'undefined') return false; - - return ( - window.matchMedia('(display-mode: standalone)').matches || - (window.navigator as any).standalone === true - ); -}; - -export const setCookieForPWA = ( - name: string, - value: string, - days: number = 7, -) => { - if (isPWA()) { - const expires = new Date(); - expires.setTime(expires.getTime() + days * 24 * 60 * 60 * 1000); - document.cookie = `${name}=${value};expires=${expires.toUTCString()};path=/;secure;samesite=lax`; - } -}; - -export const getCookieForPWA = (name: string): string | null => { - if (isPWA()) { - const nameEQ = name + '='; - const ca = document.cookie.split(';'); - for (let i = 0; i < ca.length; i++) { - let c = ca[i]; - while (c.charAt(0) === ' ') c = c.substring(1, c.length); - if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length); - } - } - return null; -}; diff --git a/src/webapp/services/auth/CookieAuthService.client.ts b/src/webapp/services/auth/CookieAuthService.client.ts index d1a1ac19..8dbd6a09 100644 --- a/src/webapp/services/auth/CookieAuthService.client.ts +++ b/src/webapp/services/auth/CookieAuthService.client.ts @@ -1,36 +1,16 @@ -import { - isPWA, - getCookieForPWA, - setCookieForPWA, -} from '@/lib/auth/pwa-cookie-handler'; - const appUrl = process.env.NEXT_PUBLIC_APP_URL || 'http://127.0.0.1:4000'; export class ClientCookieAuthService { - // Note: With HttpOnly cookies, we cannot read tokens from document.cookie in regular browser - // But in PWA context, we may need to handle cookies differently + // Note: With HttpOnly cookies, we cannot read tokens from document.cookie + // The browser automatically sends cookies with requests using credentials: 'include' // All auth logic (checking status, refreshing tokens) is handled by /api/auth/me endpoint - // Check if we have any auth indicators (for PWA context) - static hasAuthIndicators(): boolean { - if (isPWA()) { - return !!( - getCookieForPWA('accessToken') || getCookieForPWA('refreshToken') - ); - } - // In regular browser, we can't check HttpOnly cookies - return true; // Let the server-side check handle it - } - // Clear cookies via API (logout) static async clearTokens(): Promise { try { const response = await fetch(`${appUrl}/api/auth/logout`, { method: 'POST', credentials: 'include', - headers: { - 'X-PWA-Context': isPWA() ? 'true' : 'false', - }, }); if (!response.ok) { @@ -38,25 +18,9 @@ export class ClientCookieAuthService { 'Logout API call failed, but continuing with client-side logout', ); } - - // In PWA context, also clear any client-side cookies - if (isPWA()) { - document.cookie = - 'accessToken=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; secure; samesite=lax'; - document.cookie = - 'refreshToken=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; secure; samesite=lax'; - } } catch (error) { console.error('Logout API call failed:', error); // Don't throw - we still want to clear the UI state - - // Still try to clear PWA cookies on error - if (isPWA()) { - document.cookie = - 'accessToken=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; secure; samesite=lax'; - document.cookie = - 'refreshToken=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; secure; samesite=lax'; - } } } }