SSO and two-factor authentication
Sign in through your identity provider, and require a second factor on every account.
Two independent ways to strengthen a login. SSO moves the question of who you are to an identity provider you already run. Two-factor keeps the local password but demands a second proof. They compose: an install can require both.
Single sign-on
Three provider shapes ship, configured by a platform administrator under Admin → Configuration:
| Provider | Needs |
|---|---|
| A client ID and secret. Endpoints are already known, so no discovery round trip. | |
| GitHub | A client ID and secret on an OAuth app. Scopes read:user user:email. |
| OIDC | An issuer URL plus client ID and secret — Keycloak, Authentik, Okta, Entra, anything that publishes a discovery document. A display label names the button. |
A provider is live only when both its ID and its secret are set — a half-configured provider shows no button rather than a button that fails. Secrets are stored encrypted and never returned by the configuration API.
id_token, and the primary address is often private on the profile — it only appears, with a verification flag, behind a second endpoint. That is the one reason it needs its own handling; Google and your own issuer are the same protocol underneath.How an external identity becomes a local account
The provider’s immutable subject — Google’s sub, GitHub’s numeric id — is what identifies the person, never the email. GitHub logins are renameable, and a renamed account must not collide with a new one taking the old name.
- 01The subject already maps to a local account → that account signs in. Nothing else is consulted.
- 02No mapping yet, and the address matches an existing account the provider asserts is verified → the identity is linked to it.
- 03No mapping and no matching account → a new account is created, but only if signup through SSO is enabled.
Two settings govern the third step, and they answer different questions:
- Allow signup
- Whether an SSO login may create an account. Off by default: turning on Google SSO must not thereby let every Gmail address on earth register. With it off, SSO signs in accounts that already exist.
- Allowed domains
- A list like
acme.com. Empty means no restriction. A non-empty list is a hard gate on the exact domain — a lookalike such asacme.com.attacker.netdoes not pass.
Account creation through SSO obeys everything local registration obeys: the license seat ceiling, and admin approval if the install requires it. “They came in through Google” does not bypass a human in the loop.
Linking and unlinking
From Settings → SSO, an existing account can attach further identities — sign in by password today, by Google tomorrow, both being the same account. Each external identity maps to exactly one local account, so two people can never both sign in as the same provider user and land in different places.
Two-factor authentication
A time-based one-time code (TOTP) from any authenticator app — 1Password, Aegis, Google Authenticator, Bitwarden. Enrollment is three moves:
- 01Settings → Security → Enable two-factor. A secret and a QR code appear.
- 02Scan it, then type the six digits your app shows. The secret is only committed once a valid code proves the app is set up correctly.
- 03Ten backup codes are returned. Shown once. Store them somewhere that is not the phone holding the authenticator.
Each backup code carries 80 bits of entropy and is single-use — a consumed code stops working. Dashes and spaces are stripped before comparison, so how you type it does not matter.
Disabling requires your password and a current code — a stolen session alone cannot turn the second factor off. Re-enrolling means disabling first: rotating the secret in place would leave a window where old and new both work.
apps:env, instances:ssh or platform permissions first. Those are the accounts where a stolen password costs you production secrets or a root shell — see roles and permissions.Every enrollment, disable and failed attempt lands in the audit trail, with the IP address it came from.