fix(frontend): update token refresh threshold and fix race condition
The 14-day refresh threshold was designed for the old 30-day tokens but the backend now emits 1-hour tokens. The threshold caused every page load to trigger an immediate /refresh-token call, which revoked the old JTI mid-flight while concurrent requests (profile, giftcards, bookings, etc.) were still using it, causing 401 errors. Changes: - Refresh threshold: 14 days -> 5 minutes (matches 1-hour token lifetime) - Interval check: 60 min -> 2 min (must be shorter than threshold) - Race condition: refresh now completes before profile fetch, preventing JTI invalidation during concurrent requests Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -32,14 +32,16 @@ class AuthStore {
|
||||
constructor() {
|
||||
if (browser) {
|
||||
this.initializeAuth();
|
||||
// Check token refresh every hour
|
||||
// Check token refresh every 2 minutes
|
||||
// (must be shorter than the 5-minute threshold so the
|
||||
// refresh check fires before the token actually expires)
|
||||
setInterval(
|
||||
() => {
|
||||
if (this.token) {
|
||||
this.refreshTokenIfNeeded();
|
||||
}
|
||||
},
|
||||
60 * 60 * 1000
|
||||
2 * 60 * 1000
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -78,9 +80,13 @@ class AuthStore {
|
||||
firstName: '',
|
||||
lastName: ''
|
||||
};
|
||||
this.fetchUserProfile();
|
||||
// Check if token needs refresh
|
||||
this.refreshTokenIfNeeded();
|
||||
|
||||
// Refresh first so any JTI invalidation from rotation
|
||||
// happens before other requests use this token.
|
||||
// Then fetch profile with the (potentially refreshed) token.
|
||||
this.refreshTokenIfNeeded().then(() => {
|
||||
this.fetchUserProfile();
|
||||
});
|
||||
} else {
|
||||
this.clearAuth();
|
||||
}
|
||||
@@ -195,9 +201,10 @@ class AuthStore {
|
||||
return;
|
||||
}
|
||||
|
||||
// Refresh if token expires in less than 14 days
|
||||
const fourteenDays = 14 * 24 * 60 * 60 * 1000;
|
||||
if (decoded.exp * 1000 - Date.now() < fourteenDays) {
|
||||
// Refresh if token expires in less than 5 minutes
|
||||
// (1-hour token lifetime from backend)
|
||||
const fiveMinutes = 5 * 60 * 1000;
|
||||
if (decoded.exp * 1000 - Date.now() < fiveMinutes) {
|
||||
try {
|
||||
const response = await fetch('/api/refresh-token', {
|
||||
method: 'POST',
|
||||
|
||||
Reference in New Issue
Block a user