Skip to main content
The SSO button uses the OIDC configuration an admin enters in xpander Chat under Platform > Organization > Access. Google and GitHub social buttons are a separate path (GoTrue providers, supabase.auth.extraEnv in the chart).

How a sign-in works

  1. The user clicks SSO and types their work email under Sign in with SSO. The email only picks the organization and is never sent to the IdP.
  2. client-auth redirects the browser to your IdP with scopes openid profile email plus any you add. The client is confidential (client_id and client_secret, no PKCE).
  3. The IdP redirects back to https://<app-host>/oidc/<organization-id>/callback with a code.
  4. client-auth exchanges the code and reads the user from the IdP’s userinfo endpoint, from inside the cluster. The IdP must be reachable from the pods, not only from browsers.
  5. xpander finds or creates the user by email in GoTrue and starts the session.
Keycloak sign-in page titled Sign in to your account with Username or email and Password fields

After the SSO button: the identity provider's own sign-in page, here Keycloak. Shown with sample data.

What to configure

In your identity provider

Give the pods a routable path to the IdP. Node egress addresses change, so an IP-restricted public entry refuses the token and userinfo calls even when the browser redirect works. Use a private-zone record and an internal load balancer, for example keycloak.internal.<domain> on an internal ingress class, resolved so the issuer hostname still matches. For agent pre-authentication, the client needs extra settings. Turn that switch on only after sign-in works. Keycloak and preferred_username. Keycloak sends the account username, so user creation fails with Unable to validate email address: invalid format. Map the email onto it:
1

Open the mapper

Client scopes, the client’s dedicated scope, Add mapper, By configuration, User Property.
2

Map email to preferred_username

Name preferred_username, Property email, Token Claim Name preferred_username, type String, “Add to userinfo” on.
3

Retry

Retry the SSO sign-in.
Or set “Email as username” under Realm settings, Login. Releases with the September 2026 edge-functions image or later read email first, but add the mapper anyway: it works on every release.

In xpander (Platform > Organization > Access)

In the chart

client-auth is published as client-auth.<domain> and also serves skill OAuth redirects.

When it fails

Logs: the client-auth pod (token and userinfo), the auth (GoTrue) pod (user creation) and the edge-runtime pod (oidc-callback).

Group sync with Keycloak

IdP groups map to xpander user groups in four steps:
  1. Create a groups client scope. Client scopes, Create client scope, name groups, type Optional. Add a Group Membership mapper: name groups, Token Claim Name groups, Full group path off, Add to userinfo on. Then add groups to your xpander client as Optional. A mapper on the dedicated scope alone is not enough: Keycloak answers error=invalid_scope.
  2. Request the scope. Under Additional sign-in scopes, Add groups, then Save configuration. xpander records claim groups from userinfo.
  3. Sign in once, so xpander sees the group values.
  4. Link a group. Platform > Organization > Members & groups, the group’s menu, Link SSO groups. Pick a seen value or Add a group by name or ID with Add to list, then Save links. The row shows an SSO badge.
Members join the xpander group at their next sign-in.
Members & groups on the Groups tab with the Link SSO groups to Engineering panel open: no groups received yet, an Add a group by name or ID field with Add to list, and Save links

Link SSO groups, before the identity provider has sent any groups: add one by name or ID, then Save links. Shown with sample data.

GET /oidc/<org-id>/groups exists for Okta and Entra ID only. With Keycloak it answers 400, which is harmless.

Running Keycloak yourself

Give the pod at least 2 GiB when you use kcadm.sh (each call starts a second JVM). Install Keycloak after its database, role and admin secret exist, or the release deadlocks.

Agent pre-authentication

Lets an agent act with the asking person’s own permissions where systems allow. xpander exchanges the person’s sign-in token (OIDC token exchange, RFC 8693) for a token scoped to the target system. At the IdP, the xpander client also needs:
  • Standard token exchange: on Keycloak 26, standard.token.exchange.enabled=true.
  • Direct access grants enabled.
  • An audience client for the target system.
  • A client scope with an audience mapper for that client.
In xpander, the Service app card takes the Service app client ID, Service app client secret and Directory key. The Agent pre-authentication card has the Enable agent pre-authentication switch, Audiences (one per system, for example acme-inventory) and Token exchange scopes (for example the audience’s scope and openid). Click Save configuration.

Per-person sign-in to MCP connectors

An MCP connector can sign each person in through this IdP: Per-person sign-in for MCP connectors.

Next steps

Sign each person in to MCP connectors

Per-person permissions.

Check what the license enables

SSO is a license feature.