Skip to content

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_admin permission.
  • An OIDC app registered at the IdP — see provider-specific sections below.

Quick steps (any provider)

  1. Settings → 🔑 Single Sign-On (OpenID Connect).
  2. Toggle Enable OIDC sign-in.
  3. Fill in:
  4. 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
  5. Client ID — application/client ID from the IdP.
  6. Client Secret — paste the secret. Leave blank on subsequent saves to keep the existing value.
  7. Sign-in Button Label — what shows on the login page (default: Sign in with Microsoft).
  8. 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).
  9. Email Claim — usually email. Entra often needs preferred_username.
  10. Groups Claim — usually groups; must match whatever claim name your IdP puts group membership in for group → role mapping to work.
  11. JWT TTL (minutes) — how long an MFCloud session JWT is valid before /api/auth/refresh has to renew it. Lower = faster to notice an IdP-side revoke; default 15.
  12. 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:

The bullet-point summary below is enough if you've done OIDC app registration before.

Microsoft Entra ID

  1. Azure Portal → Entra ID → App registrations → New registration.
  2. Redirect URI (Web): https://<your-mfcloud-host>/api/auth/oidc/callback.
  3. After creation → Certificates & Secrets+ New client secret. Copy the Value (not Secret ID).
  4. Token configuration+ Add optional claim → tick email if you want the canonical email.
  5. API permissions → ensure openid, email, profile are granted (default).
  6. Authentication → Front-channel logout URL = https://<your-mfcloud-host>/ so logout returns to MFCloud.

Google Workspace

  1. console.cloud.google.com → APIs & Services → Credentials → + Create Credentials → OAuth client ID.
  2. Application type: Web application.
  3. Authorized redirect URI: https://<your-mfcloud-host>/api/auth/oidc/callback.
  4. After creation, copy the Client ID and Client secret.
  5. Google has no end_session_endpoint — logout clears MFCloud only.

Okta

  1. Admin console → Applications → Create App Integration → OIDC, Web Application.
  2. Sign-in redirect URI: https://<your-mfcloud-host>/api/auth/oidc/callback.
  3. Sign-out redirect URI: https://<your-mfcloud-host>/.
  4. 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.

  1. ➕ Add Mapping.
  2. 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.
  3. MFCloud Role, Priority (lower number checked first).
  4. 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_endpoint at 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/start generates state, nonce, and a PKCE S256 verifier; signs them into a 10-min HMAC cookie; 302s to the IdP.
  • /api/auth/oidc/callback validates 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 kid miss).

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