diff --git a/src/app/(auth)/login/page.tsx b/src/app/(auth)/login/page.tsx index ce76319..4755523 100644 --- a/src/app/(auth)/login/page.tsx +++ b/src/app/(auth)/login/page.tsx @@ -56,6 +56,13 @@ export default function LoginPage() { return; } + // Save tokens to localStorage BEFORE signIn to prevent race condition + // (dashboard components may call API before TokenSync has synced from session) + if (validateData.data?.accessToken) { + localStorage.setItem('accessToken', validateData.data.accessToken); + localStorage.setItem('refreshToken', validateData.data.refreshToken); + } + // If validation passed, use NextAuth to create session const result = await signIn('credentials', { email, @@ -66,6 +73,9 @@ export default function LoginPage() { setLoading(false); if (result?.error) { + // Login failed - clear the tokens we just saved + localStorage.removeItem('accessToken'); + localStorage.removeItem('refreshToken'); setError('Login failed. Please try again.'); } else { router.push('/'); diff --git a/src/app/(auth)/login/verify-2fa/page.tsx b/src/app/(auth)/login/verify-2fa/page.tsx index 1f4db39..a6704e2 100644 --- a/src/app/(auth)/login/verify-2fa/page.tsx +++ b/src/app/(auth)/login/verify-2fa/page.tsx @@ -102,8 +102,11 @@ function VerifyTwoFactorContent() { }); } + // Save tokens to localStorage BEFORE signIn to prevent race condition + localStorage.setItem('accessToken', response.data.accessToken); + localStorage.setItem('refreshToken', response.data.refreshToken); + // Now sign in with NextAuth using the tokens we received - // We need to call the NextAuth credentials provider with the tokens const result = await signIn('credentials', { email: userEmail, accessToken: response.data.accessToken, @@ -112,6 +115,8 @@ function VerifyTwoFactorContent() { }); if (result?.error) { + localStorage.removeItem('accessToken'); + localStorage.removeItem('refreshToken'); setError('Failed to complete login. Please try again.'); setLoading(false); } else { diff --git a/src/app/logout/page.tsx b/src/app/logout/page.tsx index 8d9cd57..3172bfd 100644 --- a/src/app/logout/page.tsx +++ b/src/app/logout/page.tsx @@ -23,11 +23,8 @@ export default function LogoutPage() { // Delete httpOnly cookies via server action (Next.js cookies() API) await clearAuthCookies(); - setTimeout(() => { - // Redirect to login - window.location.reload(); - window.location.href = '/login'; - }, 3000); + // Redirect to login immediately + window.location.href = '/login'; }; performLogout().catch(() => { diff --git a/src/components/providers/session-provider.tsx b/src/components/providers/session-provider.tsx index 572740f..221737a 100644 --- a/src/components/providers/session-provider.tsx +++ b/src/components/providers/session-provider.tsx @@ -39,9 +39,14 @@ function TokenSync() { hasInitialized.current = true; } } else if (status === "unauthenticated") { - // Clear tokens when logged out - localStorage.removeItem("accessToken"); - localStorage.removeItem("refreshToken"); + // Only clear tokens if a logout is explicitly in progress. + // Don't clear during normal page loads or brief unauthenticated flickers, + // as the login page saves tokens to localStorage before signIn completes. + const loggingOut = localStorage.getItem("isLoggingOut") === "true"; + if (loggingOut) { + localStorage.removeItem("accessToken"); + localStorage.removeItem("refreshToken"); + } hasInitialized.current = false; } }, [session, status]);