diff --git a/frontend/src/lib/stores/auth.svelte.ts b/frontend/src/lib/stores/auth.svelte.ts index f62c3b5..5ef46c2 100644 --- a/frontend/src/lib/stores/auth.svelte.ts +++ b/frontend/src/lib/stores/auth.svelte.ts @@ -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',