Wheelhouse docs

Single sign-on#

Wheelhouse can sign people in through an OIDC identity provider. When it is set up, the sign-in screen offers a Continue with … button, named after the provider, above the password form — disabled, with "The identity provider is not answering." under it, when the provider does not answer. The Account page shows a Single sign-on panel, and on the Users page an account's Identity provider ID links it to a person at the provider. The provider decides who somebody is. Wheelhouse decides what they may do.

Passwords, two-factor authentication, API tokens and the break-glass token all keep working when single sign-on is on. A router that can only be entered through an identity provider is one provider outage away from being unmanageable.

What the web interface manages, and what it does not#

Managed in the web interfaceOnly by the agent's options
Linking an account to a person at the provider, and unlinking it — Users and AccountThe provider's address, the client ID and the client secret
Seeing whether the provider answers — AccountWhich claim becomes the username
Seeing who is linked — the Single sign-on column on UsersWhich groups map to which role
Signing in, and signing outWhether an unknown identity gets an account at all

The provider's settings cannot be changed through the web interface that the provider gates. They are options on the agent's service, changed at the router's console, and the agent checks them when it starts: a half-configured provider stops the agent from starting, rather than failing every sign-in.

The options#

OptionDefaultWhat it does
--oidc-issuer—The provider's issuer address. Must be an absolute http(s) URL, and needs a client ID.
--oidc-client-id—The client ID. Needs an issuer.
--oidc-client-secret-file—A file holding the client secret, which single sign-on requires. --oidc-client-secret exists too and is visible in the process list; prefer the file.
--oidc-redirect-urlworked out per requestThe exact callback address registered at the provider. It must end in /api/oidc/callback.
--oidc-scopesopenid profile email groupsThe scopes requested. openid is added if you leave it out.
--oidc-username-claimpreferred_usernamepreferred_username, email, name or sub.
--oidc-groups-claimgroupsWhere group membership is, for providers that put it elsewhere.
--oidc-admin-groups—Comma-separated groups that map to admin. With this and the next one empty, groups set no role at all.
--oidc-operator-groups—Comma-separated groups that map to operator.
--oidc-default-roleviewerThe role for a new account outside every mapped group.
--oidc-provisiontrueCreate an account the first time an unknown identity signs in.
--oidc-link-by-emailfalseLink an identity to an existing account by email address — and only when the provider asserts email_verified.
--oidc-labelAuthentikThe provider name on the sign-in button.
--oidc-ca-file—A PEM root certificate to trust for the provider, instead of the system's.
--oidc-post-logout-redirect—A registered address for the provider to send the browser to after signing out.

The sign-in flow#

  1. GET /api/oidc/login creates a state value and a PKCE verifier, keeps them for ten minutes, and sends the browser to the provider.
  2. The provider sends the browser back to GET /api/oidc/callback.
  3. The agent looks the state up and uses it up. An unknown or expired state is refused before anything is exchanged.
  4. The authorisation code is exchanged with the PKCE verifier, the ID token is verified, and its nonce is checked against the one this attempt used.
  5. The claims are matched to an account (below). If any step fails, the browser goes back to the sign-in screen, which shows a short reason; the provider's own error description is logged and never passed on.
  6. A session is opened, marked as single sign-on, with the provider's ID for the person and the ID token — kept only so that signing out can end the provider's session too, and only as long as the session lasts.

The sign-in is recorded in the audit log as login (oidc), with the issuer, the provider's ID for the person, and the groups the provider sent.

How an identity becomes an account#

In this order:

  1. By the provider's ID. An account whose identity provider ID matches the ID token's sub is the account. That ID is the only link Wheelhouse trusts by default: it is the provider's own unchanging identifier, where an email address is a claim the provider could give somebody else. The match is case-sensitive, because the ID is opaque.
  2. By verified email, if that is turned on. With --oidc-link-by-email, an identity carrying an email address and email_verified: true is linked to the account with that address, and the link is audited as oidc-link. An account already linked to a different identity is refused. It is off by default: linking on an unverified address would make the provider's self-service a way into an existing account.
  3. By creating an account, when --oidc-provision is on. An account is created with the name taken from the claims, the mapped or default role, and no password — the provider is the credential. Audited as oidc-provision.
  4. Otherwise refused, with "this identity is not linked to a Wheelhouse account".

The username comes from the chosen claim, falling back through the others, cut at the first @, reduced to letters, digits, dots, underscores and hyphens, and cut to 48 characters.

Group-to-role mapping#

Mapping is opt-in. With neither --oidc-admin-groups nor --oidc-operator-groups set, the provider's groups say nothing about roles, and an existing account keeps the role it has. There is no group option for the approver role.

With either set, group names are matched regardless of case, admin is checked before operator so that somebody in both lists is never given the lower role by ordering, and an identity in neither gets --oidc-default-role.

A mapped role is applied to the account at every sign-in, so a change at the provider takes effect the next time the person signs in. Two rules hold:

  • The last admin is never demoted by a mapping. The admins are counted and the change is made in one step, and a mapping that would leave no admin is logged and not applied.
  • A role change ends the account's sessions, exactly as it does when an admin changes the role on the Users page. A session never carries an out-of-date role.

Two-factor authentication and single sign-on#

Require two-factor authentication, on Agent settings, does not apply to a single sign-on session. The second factor for these accounts belongs to the provider, which is where it is set up; a second secret stored by Wheelhouse would be a weaker factor for the agent to keep. Requiring a multi-factor claim (acr or amr) from the provider is not implemented.

Signing out#

Signing out ends the Wheelhouse session. When the session came through the provider and the provider publishes an end-session address, the web interface then sends the browser there, with the ID token as the hint, so the provider can end its own session too. The address to return to afterwards is added only when --oidc-post-logout-redirect is set, because a provider accepts only an address registered with it.

When the provider publishes no end-session address, signing out of Wheelhouse leaves the provider's session open, and the next Continue with … signs the person straight back in. Removing somebody's access at the provider does not end a Wheelhouse session already open: it takes effect at their next sign-in.

Unlinking#

Unlink, on the Account page, detaches your own account. It is disabled for an account with no password of its own, because unlinking the only way in would leave nobody able to sign in as it. An admin can unlink somebody else by emptying their Identity provider ID on the Users page, which is audited as oidc-unlink-user; your own unlink is audited as oidc-unlink.

For automation, POST /api/auth/oidc/unlink answers 404 when the account is not linked, 409 when it has no password — "this account has no password of its own — set one before unlinking single sign-on" — and otherwise clears the link.

What an admin can see#

GET /api/admin/oidc (admin only) returns the whole configuration except the client secret: the issuer, the client ID, the scopes, the username and groups claims, both group lists, the default role, whether accounts are created and whether email linking is on, the redirect address, whether the provider answers, the provider's end-session address, and the list of linked accounts with their provider IDs and roles. That last one answers who can sign in through the provider.

See also#

  • Users — linking an account to a person at the provider, and the refusals around it.
  • Account — the panel a person sees, and unlinking their own account.
  • Roles — what a mapped role gives.
  • Accounts and sessions — the concept.
  • Authenticating — the session a sign-on produces.
  • Every flag — every option on this page, in one table.

Updated 2026-09-18 manual sso oidc accounts