Skip to content

SSO

Enterprise orgs can register SAML or OIDC identity providers through the admin-only SSO management routes. Configuration is stored on the organization record and drives the dashboard sign-in flow.

  1. User visits https://<dashboard>/sign-in and types their email.
  2. The sign-in page calls GET /api/auth/sso/discovery?email=<addr>, which returns a provider match if the email’s domain equals the emailDomain on a registered SSO provider.
  3. On a match the sign-in page swaps the password button for Sign in with ProviderName, which hits GET /api/auth/sso/login?providerId=<id>&next=<path>.
  4. That endpoint redirects to the provider’s OIDC authorize URL.
  5. On the return trip, GET /api/auth/sso/callback?code=&state= exchanges the code for an id_token, extracts the email claim, upserts the user in the shared Postgres, and sets the Better Auth session cookie.
https://<dashboard-host>/api/auth/sso/callback

Enterprise-provisioned deep-links can skip the discovery step by appending ?sso=<providerId> to /sign-in — the page bounces to /api/auth/sso/login immediately.

All routes require an admin-scoped API key and an Enterprise org — a non-Enterprise org gets 403 CARBON_FORBIDDEN with an actionable message rather than a silent success.

MethodPathPurpose
GET/v1/sso/providersList configured providers
POST/v1/sso/providersRegister a SAML or OIDC provider
DELETE/v1/sso/providers/:idRemove a provider
Terminal window
curl -X POST <api-origin>/v1/sso/providers \
-H "x-carbon-key: ck_live_admin_…" \
-H "content-type: application/json" \
-d '{
"type": "saml",
"name": "Okta (Acme)",
"entityId": "https://acme.okta.com/…",
"ssoUrl": "https://acme.okta.com/app/…/sso/saml",
"certificate": "-----BEGIN CERTIFICATE-----\nMIIC…\n-----END CERTIFICATE-----",
"emailDomain": "acme.example"
}'
Terminal window
curl -X POST <api-origin>/v1/sso/providers \
-H "x-carbon-key: ck_live_admin_…" \
-H "content-type: application/json" \
-d '{
"type": "oidc",
"name": "Google Workspace (Acme)",
"issuer": "https://accounts.google.com",
"clientId": "…apps.googleusercontent.com",
"clientSecret": "GOCSPX-…",
"emailDomain": "acme.example"
}'

Every SSO change writes an audit event (sso_provider.created / sso_provider.deleted) so it shows up in carbon activity and in the compliance export events / audit buckets.