Storing session tokens in localStorage means they survive browser restart, tab close, and OS sleep. An attacker with brief physical access, an XSS payload, or a malicious browser extension can exfiltrate a localStorage token and replay it from any machine at any time — the user's network disconnect or tab close provides no protection. CWE-384 (Session Fixation) and CWE-287 (Improper Authentication) both apply when a stale persistent token is accepted as proof of identity. NIST 800-63B IA-11 specifically addresses re-authentication requirements after session interruption. Financial applications that auto-resume from disk-persisted tokens effectively eliminate the security benefit of inactivity timeouts.
Medium because the attack requires the token to be exfiltrated first (via XSS, physical access, or extension), but once captured, a localStorage-persisted token grants indefinite session resumption without any re-authentication barrier.
Switch to sessionStorage (cleared on tab close) and never write session tokens to localStorage. Enforce this in src/lib/auth.ts:
// sessionStorage clears on tab close — correct for financial sessions
sessionStorage.setItem('sessionToken', token);
// Guard all protected routes against absent in-memory sessions
if (!sessionStorage.getItem('sessionToken')) {
redirect('/login'); // require fresh authentication
}
// Never write session tokens to localStorage
// localStorage.setItem('sessionToken', token); // XSS-exfiltrable, persists after browser restart
For token refresh flows, only issue a new token while an in-session sessionStorage entry is present — do not issue tokens on cold starts from stored data.
finserv-session-security.session-lifecycle.resumption-requires-reauthmedium"Session token in localStorage — auto-resumes across browser restarts, 0 re-auth required. 1 of 1 token stores uses localStorage."src/lib/auth.ts). Use sessionStorage (not localStorage) and do not persist session tokens to disk:
// Use sessionStorage (cleared on tab close) not localStorage
sessionStorage.setItem('sessionToken', token);
// Never store sensitive tokens in localStorage
// Implement token refresh only for in-session recovery, not cross-session
if (!sessionStorage.getItem('sessionToken')) {
// No in-memory session available — require login
redirect('/login');
}