Configure OIDC / SSO¶
OpenID Connect single sign-on — corporate users sign in with their existing Microsoft Entra ID, Google Workspace, or Okta account. Same JWT downstream, so all RBAC and permission checks work unchanged.
Why use it¶
- One password (the IdP's) instead of three (local + LDAP + per-product).
- MFA / conditional access enforced at the IdP automatically apply.
- Offboarding = disable the user in the IdP, MFCloud access dies on next login.
- Zero password-reset tickets — that's the IdP's problem.
Prerequisites¶
- Master reachable from the IdP at a stable URL (the redirect URI).
- Operator has
global_adminpermission. - An OIDC app registered at the IdP — see provider-specific sections below.
Quick steps (any provider)¶
- Settings → 🔑 Single Sign-On (OpenID Connect).
- Toggle Enable OIDC sign-in.
- Fill in:
- Issuer URL — the IdP's discovery base.
- Entra:
https://login.microsoftonline.com/<tenant-id>/v2.0 - Google:
https://accounts.google.com - Okta:
https://<your-domain>.okta.com
- Entra:
- Client ID — application/client ID from the IdP.
- Client Secret — paste the secret. Leave blank on subsequent saves to keep the existing value.
- Sign-in Button Label — what shows on the login page (default: Sign in with Microsoft).
- Default Role — the role assigned to new users on first SSO login (and to anyone whose groups don't match a row in Group → Role Mapping below).
- Email Claim — usually
email. Entra often needspreferred_username. - Groups Claim — usually
groups; must match whatever claim name your IdP puts group membership in for group → role mapping to work. - JWT TTL (minutes) — how long an MFCloud session JWT is valid before
/api/auth/refreshhas to renew it. Lower = faster to notice an IdP-side revoke; default 15. - Save SSO Settings.
The login page now shows a "Sign in with X" button below the local form. Click → IdP authenticate → land back in the console with a fresh JWT.
Register the app at your IdP¶
Per-IdP step-by-step runbooks — pick the one that matches your provider:
- Microsoft Entra ID (Azure AD) — full walkthrough including front-channel logout and groups claim.
- Google Workspace — OAuth consent screen + client setup.
- Okta — OIDC app + group claim mapping.
- Keycloak / Authentik (self-hosted) — realm/application + client setup, including the gotchas specific to standing up your own test IdP.
The bullet-point summary below is enough if you've done OIDC app registration before.
Microsoft Entra ID¶
- Azure Portal → Entra ID → App registrations → New registration.
- Redirect URI (Web):
https://<your-mfcloud-host>/api/auth/oidc/callback. - After creation → Certificates & Secrets → + New client secret. Copy the Value (not Secret ID).
- Token configuration → + Add optional claim → tick
emailif you want the canonical email. - API permissions → ensure
openid,email,profileare granted (default). - Authentication → Front-channel logout URL =
https://<your-mfcloud-host>/so logout returns to MFCloud.
Google Workspace¶
- console.cloud.google.com → APIs & Services → Credentials → + Create Credentials → OAuth client ID.
- Application type: Web application.
- Authorized redirect URI:
https://<your-mfcloud-host>/api/auth/oidc/callback. - After creation, copy the Client ID and Client secret.
- Google has no
end_session_endpoint— logout clears MFCloud only.
Okta¶
- Admin console → Applications → Create App Integration → OIDC, Web Application.
- Sign-in redirect URI:
https://<your-mfcloud-host>/api/auth/oidc/callback. - Sign-out redirect URI:
https://<your-mfcloud-host>/. - Assignments: pick the groups that should have console access.
Group → Role Mapping¶
Below the main SSO form, an IdP Group → MFCloud Role Mapping table maps IdP group membership to an MFCloud role — same UX pattern as LDAP's group mapping, separate table.
- ➕ Add Mapping.
- IdP Group ID — the value your IdP's Groups Claim actually sends: an object ID/GUID for Entra,
[email protected]for Google Workspace, or a group name for Okta — see each provider's runbook for the exact value. - MFCloud Role, Priority (lower number checked first).
- Save Group Mappings.
Users whose groups match no row fall through to the page's Default Role.
Logout Behavior¶
Signing out of MFCloud always ends the local session. Whether it also ends the session at the IdP ("RP-initiated logout") depends on the provider:
- Entra ID — if you configured a Front-channel logout URL (runbook), Microsoft calls it on sign-out, so both sessions end together.
- Okta — the Sign-out redirect URI achieves the same.
- Google Workspace — Google's OIDC discovery document doesn't advertise an
end_session_endpointat all, so MFCloud sign-out can only ever clear the local session; the user stays signed into Google in the same browser (use Manage your Google account → Sign out to also break that).
Behind the scenes¶
/api/auth/oidc/startgeneratesstate,nonce, and a PKCE S256 verifier; signs them into a 10-min HMAC cookie; 302s to the IdP./api/auth/oidc/callbackvalidates the cookie, exchanges the auth code for an ID token, verifies the JWT against the IdP's JWKS, looks up or auto-creates the user by(oidc_issuer, oidc_subject).- Discovery doc + JWKS cached for 60 min; key rotation handled automatically (cache busts on
kidmiss).
Safety net — local always wins¶
Local sign-in (/api/login) is tried first regardless of OIDC state — misconfiguring SSO can't lock out local accounts. The local admin account's Super Admin rights come from its seeded RBAC role row (not a hardcoded username override, so it can be renamed or demoted like any other account), re-derived on every request the same as any user's role.
See also¶
- Troubleshooting → SSO callback 400
- Configure LDAP / AD — same coexist-with-local model.