Session does not expire unexpectedly; inactivity warning present with time to extend
Why it matters
Users with cognitive disabilities, motor impairments, or those using assistive technology work more slowly and may legitimately need longer to complete tasks. A session that expires silently and discards form data—a grant application, benefits form, or tax filing—causes real harm beyond mere inconvenience. WCAG 2.2 SC 2.2.1 (Level A) requires that users be warned before a time limit expires and given an opportunity to extend it without data loss. SC 2.2.2 (Level A) targets automatic page updates that move content without user control. Section 508 2018 Refresh 503.3.5 incorporates timing control requirements. Silent session expiry during form-heavy government workflows is a common Section 508 complaint category.
Severity rationale
Info because session timeout issues are scoped to authenticated flows and do not block access to public content, but they cause significant data-loss harm to users working slowly on form-heavy tasks.
Remediation
Implement a session warning dialog that appears at least 60 seconds before expiration and offers an extend option without requiring re-authentication. In a client component wrapping authenticated pages:
const SESSION_DURATION_MS = 15 * 60 * 1000; // 15 minutes
const WARNING_BEFORE_MS = 60 * 1000; // 1 minute warning
useEffect(() => {
const warningTimer = setTimeout(() => {
setShowWarning(true); // Show dialog
}, SESSION_DURATION_MS - WARNING_BEFORE_MS);
return () => clearTimeout(warningTimer);
}, [lastActivity]);
{showWarning && (
<div role="alertdialog" aria-modal="true" aria-labelledby="timeout-title">
<h2 id="timeout-title">Your session is about to expire</h2>
<p>You will be logged out in 60 seconds. Any unsaved changes will be lost.</p>
<button onClick={extendSession}>Stay logged in</button>
<button onClick={logout}>Log out now</button>
</div>
)}
Use role="alertdialog" (not role="dialog") so screen readers immediately announce the warning without waiting for the user to navigate to it.
Detection
- ID:
session-timeout - Severity:
info - What to look for: Count all relevant instances and enumerate each. Check whether the application has user authentication. If so, examine the code for session timeout logic. Look for warnings or alerts before session expiration. Check whether users have an opportunity to extend their session (button to continue, dialog with countdown).
- Pass criteria: If the app has authentication, sessions do not expire silently. Users receive a warning at least 20 seconds before expiration and can extend the session without losing data.
- Fail criteria: Sessions expire without warning, or users have no opportunity to extend them.
- Skip (N/A) when: No user authentication or session management exists.
- Detail on fail: Example:
"User sessions time out after 15 minutes of inactivity. No warning is displayed. Users lose unsaved form data when the session expires." - Remediation: Implement a session warning:
useEffect(() => { const sessionTimeout = 15 * 60 * 1000; // 15 minutes const warningTime = 1 * 60 * 1000; // 1 minute before timeout const timer = setTimeout(() => { // Show warning dialog setShowWarning(true); }, sessionTimeout - warningTime); return () => clearTimeout(timer); }, []);
External references
- wcag:2.2 · 2.2.1 — Timing Adjustable
- wcag:2.2 · 2.2.2 — Pause, Stop, Hide
- section-508:2018-refresh · 503.3.5 — Timing Adjustable — Session Timeout
Taxons
History
- 2026-04-18·v1.0.0·Initial import from gov-section-508·automated