Phase 0: Fix token race condition causing logout after login
- Updated getAuthToken/getRefreshToken to read from Zustand store first (faster, no parsing delay) - Added token existence check before making API calls in AppLayout - Added retry mechanism with 100ms delay to wait for Zustand persist to write token - Made 403 error handler smarter - only logout if token actually exists (prevents false logouts) - Fixes issue where user gets logged out immediately after successful login
This commit is contained in:
@@ -78,9 +78,16 @@ function getActiveSectorId(): number | null {
|
||||
}
|
||||
}
|
||||
|
||||
// Get auth token from store
|
||||
// Get auth token from store - try Zustand store first, then localStorage as fallback
|
||||
const getAuthToken = (): string | null => {
|
||||
try {
|
||||
// First try to get from Zustand store directly (faster, no parsing)
|
||||
const authState = useAuthStore.getState();
|
||||
if (authState?.token) {
|
||||
return authState.token;
|
||||
}
|
||||
|
||||
// Fallback to localStorage (for cases where store hasn't initialized yet)
|
||||
const authStorage = localStorage.getItem('auth-storage');
|
||||
if (authStorage) {
|
||||
const parsed = JSON.parse(authStorage);
|
||||
@@ -92,9 +99,16 @@ const getAuthToken = (): string | null => {
|
||||
return null;
|
||||
};
|
||||
|
||||
// Get refresh token from store
|
||||
// Get refresh token from store - try Zustand store first, then localStorage as fallback
|
||||
const getRefreshToken = (): string | null => {
|
||||
try {
|
||||
// First try to get from Zustand store directly (faster, no parsing)
|
||||
const authState = useAuthStore.getState();
|
||||
if (authState?.refreshToken) {
|
||||
return authState.refreshToken;
|
||||
}
|
||||
|
||||
// Fallback to localStorage (for cases where store hasn't initialized yet)
|
||||
const authStorage = localStorage.getItem('auth-storage');
|
||||
if (authStorage) {
|
||||
const parsed = JSON.parse(authStorage);
|
||||
@@ -148,9 +162,14 @@ export async function fetchAPI(endpoint: string, options?: RequestInit & { timeo
|
||||
if (errorData?.detail?.includes('Authentication credentials') ||
|
||||
errorData?.message?.includes('Authentication credentials') ||
|
||||
errorData?.error?.includes('Authentication credentials')) {
|
||||
// Token is invalid - clear auth state and force re-login
|
||||
const { logout } = useAuthStore.getState();
|
||||
logout();
|
||||
// Only logout if we actually have a token stored (means it's invalid)
|
||||
// If no token, it might be a race condition after login - don't logout
|
||||
const authState = useAuthStore.getState();
|
||||
if (authState?.token || authState?.isAuthenticated) {
|
||||
// Token exists but is invalid - clear auth state and force re-login
|
||||
const { logout } = useAuthStore.getState();
|
||||
logout();
|
||||
}
|
||||
// Don't throw here - let the error handling below show the error
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
Reference in New Issue
Block a user