Sys Authentication & Access Control
En bref
The hardened entry door to the sys console: OAuth-only login through Microsoft or Google, a strict email allowlist, mandatory WebAuthn as second factor, four scoped sys roles, 60-minute sliding sessions with an 8-hour hard ceiling, and a 5-minute fresh-auth gate guarding every sensitive mutation.
Comment ça fonctionne
There is no password path and no OTP path. An operator hits `/auth/sys/login/start`, picks Microsoft or Google, and the API verifies the returned token against the provider's JWKS. The email claim is then matched against `SYS_ADMIN_EMAILS`; the allowlist entry can pin a specific provider per email when an operator must use a particular identity (`alice@example.com:google`).
A successful OAuth round-trip mints only a 2-minute pending JWT, never a usable sys-JWT. The operator must then complete a WebAuthn assertion via `/auth/sys/webauthn/authenticate/{start,complete}`; only then is the full sys-JWT issued. First-time onboarding flows through `/auth/sys/webauthn/register-onboard/*` so a brand-new operator can register their passkey without already having one.
The sys-JWT is ES512-signed, namespace-isolated from tenant JWTs, and slides activity for 60 minutes up to a hard 8-hour ceiling per login (the `hard_exp` claim is immutable across reauth). Roles are `sys_support`, `sys_engineer`, `sys_finance`, and `sys_security`, granted via `POST /auth/sys/users/{email}/roles`; an operator may hold several, self-grant is blocked, and every grant requires fresh-auth. The fresh-auth gate uses `@requires_fresh_auth(300)` to return `401 fresh_auth_required` with a `reauth_url`; the FreshAuthGate component in the console resolves it transparently via WebAuthn so the operator only sees a brief biometric prompt.
Force-logout of any sys session lives in the Operator sessions panel and is `sys_security`-only with mandatory reason. The break-glass endpoint is present as a 501 shell today and ships its full two-admin-confirm + 15-minute cap flow alongside the deploy hardening track.
Capacités clés
- OAuth-only login via Microsoft or Google with per-email provider pinning
- Mandatory WebAuthn second factor before sys-JWT is minted
- 60-minute sliding session with 8-hour immutable hard ceiling
- Fresh-auth gate returning 401 with `reauth_url`, resolved transparently via passkey
- Four sys roles enforced server-side; self-grant blocked; combinations allowed
- Operator sessions panel with reason-required force-logout (`sys_security`)
- Break-glass endpoint shell ready for sealed-envelope YubiKey + two-admin ceremony
En pratique
A new sys engineer is added to `SYS_ADMIN_EMAILS` and emailed an onboarding link. She visits `sys.petanque.life`, picks Google, completes the corporate SSO flow, and is held on a `/auth/sys/webauthn/register-onboard` page. She taps her YubiKey to register a passkey; the API now mints her first real sys-JWT.
Two days later she opens the User Directory to grant a colleague the `sys_engineer` role. The endpoint replies `401 fresh_auth_required`; the FreshAuthGate pops a passkey prompt, she touches her key, and the grant submits. Her first attempt to grant herself `sys_security` is rejected by the self-grant guard, and she opens a ticket asking another operator to do it instead.
Fonctionnalités de ce sous-système
9| ID | Status | Fonctionnalités |
|---|---|---|
| F21.01.01 | Livré | Microsoft OAuth or Google OAuth — no password, no OTP. Each provider is verified against its own JWKS; the token's email claim must match the allowlist (F21.01.02) regardless of provider. Work-Google accounts and Petanque Life Azure AD accounts both accepted so operators can pick the provider their device already has. ✅ PL-T121 |
| F21.01.02 | Livré | Email allowlist (SYS_ADMIN_EMAILS setting) — even with a valid Microsoft or Google token, off-allowlist emails are rejected at auth time. The allowlist entry may optionally pin the allowed provider per email (alice@example.com:google) when an operator must use a specific identity. Implemented (PL-T120) |
| F21.01.03 | Livré | Mandatory WebAuthn/passkey as second factor — OAuth mints only a 2-min pending JWT; the full sys-JWT is only issued after a verified WebAuthn assertion. First passkey onboarded via /webauthn/register-onboard/*. Implemented (PL-T121) |
| F21.01.04 | Livré | Four sys sub-roles: sys_support, sys_engineer, sys_finance, sys_security. A user may hold several. Capability matrix enforced server-side via existing ACC-003 deny-by-default framework. Self-grant blocked. Implemented (PL-T121) |
| F21.01.05 | Livré | Session TTL 60 min sliding. Activity renews up to a hard ceiling of 8 h per login. hard_exp is immutable across reauth. Implemented (PL-T121) |
| F21.01.06 | Livré | Fresh-auth gate (@requires_fresh_auth(300)) — returns 401 fresh_auth_required with a reauth_url. Frontend FreshAuthGate resolves transparently via WebAuthn. Gated endpoints: role changes, force-logout. Impersonation / refund / secret-rotation land in F21.02 / F21.07 / F21.17. Implemented (PL-T121) |
| F21.01.07 | Livré | Force-logout any sys session from the Operator sessions panel (sys_security only). Reason is required and audited. Implemented (PL-T121) |
| F21.01.08 | Livré | Break-glass account procedure documented — sealed envelope with YubiKey + runbook. Endpoint shell present (/auth/sys/break-glass returns 501 today). Full flow ships with PL-T138. ✅ PL-T122 |
| F21.01.09 | Livré | API-token-vy i /settings/api-token — operatören kan visa, kopiera och få curl/httpie/python-snippets för sin egen sys-JWT. REVEAL-prompt + 30 s auto-mask + audit-event sys.token.viewed. Inga nya tokens utfärdas — samma JWT som redan finns i AsyncStorage. ✅ PL-T317 |