|
@@ -11,7 +11,7 @@
|
|
|
>
|
|
>
|
|
|
> Each finding is referenced as **F<N>** for later citation.
|
|
> Each finding is referenced as **F<N>** for later citation.
|
|
|
>
|
|
>
|
|
|
-> **Findings rolled up:** 5 sev-3 (5 fixed, 0 open), 27 sev-2 (27 fixed, 0 open), 42 sev-1 (3 fixed, 39 open).
|
|
|
|
|
|
|
+> **Findings rolled up:** 5 sev-3 (5 fixed, 0 open), 27 sev-2 (27 fixed, 0 open), 42 sev-1 (4 fixed, 38 open).
|
|
|
|
|
|
|
|
---
|
|
---
|
|
|
|
|
|
|
@@ -1244,6 +1244,40 @@
|
|
|
(8h idle / 24h absolute). No "revoke session by user_id"
|
|
(8h idle / 24h absolute). No "revoke session by user_id"
|
|
|
primitive.
|
|
primitive.
|
|
|
- **Severity: 1**
|
|
- **Severity: 1**
|
|
|
|
|
+- **Status:** Fixed. `AuthRequiredMiddleware` now periodically
|
|
|
|
|
+ revalidates the cached `UserContext` against `GET /api/v1/admin/me`.
|
|
|
|
|
+ Cadence is configurable via `UI_SESSION_REVALIDATE_SECONDS` (default
|
|
|
|
|
+ 300 seconds — 5 minutes); the middleware tracks the last revalidation
|
|
|
|
|
+ timestamp in a new `_revalidated_at` session slot owned by
|
|
|
|
|
+ `SessionManager`. Branches:
|
|
|
|
|
+ - **403 from the api** (`user_disabled` or `unknown impersonated user`)
|
|
|
|
|
+ → session cleared, error flash "Your access was revoked. Please
|
|
|
|
|
+ sign in again.", 302 to `/login`. The api's existing F11 disabled-
|
|
|
|
|
+ user path drives this from the server side, so `Disabled` /
|
|
|
|
|
+ deleted users are kicked off all live sessions within one
|
|
|
|
|
+ revalidation window.
|
|
|
|
|
+ - **404** → defensive same-as-403 (the api currently always returns
|
|
|
|
|
+ 403 for missing/disabled users; treat 404 the same way for safety).
|
|
|
|
|
+ - **200 with changed role / display\_name / email** →
|
|
|
|
|
+ `SessionManager::updateUser()` rewrites the cached row but
|
|
|
|
|
+ preserves `_authenticated_at` / `_last_active` so the 8h idle and
|
|
|
|
|
+ 24h absolute timeouts keep running off the original login.
|
|
|
|
|
+ - **200 unchanged** → just bump `_revalidated_at`.
|
|
|
|
|
+ - **api unreachable / 401 / 5xx / generic** → log a warning, mark
|
|
|
|
|
+ revalidated to avoid grinding on every request, and proceed with
|
|
|
|
|
+ the existing session. An api outage must not lock every live
|
|
|
|
|
+ session out, and the api itself is the authoritative gate on
|
|
|
|
|
+ every data call (it re-resolves the principal via
|
|
|
|
|
+ `X-Acting-User-Id` per request, F11), so a stale UI cache during
|
|
|
|
|
+ an outage cannot escalate privilege.
|
|
|
|
|
+ Pre-F36 ("legacy") sessions without `_revalidated_at` are
|
|
|
|
|
+ bootstrapped on first sight without an api call, so existing
|
|
|
|
|
+ rolling sessions don't all stampede the api on deploy. Tests:
|
|
|
|
|
+ `ui/tests/Integration/Auth/SessionRevalidationTest.php` covers
|
|
|
|
|
+ within-interval (no api call), past-interval-no-change,
|
|
|
|
|
+ past-interval-role-changed (admin → viewer is reflected
|
|
|
|
|
+ immediately), `user_disabled` and unknown-user kick paths,
|
|
|
|
|
+ api-unreachable-keeps-session, and the legacy-session bootstrap.
|
|
|
|
|
|
|
|
### F37 — Local-admin password hash algorithm not validated at boot
|
|
### F37 — Local-admin password hash algorithm not validated at boot
|
|
|
- **File:** `ui/src/Auth/LocalLoginController.php:42, 78`
|
|
- **File:** `ui/src/Auth/LocalLoginController.php:42, 78`
|