> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xpander.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Identity providers

> Sign-in options per deployment, the OIDC client to create in Keycloak, Okta or Entra ID, group sync, and agent pre-authentication so agents act with a person's own permissions where systems allow.

## Sign-in per deployment

| Deployment               | Sign-in                                                                                                                                                                  |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| xpander cloud and Hybrid | Email code, Google, GitHub, or your identity provider over OIDC (**Settings > OIDC (SSO)**, an enterprise feature). Registration on xpander cloud is self-serve and free |
| Air-Gapped               | Inside the perimeter: a bootstrap admin password, email codes, or your OIDC provider                                                                                     |

Roles are **Admin** and **Team member** (**Settings > Team**); groups under **Settings > User groups** can follow the identity provider's groups. See [Govern every agent](/run/govern#who-may-do-what).

## The OIDC client

Create a confidential OIDC client for xpander at the identity provider:

| Setting       | Value                                                                                                                                                                                                                                        |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Client type   | Confidential, client authentication on                                                                                                                                                                                                       |
| Flow          | Authorization code (Keycloak: "Standard flow")                                                                                                                                                                                               |
| Redirect URIs | Three exact URIs, not a wildcard: a sign-in URI (`.../oidc/<org-id>/callback`), a sign-out URI (`.../oidc/<org-id>/logout`) and an initiate-login URI (`.../oidc/<org-id>/login`); Settings > OIDC > Redirect URIs shows and copies each one |
| Web origins   | `https://<app-host>`                                                                                                                                                                                                                         |
| Scopes        | `openid`, `profile`, `email`. For group sync, a client scope named `groups` with a Group Membership mapper, assigned to the client as optional                                                                                               |
| Claims        | `email` must be present in userinfo and be the user's address                                                                                                                                                                                |

**Settings > OIDC** in xpander holds the issuer URL, exactly as it appears in the discovery document, including any context path. A Keycloak instance under `/auth` uses `https://idp.example.com/auth/realms/<realm>`. It also holds the client ID and secret, and optional extra scopes. An optional **API service app** card adds a second client's ID and secret, plus a generated **Directory key**. Directory reads and agent token exchange use this second app; Okta needs key-pair authentication on it. The page also has the agent pre-authentication switch.

The token and userinfo calls run from inside the cluster, so the IdP must be reachable from the pods, not only from the browser; an IP-restricted public entry point refuses them.

<Frame caption="Settings > OIDC: issuer, client, scopes and the API service app card. Shown with sample data.">
  <img src="https://mintcdn.com/xpanderai-099931d1/OdLxX9OyFVicAV0l/images/verify/oidc-1.png?fit=max&auto=format&n=OdLxX9OyFVicAV0l&q=85&s=a34f54d7350f7a3214786c87bbe674ac" alt="OIDC identity provider fields" width="1440" height="900" data-path="images/verify/oidc-1.png" />
</Frame>

<Frame caption="Settings > OIDC: the three redirect URIs and the Agent pre-authentication card with its switch, Audiences and Token exchange scopes. Shown with sample data.">
  <img src="https://mintcdn.com/xpanderai-099931d1/OdLxX9OyFVicAV0l/images/verify/lab-oidc-preauth.png?fit=max&auto=format&n=OdLxX9OyFVicAV0l&q=85&s=e95a57e86f846f9db25aa4d311a464e4" alt="OIDC settings showing Sign-in, Sign-out and Initiate login redirect URIs, then an Agent pre-authentication card with the Enable agent pre-authentication switch on, one audience, two token exchange scopes and a Save configuration button" width="1440" height="900" data-path="images/verify/lab-oidc-preauth.png" />
</Frame>

## Group sync

Group membership from the IdP maps to xpander user groups through a `groups` claim. The recipe, for Keycloak:

1. At the IdP, a **client scope named `groups`** with a **Group Membership** mapper (claim `groups`, full path off, in userinfo), assigned to the xpander client as an optional scope. A mapper on the client alone is not enough: xpander requests `scope=groups`, and Keycloak answers `error=invalid_scope` when no client scope of that name exists.
2. **Settings > OIDC > Additional sign-in scopes**: **Add**, type `groups`, **Save configuration**.
3. After the next sign-in the values the IdP sent are known to xpander. Under **Settings > User groups**, open the group row's menu (three dots) and choose **Link SSO groups**. The dialog lists the observed values, takes a value typed by hand, and saves with **Save links**. The row then shows an **SSO** badge.
4. Members of the linked identity-provider groups join the xpander group at their next sign-in.

<Frame caption="Link SSO groups: the observed identity-provider values, a manual entry field and Save links. Shown with sample data.">
  <img src="https://mintcdn.com/xpanderai-099931d1/OdLxX9OyFVicAV0l/images/verify/lab-user-groups-link-dialog.png?fit=max&auto=format&n=OdLxX9OyFVicAV0l&q=85&s=40906a53b763622e1e18968db09a7fd2" alt="Link SSO groups to Ops dialog reading 'Members of the linked identity-provider groups join this group at their next sign-in', with a search box, one observed group value, a manual entry field and a Save links button" width="1440" height="900" data-path="images/verify/lab-user-groups-link-dialog.png" />
</Frame>

<Frame caption="Settings > User groups after Save links: the group carries an SSO badge and names the linked identity-provider group. Shown with sample data.">
  <img src="https://mintcdn.com/xpanderai-099931d1/OdLxX9OyFVicAV0l/images/verify/lab-user-groups-linked.png?fit=max&auto=format&n=OdLxX9OyFVicAV0l&q=85&s=e96715ef489faa20de4428d087044a2e" alt="User groups list with a Default group and an Ops group carrying an SSO badge and the line 'Linked to the Keycloak acme-ops group', with a toast reading SSO group links saved" width="1440" height="900" data-path="images/verify/lab-user-groups-linked.png" />
</Frame>

When the IdP answers the callback with an error, the browser lands on `/` signed out with no message; the `error=` parameter is on the callback request in the browser's network log. The Keycloak screens, the `preferred_username` mapper and the failure table are on [SSO with your identity provider](/self-hosted/sso#group-sync-with-keycloak).

## Agent pre-authentication

Agent pre-authentication uses OIDC token exchange. At the moment of a call, xpander exchanges the asking person's sign-in token for one scoped to the target system, so the agent acts with that person's permissions where the outside system allows it. The IdP client needs token exchange enabled (Keycloak 26: the client attribute `standard.token.exchange.enabled=true`), direct access grants, an audience client for the target system, and a client scope with an audience mapper. In xpander, **Settings > OIDC > Agent pre-authentication** holds the **Enable agent pre-authentication** switch, **Audiences** (one per target system) and **Token exchange scopes**. **Save configuration** applies them. Leave it off to start.

## Self-hosted chart values

```yaml theme={"dark"}
client-auth:
  env:
    APP_URL: https://<app-host>   # the UI origin, no trailing slash; it forms the redirect_uri
ui:
  authProviders: [sso]            # renders the SSO button
```

The Keycloak `preferred_username` mapper, the failure table and the pods to read logs from are on [SSO with your identity provider](/self-hosted/sso).
