+| AUTH-1 | Idle + Absolute session timeouts (`/settings/security` Authentication policy) are not effectively enforced for the browser | **P1** | In progress | **Symptom:** a user who walks away stays logged in far past the configured idle timeout; the absolute timeout never bites either. The real ceiling is the 7-day refresh token. Security/compliance gap (NIST 800-53 AC-11/AC-12 — the frameworks OpenWatch itself scans for). **Backend is correct in isolation:** `internal/identity/sessions.go` `VerifySession` rejects on idle/absolute expiry and uses the configured windows. **Three compounding causes defeat it:** (1) the SPA polls many endpoints every 15-60s (ScansPage 15s, ScanningPage 30s, HostDetailPage 60s, ActivityPage 15s) + a persistent SSE stream; every authenticated request slides `expires_at = now + idle` (`sessions.go:188`), so "idle" tracks HTTP traffic, not user activity, and the window never elapses. (2) the cookie-refresh path (`internal/server/auth_handlers.go:269` `PostAuthRefreshCookie`) validates only the 7-day refresh token and mints a **fresh** session with new idle AND new absolute windows (`IssueSession` line 304) on the API client's transparent 401 retry (`frontend/src/api/client.ts:142`), masking expiry and resetting the absolute cap. (3) there is **no client-side user-activity idle timer** in the frontend — no mousemove/keydown tracking, no proactive logout/redirect. **Fix (layered):** (a) client-side idle timer keyed to real user input, reads `session_idle_timeout_seconds` from `/api/v1/auth-policy`, on inactivity calls logout (revoke session+refresh) + redirect `/login` [slice 1, in progress]; (b) enforce the absolute ceiling in refresh-cookie — carry the original login's absolute deadline in the refresh token; refuse to refresh past it; (c) defense-in-depth: only slide the server idle window on user-initiated requests (e.g. an `X-User-Activity` header), so server-side idle is real even if the client timer is bypassed |
0 commit comments