ASVS 5.0 V7.3.1 (Level 2) requires an inactivity timeout, so a session that has been idle for the configured time forces the user to authenticate again. The length should come from your risk analysis and documented decisions (see V7.1.1), not from a framework default nobody read.
Why it matters
Unattended sessions are open doors: a laptop in a cafe, a shared kiosk, a phone left on a desk. The shorter the idle window, the smaller the chance someone else uses it. The timeout also limits how long a stolen cookie works if the attacker is slow.
How to implement it
Track last activity on the server. Do not trust a client side timer; it is a convenience for the user interface, not a control.
IDLE_SECONDS = 15 * 60
def check_session(session, now):
if now - session.last_seen > IDLE_SECONDS:
session.revoked = True
return None
session.last_seen = now
return session
With Express and a store backed session, set a rolling cookie and a matching server side expiry:
app.use(session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
rolling: true,
cookie: { maxAge: 15 * 60 * 1000, httpOnly: true, secure: true, sameSite: "lax" },
store,
}));
Vary the value by risk. A payments admin might get 5 minutes, a read only dashboard 30. Update last activity only on genuine user requests, so a background poll does not keep sessions alive forever.
How to test it
- Sign in, wait one minute past the idle limit (or move the server clock or the stored timestamp), and make a request. Expect a redirect to login or a 401.
- Confirm that the old cookie cannot be reused after the timeout.
- Make requests just before the limit and confirm the window resets.
- Check that background polling endpoints do not extend the session.
Common mistakes
- A JavaScript countdown that the user can pause.
- Rolling the expiry on every request, including automated pings.
- Different timeouts across services that nobody documented.
Quick check
Can the timeout be client side only?
No. The server must reject the request after the idle period regardless of what the browser does.