mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-19 07:33:18 +02:00
fix(auth): redirect to /login when JWT expires mid-session (#1698)
When the JWT expired on an open tab, the next API request hit a 401 with
"Token has expired"; client.ts cleared the token from storage but
AuthContext.user stayed populated from the original mount. ProtectedRoute
only redirects when user === null, so the protected tree kept rendering
and every subsequent request silently failed with no Authorization
header — the UI looked like every list was empty until a manual refresh
remounted AuthProvider.
The 3 other setAuthToken(null) sites live inside AuthContext itself and
already pair with setUser(null), so only the client.ts cross-module
site needed a React-tree signal.
- client.ts: after setAuthToken(null) on a token-invalidating 401,
window.dispatchEvent(new CustomEvent('auth:expired')). Guarded on
`typeof window !== 'undefined'` for SSR / test safety. Generic
"Authentication required" 401s still don't clear the token or fire
the event — treated as transient timing issues per the pre-existing
comment at client.ts:155.
- AuthContext.tsx: mount useEffect adds a window listener that calls
setUser(null) under the mountedRef guard; cleanup removes the
listener so unmount → remount doesn't double-bind.
Mirrors the patch the reporter shipped on their fork (deec96d1).
This commit is contained in:
@@ -94,8 +94,20 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
|
||||
mountedRef.current = true;
|
||||
// Check auth status on mount
|
||||
checkAuthStatus();
|
||||
|
||||
// Listen for token-expiry events from the API client. setAuthToken(null)
|
||||
// in client.ts only clears storage; without this listener, `user` stays
|
||||
// populated and ProtectedRoute keeps rendering the protected tree until a
|
||||
// manual refresh — every request silently fails in the meantime (#1698).
|
||||
const handleAuthExpired = () => {
|
||||
if (!mountedRef.current) return;
|
||||
setUser(null);
|
||||
};
|
||||
window.addEventListener('auth:expired', handleAuthExpired);
|
||||
|
||||
return () => {
|
||||
mountedRef.current = false;
|
||||
window.removeEventListener('auth:expired', handleAuthExpired);
|
||||
};
|
||||
}, []);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user