§06 · Identity & access

SSO · SAML & OIDC

Sign in to Exo through your identity provider. Register Exo as an app in the IdP, enter the provider values in the dashboard, and the browser sign-in flow mints the same User JWT a password login would.

Exo does browser single sign-on over SAML 2.0 and OIDC (OpenID Connect). Configure both per tenant under Dashboard → Identity providers, with the idp:write permission. Use whichever protocol your IdP exposes. Okta, Microsoft Entra, Google, Auth0, Ping, and Keycloak all support one or both.

How sign-in works

A user enters their work email on the login page. Exo looks up which provider serves that domain and bounces the browser to your IdP. The IdP authenticates them and redirects back with an assertion (SAML) or an id_token (OIDC). Exo validates it, creates or updates the user, applies their group memberships, and issues a User JWT, the same token a password login mints. There's no separate SSO session store. The JWT is the session.

Add a provider

The Identity Providers catalogue: SAML, OIDC, SCIM push, LDAP pull, Microsoft Graph pull, Google Workspace pull
Identity → Identity Providers. Browser SSO (SAML, OIDC) on the left; provisioning and directory pulls (SCIM, LDAP, Graph, Google) alongside.

Open Identity providers, choose SAML 2.0 or OIDC, and give it a display name (what users see on the login page). The editor has a form view for the common fields and a YAML view for the full config. Secrets (client secrets, signing keys) are write-only: once saved they never render back, and leaving a secret field blank on edit keeps the stored value.

Configure SAML 2.0

Exo is the service provider (SP). Create the IdP side first so you have the SSO URL, entity ID, and signing certificate to paste in. Exo publishes its SP metadata for the IdP to consume:

endpoints Exo gives the IdP· text
1SP metadata GET /api/v1/sso/saml/{idp-id}/metadata
2ACS (reply) POST /api/v1/sso/saml/{idp-id}/acs
3SP entity ID https://exo/sp/{idp-id} (override if your IdP needs a URL)

Then fill the Exo side:

FieldMaps toNotesExample
IdP SSO URLsso_urlWhere Exo sends the auth requesthttps://acme.okta.com/app/exo/abc123/sso/saml
IdP entity IDentity_idIssuer of the assertionhttp://www.okta.com/exkabc123
IdP signing certx509_certPEM, used to verify the assertion-----BEGIN CERTIFICATE----- MIIC…
SP entity IDsp_entity_idOptional; defaults to https://exo/sp/{id}https://exo/sp/{id}
ACS URLacs_urlOptional; defaults to the /acs route abovehttps://exo.acme.com/api/v1/sso/saml/{idp-id}/acs
Email attributeattribute_mapping.emailClaim carrying the user's emailemail
Name attributeattribute_mapping.nameClaim carrying display namedisplayName
Groups attributeattribute_mapping.groupsMulti-valued claim of group namesgroups

Configure OIDC

Register Exo as a web app in your IdP, set the redirect URI to the callback below, and copy the client credentials in. Exo reads the IdP's /.well-known/openid-configuration from the issuer, so you supply the issuer URL, not every endpoint.

redirect URI to register· text
GET /api/v1/sso/oidc/{idp-id}/callback
FieldMaps toNotesExample
Issuer URLissuerBase URL; Exo fetches the discovery dochttps://login.microsoftonline.com/acme.onmicrosoft.com/v2.0
Client IDclient_idFrom the IdP app registration12345678-9abc-def0-1234-56789abcdef0
Client secretclient_secretWrite-only after savewxy8Q~…
Redirect URIredirect_uriMust equal the callback registered abovehttps://exo.acme.com/api/v1/sso/oidc/{idp-id}/callback
ScopesscopesOptional; defaults to openid email profile groupsopenid email profile groups
Email claimemail_claimOptional; defaults to "email"email
Name claimname_claimOptional; defaults to "name"name
Groups claimgroups_claimOptional; defaults to "groups"groups

The flow uses Authorization Code with PKCE. Exo validates the id_token's issuer, audience, and expiry, then reads email, name, and groups from the claims you named above.

Default provider & discovery

Mark one provider Default for SSO discovery so users who land on the login page without a matched email still get a sign-in button. Email discovery is rate-limited and nonce-protected against account enumeration. Nothing to configure there.

Groups & roles

Every group name in the assertion or token reconciles into an Exo group on each sign-in, but groups don't carry roles: a user's role is assigned directly, one per user, and first-time SSO users land as Member. Groups scope access instead; use them as principals on per-agent access lists. See Roles & permissions. To keep the full directory in sync between logins, including deactivations, pair SSO with SCIM or directory sync.

Test & roll out

Save the provider disabled first, use the row's Test button to check the config, then enable it and run a real sign-in end to end. Enable is reversible: toggling a provider off stops new SSO logins through it at once, without deleting the config.