fix: Prevent token race conditions by pre-saving access/refresh tokens to localStorage before NextAuth signIn and refining logout token clearing.
This commit is contained in:
@@ -56,6 +56,13 @@ export default function LoginPage() {
|
|||||||
return;
|
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
|
// If validation passed, use NextAuth to create session
|
||||||
const result = await signIn('credentials', {
|
const result = await signIn('credentials', {
|
||||||
email,
|
email,
|
||||||
@@ -66,6 +73,9 @@ export default function LoginPage() {
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
|
||||||
if (result?.error) {
|
if (result?.error) {
|
||||||
|
// Login failed - clear the tokens we just saved
|
||||||
|
localStorage.removeItem('accessToken');
|
||||||
|
localStorage.removeItem('refreshToken');
|
||||||
setError('Login failed. Please try again.');
|
setError('Login failed. Please try again.');
|
||||||
} else {
|
} else {
|
||||||
router.push('/');
|
router.push('/');
|
||||||
|
|||||||
@@ -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
|
// 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', {
|
const result = await signIn('credentials', {
|
||||||
email: userEmail,
|
email: userEmail,
|
||||||
accessToken: response.data.accessToken,
|
accessToken: response.data.accessToken,
|
||||||
@@ -112,6 +115,8 @@ function VerifyTwoFactorContent() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (result?.error) {
|
if (result?.error) {
|
||||||
|
localStorage.removeItem('accessToken');
|
||||||
|
localStorage.removeItem('refreshToken');
|
||||||
setError('Failed to complete login. Please try again.');
|
setError('Failed to complete login. Please try again.');
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -23,11 +23,8 @@ export default function LogoutPage() {
|
|||||||
// Delete httpOnly cookies via server action (Next.js cookies() API)
|
// Delete httpOnly cookies via server action (Next.js cookies() API)
|
||||||
await clearAuthCookies();
|
await clearAuthCookies();
|
||||||
|
|
||||||
setTimeout(() => {
|
// Redirect to login immediately
|
||||||
// Redirect to login
|
|
||||||
window.location.reload();
|
|
||||||
window.location.href = '/login';
|
window.location.href = '/login';
|
||||||
}, 3000);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
performLogout().catch(() => {
|
performLogout().catch(() => {
|
||||||
|
|||||||
@@ -39,9 +39,14 @@ function TokenSync() {
|
|||||||
hasInitialized.current = true;
|
hasInitialized.current = true;
|
||||||
}
|
}
|
||||||
} else if (status === "unauthenticated") {
|
} else if (status === "unauthenticated") {
|
||||||
// Clear tokens when logged out
|
// 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("accessToken");
|
||||||
localStorage.removeItem("refreshToken");
|
localStorage.removeItem("refreshToken");
|
||||||
|
}
|
||||||
hasInitialized.current = false;
|
hasInitialized.current = false;
|
||||||
}
|
}
|
||||||
}, [session, status]);
|
}, [session, status]);
|
||||||
|
|||||||
Reference in New Issue
Block a user