fix(oidc): local-credential lockout, session hydration, split-origin gaps (codex round 3)

- OIDC-owned accounts can never authenticate locally: the password
  login rejects auth_provider='oidc' rows outright (generic 401), and
  the super-admin password reset refuses them with a clear message —
  previously a reset would have minted a local password bypassing the
  IdP's MFA/access policies
- /auth/session now returns a full adminUser payload (role join) and
  AdminAuthContext hydrates user state from it: an SSO redirect
  establishes the session without any login JSON, which left the header
  identity blank and current-admin form defaults empty
- the /sso/login error path redirects absolute to the frontend base
  (same split-origin reasoning as the callback)
- docker-compose.yml passes API_URL through to the backend (production
  compose uses env_file and needs nothing; dev compose is gitignored)
- authSession.symmetry test mock taught the joined admin lookup
  (leftJoin, prefixed columns, aliases) — the route change made the old
  mock throw, which read as "table missing, trust token"

Tests: new case pins that a known-good password on an OIDC-owned row
still gets 401. 14/14 OIDC, 13/13 symmetry.
This commit is contained in:
Paul Nothaft
2026-07-16 10:07:59 +02:00
parent 7f7d38a57f
commit e91c7deaa4
6 changed files with 88 additions and 9 deletions
+3
View File
@@ -60,6 +60,9 @@ services:
- SMTP_PASS=${SMTP_PASS}
- EMAIL_FROM=${EMAIL_FROM:[email protected]}
- FRONTEND_URL=${FRONTEND_URL:-http://localhost:3000}
# Public API origin for split-origin deployments (#798 SSO redirect_uri).
# Empty = same origin as FRONTEND_URL (the standard proxied setup).
- API_URL=${API_URL:-}
- ADMIN_URL=${ADMIN_URL:-http://localhost:3001}
- TZ=${TZ:-UTC}
- STORAGE_PATH=/app/storage