Skip to content

SSO Runbook — Keycloak / Authentik (self-hosted)

End-to-end setup for sign-in with a self-hosted OIDC provider. ~10 minutes from a clean Keycloak realm to a working "Sign in with Keycloak" button on the MFCloud console. Authentik follows the same shape — it's noted inline wherever its screens use different names.

What you'll end up with

  • A dedicated realm (Keycloak) or application (Authentik) that only MFCloud uses.
  • A confidential OIDC client with a redirect URI registered.
  • A client ID + secret you'll paste into MFCloud's Settings → SSO.

Prerequisites

  • Admin access to your Keycloak or Authentik instance.
  • MFCloud master reachable at a stable HTTPS URL from both the IdP (server-to-server token exchange) and the browser doing the sign-in.

Why this runbook exists

Unlike Entra/Google/Okta, a self-hosted IdP has no fixed tenant URL — you're both the IdP admin and the MFCloud admin, so a couple of things that a SaaS IdP enforces for you become your own responsibility to get right:

  • The Issuer URL must be reachable from the MFCloud master's server side, not just from your browser. If Keycloak/Authentik lives behind a different network segment than the master, the discovery-doc fetch (/api/auth/oidc/start) will fail even though the browser can reach the IdP's login page fine.
  • Realms/applications you spin up for testing are easy to leave behind. Delete the test realm (or the whole VM, if it was disposable) once you've confirmed sign-in works — see Cleanup.

Step 1 — Create a realm (Keycloak) / application (Authentik)

Keycloak:

  1. Admin console → realm dropdown (top-left) → Create Realm.
  2. Realm name = mfcloud (or whatever you like) → Create.

Authentik: create a new Application + Provider pair instead — Authentik doesn't have a separate realm concept; skip to Step 2 and pick OAuth2/OpenID Provider as the provider type.

Step 2 — Create the OIDC client

Keycloak:

  1. Clients → Create client.
  2. Client type = OpenID Connect, Client ID = mfcloud-consoleNext.
  3. Client authentication = On (this makes it a confidential client — you need a secret) → Next.
  4. Valid redirect URIs = https://<your-mfcloud-host>/api/auth/oidc/callbackSave.
  5. Credentials tab → copy the Client secret.

Authentik: Provider type OAuth2/OpenID Provider, Client type = Confidential, Redirect URIs = the same callback URL, Signing Key = any available RSA key. The client ID/secret are shown on the Provider's detail page after creation.

Step 3 — Create a test user

Both platforms ship with no default users besides the bootstrap admin, and that admin account lives in a different realm/context than your new client — create a normal user to sign in with:

Keycloak: Users → Add user → fill in Username, Email, First name, Last nameCreateCredentials tab → Set password (untick Temporary so it doesn't force a reset on first login).

Fill in First/Last name, not just email

If Keycloak's realm has the default User Profile config (first/last name marked required), a user created without them gets bounced into a Verify Profile page mid-login instead of reaching MFCloud's callback — the flow doesn't fail, it just stalls on an extra Keycloak screen the first time. Filling both fields in at creation avoids it entirely.

Authentik: Directory → Users → Create, then set a password via the user's Set password action.

Step 4 — Paste into MFCloud

In the MFCloud console:

  1. Settings → 🔑 Single Sign-On (OpenID Connect).
  2. Fill in:
  3. Issuer URL — Keycloak: https://<your-keycloak-host>/realms/mfcloud (note /realms/<name>, not /auth/realms/<name> — that older path was dropped in Keycloak 17+). Authentik: https://<your-authentik-host>/application/o/<slug>/.
  4. Client ID — from Step 2.
  5. Client Secret — from Step 2.
  6. Sign-in Button LabelSign in with Keycloak (or your IdP's name).
  7. Default RoleTenant Viewer.
  8. Email Claimemail.
  9. Groups Claimgroups (Keycloak includes this by default for realm roles/groups the client's scope allows; Authentik needs a Scope Mapping added to the provider to populate it).
  10. Enable OIDC sign-in ✓.
  11. Save SSO Settings.

Step 5 — Test it

  1. Sign out of MFCloud.
  2. Login page → Sign in with Keycloak.
  3. Redirects to your IdP's own login form → authenticate → back to MFCloud dashboard.
  4. User avatar should show the test user's email.

Troubleshooting

Symptom Cause Fix
Login form loads, but after submitting you land on a Keycloak "Update Account Information" / "Verify Profile" page instead of MFCloud Test user is missing a required profile field (usually first/last name) Fill in the missing field(s) on that page once, or set them on the user ahead of time (Step 3)
400: Stale or missing OIDC flow cookie even though you clicked the button seconds ago You (or a test script) hit the master over plain HTTP. The flow cookie is Secure-flagged and browsers/HTTP clients never send it over an unencrypted connection Always test through the real HTTPS front end (Caddy), never a bare :8000 app port
Discovery fails / /api/auth/oidc/start 502s The MFCloud master container can't reach the IdP's /.well-known/openid-configuration — common if the IdP is on an isolated test network Confirm curl <issuer>/.well-known/openid-configuration succeeds from the master's own host, not just your browser
Works for you, fails for a colleague on a different network Issuer URL points at an address only reachable from your machine (e.g. a hosts file override) Use a real, universally-resolvable hostname for anything beyond a one-person test

Cleanup

Self-hosted test IdPs tend to be disposable — a Keycloak/Authentik instance spun up just to validate the OIDC integration, not a production identity system. Once you've confirmed sign-in works:

  1. Settings → SSO → Enable OIDC sign-in ✗ (or point it at your real IdP instead).
  2. Delete the test realm/application at the IdP.
  3. Tear down the VM/container it was running in, if it was purpose-built for this test.

See also