Silent session expirations destroy work in progress and are disproportionately harmful to users with cognitive disabilities, fine motor impairments, or anyone who types slowly. WCAG 2.2 SC 2.2.1 (Timing Adjustable) is a Level A requirement: if a timed session exists, users must receive at least 20 seconds of warning and the ability to extend it. Losing an unsaved multi-step form or a long text entry to an invisible timeout is not a minor annoyance — it causes real task failure.
High because silent session expiry deletes user work without warning, directly violating WCAG 2.2 SC 2.2.1 at Level A and imposing disproportionate burden on users with cognitive or motor disabilities.
Show a warning dialog before session expiry and provide a one-click extension. The WCAG 2.2 SC 2.2.1 minimum is 20 seconds of warning.
useEffect(() => {
const SESSION_DURATION = 15 * 60 * 1000 // 15 minutes
const WARN_BEFORE = 30 * 1000 // warn 30 seconds before
const warningTimer = setTimeout(() => {
setShowExpiryWarning(true)
}, SESSION_DURATION - WARN_BEFORE)
return () => clearTimeout(warningTimer)
}, [])
// In the warning dialog:
<dialog open={showExpiryWarning} aria-live="assertive">
<p>Your session will expire in 30 seconds.</p>
<button onClick={extendSession}>Stay logged in</button>
<button onClick={logout}>Log out</button>
</dialog>
Ensure form state is either saved to a draft or preserved in localStorage so work survives even if the user does not respond in time.
ID: accessibility-wcag.operable.session-timeout
Severity: high
What to look for: Enumerate every relevant item. Check for session timeout logic in authentication or middleware. If sessions expire, verify that users are warned before expiry and given an option to extend the session or re-authenticate without losing work.
Pass criteria: If a session timeout exists, users receive a warning with at least 20 seconds notice, and they can extend the session or save their work.
Fail criteria: Sessions expire without warning, or users cannot extend the session and lose work.
Skip (N/A) when: The application has no session timeout, or the timeout is longer than 20 hours.
Detail on fail: Example: "Session times out after 15 minutes with no warning. Users lose form input without saving"
Remediation: Implement a session timeout warning:
useEffect(() => {
const timeoutId = setTimeout(() => {
showWarning('Your session will expire in 20 seconds. Do you want to stay logged in?')
const extendId = setTimeout(() => {
logout()
}, 20000)
}, sessionDuration - 20000)
return () => clearTimeout(timeoutId)
}, [])