Skip to main content

Admin SSO (OIDC)

The admin console supports single sign-on via any OpenID Connect provider (Google Workspace, Entra ID, Okta, Dex, …) using the Authorization Code flow with PKCE (S256), a state CSRF token and a nonce. The feature is opt-in: with no configuration the console stays on the password flow, unchanged.

Enabling​

All four values must be set — anything less keeps SSO off:

Env / config.yaml (admin:)Meaning
YABANIN_ADMIN_OIDC_ISSUER / oidc_issuerProvider issuer URL, e.g. https://accounts.google.com
YABANIN_ADMIN_OIDC_CLIENT_ID / oidc_client_idOAuth client id
YABANIN_ADMIN_OIDC_CLIENT_SECRET / oidc_client_secretOAuth client secret
YABANIN_ADMIN_OIDC_REDIRECT_URL / oidc_redirect_urle.g. https://admin.example.com/auth/oidc/callback

The provider's discovery document and JWKS are fetched at startup; a failure logs loudly and keeps the console on the password flow — never a half-working SSO mount.

The flow​

  1. GET /auth/oidc/login — issues a one-time state/nonce/PKCE triple in a 10-minute HttpOnly+Secure cookie (SameSite=Lax: the callback arrives as a top-level navigation) and redirects to the provider.
  2. GET /auth/oidc/callback — constant-time state check, code exchange with the PKCE verifier, ID token verification (signature against the provider's JWKS, issuer, audience, expiry, nonce).
  3. User mapping — fail-closed: the verified email must match an existing active admin user. SSO never provisions accounts, never widens roles; the issued session is byte-for-byte the password-flow session (same HMAC cookie, same IsRoot).

The one-time cookie is cleared on every callback outcome — its secrets are single-use by construction.

Security contract​

  • email_verified is required. A provider asserting an email without verifying it does not log anyone in.
  • No auto-provisioning. Unknown emails get the same refusal as disabled accounts — no user enumeration, no signup-by-SSO.
  • Nonce binds the ID token to this login. A token minted for another session cannot be replayed.
  • No open redirects. Success always lands on /; the login redirect always targets the configured issuer.
  • The local part of emails never reaches the logs; only the domain is recorded on a mapping refusal.