* feat(auth): OIDC role mapping + login policy — phase 2 (#798) Role mapping: configurable dot-path roles claim (Keycloak realm_access.roles, Authentik/Pocket ID groups, Entra roles), IdP-value → PicPeak-role mapping table validated against the roles table, re-evaluated on every SSO login with highest-priority-wins on multiple matches. The last active super_admin is never demoted. Optional require-mapped-role policy refuses logins whose token maps to no role (sso_error=no_role). Login policy: oidc_disable_local_login makes the API refuse password logins (403 LOCAL_LOGIN_DISABLED) and the login page render SSO-only; only effective while SSO is enabled+configured, and OIDC_BREAK_GLASS=true always re-opens local login. Public settings expose the EFFECTIVE flag only. Settings UI: Role-mapping card (claim path, mapping rows editor, strict toggle) and Login-policy card with break-glass hint, EN+DE. 14 new integration tests over the mock IdP. * fix(auth): harden phase-2 review findings (#798) - memoize the scrypt-derived OIDC key and serve /public/settings from a 10s-TTL flag cache — the unauthenticated endpoint no longer pays a 13-key config read + blocking scryptSync per request (login route still checks uncached) - make the last-super-admin demotion guard atomic (FOR UPDATE on the active super rows) — concurrent mapped callbacks could previously both count 2 and demote both supers - own-property lookup in role mapping: IdP values like `constructor` now count as unmapped instead of corrupting the roles query - SsoTab clears oidc_disable_local_login in the same save that turns SSO off — the full-form payload otherwise hit the server-side 400 * fix(auth): guarantee break-glass reachability for SSO-only mode (#798) - wire OIDC_BREAK_GLASS and OIDC_ENCRYPTION_KEY through the quick-start docker-compose.yml env allowlist (production compose already passes .env via env_file) and document both in .env.example - refuse enabling oidc_disable_local_login unless an active local-password super_admin exists: OIDC_BREAK_GLASS only re-opens the password route, which OIDC-owned accounts can never use, and settings.edit is super_admin-only — an all-OIDC instance would be unrecoverable during an IdP outage * fix(auth): close SSO-only lockout gaps from review round 3 (#798) - role sync never demotes the last active LOCAL-password super_admin (an OIDC-owned super does not count as break-glass), and isLocalLoginDisabled() disarms itself when no such account remains — self-healing against manual demotion/deactivation/deletion paths - the local-super save-time check now validates the MERGED state, so re-enabling SSO with a stored disable flag is checked too - ALL oidc_* keys are reserved from the generic settings upserts/reads (prefix match) — policy and mapping invariants can only go through the validated PUT /sso - /admin/login/mfa re-checks the policy so an mfa_pending token minted before the flip cannot complete into a local session --------- Co-authored-by: Paul Nothaft <[email protected]>
This commit is contained in:
co-authored by
Paul Nothaft
parent
ad326da35c
commit
f8a95d29d2
@@ -10,6 +10,14 @@ NODE_ENV=production
|
||||
# Generate one with: openssl rand -base64 64
|
||||
#JWT_SECRET=your_very_long_random_jwt_secret_here
|
||||
|
||||
# OIDC SSO for admins (#798) — configured in the admin UI; only these two
|
||||
# values live in the environment:
|
||||
# Key encrypting the OIDC client secret at rest (defaults to JWT_SECRET).
|
||||
#OIDC_ENCRYPTION_KEY=
|
||||
# Break-glass: 'true' re-enables local password login even while the SSO
|
||||
# settings disable it (recovery when the IdP is down or misconfigured).
|
||||
#OIDC_BREAK_GLASS=false
|
||||
|
||||
# Auth cookie Secure flag
|
||||
# unset - default: follows NODE_ENV (production=true, dev=false)
|
||||
# true - always set Secure (HTTPS-only cookies; breaks plain-HTTP access)
|
||||
|
||||
Reference in New Issue
Block a user