Logout clears client+server session data within 1s
Why it matters
A logout that only clears client-side state — localStorage, React context, or a cookie set to Max-Age=0 without server-side destruction — leaves the server-side session record valid. Any actor who captured the session token (via network sniff, log file, browser extension, or XSS) can replay it after the user 'logged out' and regain full access. CWE-613 defines this as insufficient session expiration. OWASP A07 (Identification and Authentication Failures) and PCI-DSS Req 8.2.6 both require server-side invalidation. The consequence in a financial context is that post-logout token replay enables transfers, account changes, and data exfiltration on an account the user believed was secured.
Severity rationale
High because a server-side session that survives client logout allows token replay attacks — any captured session token remains valid indefinitely, granting full financial account access after the user has explicitly signed out.
Remediation
Implement all four cleanup steps in src/app/api/auth/logout/route.ts — server destruction, token invalidation, cookie clearing, and client state reset must complete atomically:
export async function POST(req: Request) {
const session = await getSession(req);
if (session) {
await sessionStore.destroy(session.id); // 1. server session gone
await tokenBlacklist.add(session.token); // 2. token invalidated
}
const response = new Response(JSON.stringify({ ok: true }), { status: 200 });
// 3. clear cookies server-side
response.headers.set('Set-Cookie',
'sessionId=; Path=/; HttpOnly; Secure; SameSite=Strict; Max-Age=0');
response.headers.set('Set-Cookie',
'authToken=; Path=/; HttpOnly; Secure; SameSite=Strict; Max-Age=0');
return response;
}
Client-side cleanup (step 4 — localStorage.clear(), sessionStorage.clear()) must run in the calling component after the server response confirms destruction, not in lieu of it.
Detection
- ID:
logout-clears-data - Severity:
high - What to look for: Count all cleanup actions in the logout endpoint and classify each as server-side or client-side. Enumerate at least 4 required actions: session.destroy(), token invalidation, cookie clearing, and client-state clearing. Quote the actual logout function code found. A logout that only clears client-side state does not count as pass — do not pass if server-side session remains valid after logout.
- Pass criteria: Logout endpoint performs at least 4 cleanup actions: (1) server session destroyed, (2) tokens invalidated, (3) cookies cleared, (4) client state cleared — all within under 1 second. Count all cleanup steps — report the ratio even on pass (e.g., "4 of 4 cleanup actions found: session.destroy(), token blacklist, Set-Cookie Max-Age=0, localStorage.clear()").
- Fail criteria: Logout only clears client-side state (missing server-side destroy), or fewer than 4 cleanup actions found, or session data remains in store after logout, or cookies not cleared.
- Skip (N/A) when: Session management is entirely delegated to a third-party provider — cite the actual provider found.
- Detail on fail:
"Logout clears localStorage but 0 server-side cleanup — session.destroy() not called. 2 of 4 required actions missing."or"Cookies not cleared — 3 of 4 actions found" - Cross-reference: Check
finserv-session-security.session-integrity.token-security-httponlyfor cookie security settings, andfinserv-session-security.session-lifecycle.session-operations-loggedfor logout event logging. - Remediation: Implement comprehensive logout that clears both server and client state (in
src/app/api/auth/logout/route.ts):// app/api/auth/logout.ts (Next.js) export async function POST(req: Request) { const session = await getSession(req); if (session) { // Clear server-side session await sessionStore.destroy(session.id); // Invalidate any tokens await tokenBlacklist.add(session.token); } // Create response and clear cookies const response = new Response(JSON.stringify({ ok: true }), { status: 200 }); response.headers.set('Set-Cookie', 'sessionId=; Path=/; HttpOnly; Secure; SameSite=Strict; Max-Age=0'); response.headers.set('Set-Cookie', 'authToken=; Path=/; HttpOnly; Secure; SameSite=Strict; Max-Age=0'); // Client-side cleanup in middleware or layout localStorage.removeItem('sessionData'); sessionStorage.clear(); return response; }
External references
- cwe · CWE-613 — Insufficient Session Expiration
- owasp:2021 · A07
- nist:rev5 · AC-12 — Session Termination
- pci-dss:4.0 · Req 8.2.6 — Inactive account management / session cleanup
Taxons
History
- 2026-04-18·v1.0.0·Initial import from finserv-session-security·automated