Platform
Enterprise SSO (OIDC)
Each workspace can register its own OIDC provider — Okta, Entra ID, Google Workspace, or any spec-compliant IdP. Email routing activates only after DNS ownership verification; a verified normalized domain can belong to exactly one workspace. Membership provisioning is durable and idempotent, secrets are encrypted at rest and masked in responses, and every web replica reads the current registry without requiring a restart. DNS ownership is a renewable 30-day lease so an abandoned workspace cannot hold a routing domain forever.
The sign-in flow
Provider management (owner-only)
SSO providers are managed per workspace under Settings → SSO. Create, update, and delete are strictly owner-gated — admins do not qualify — because a provider controls who can enter the workspace. A provider registration carries:
- Issuer URL— the IdP's OIDC issuer; endpoints are resolved via standard discovery (
/.well-known/openid-configuration). - Client ID and client secret — from the app registration in the IdP.
- Email domain — the optional domain this provider claims for sign-in routing (e.g.
client.com).
Secrets: encrypted at rest, masked on read
APP_SECRET. Organization-scoped application queries provide workspace isolation for this non-RLS control-plane table; the encryption key itself is app-scoped, not per-workspace. Reads return only a masked hint. Rotate a provider secret by writing a replacement; never expect the API to reveal the existing value. Create, update, verify, and delete write workspace audit events without secret material. Deleting or materially reconfiguring a provider also deletes its linked OIDC account token rows so stale access, refresh, and ID tokens are not retained. Existing eli.ai cookie sessions are separate records and remain valid until normal expiry or explicit administrative revocation.Prove and claim the email domain
Saving a domain creates an unverified claim and a random DNS challenge. The settings card shows the exact TXT record to publish:
Domains are trimmed, lowercased, converted to their ASCII DNS form, and validated before storage. The final verification update is protected by a unique index over the normalized verified domain, so two workspaces racing to verify the same name cannot both win. A successful proof leases the claim for 30 days; repeating Verify while the TXT record remains published renews it. A conflict returns 409 domain_already_claimed.
- Unverified duplicate claims may be staged, but none participates in routing.
- Changing or clearing a verified domain invalidates its proof immediately.
- An expired lease stops routing. The next valid claimant atomically releases the stale row and competes for the unique claim.
- Disabling stops routing but retains the claim only until its lease expires; changing or deleting releases it immediately.
- Workspace destruction deletes provider secrets, linked OIDC tokens, and verified claims even though the organization audit anchor is retained.
Conflict and orphan recovery
Email-domain routing
The sign-in page stays a single field. When an entered email's domain matches a registered SSO provider that is both enabled and verified, the password step is replaced with a redirect to that provider's IdP. Unverified, disabled, malformed, and unknown domains return no SSO provider and continue through the other configured sign-in flow.
A configured domain gates direct provider sign-in too
providerId therefore cannot bypass an unverified or expired lookup. A provider with no configured domain remains an explicit provider-id flow and makes no email-domain ownership claim.Auto-provisioned membership
On a successful callback, the provider account is linked to the user and eli.ai idempotently adds that user to the provider's workspace with the legacy memberrole (the editor bundle). Role elevation remains an explicit in-app action; a later sign-in never overwrites an administrator's role change. Once provisioning completes, a later administrative membership removal also remains effective; an unrelated password session does not silently recreate it.
Provisioning failure is recoverable and fails sign-in closed
Durable registry across replicas
Provider configuration lives in PostgreSQL. Before handling any auth request, each web replica fingerprints the enabled provider rows and rebuilds its Better Auth OIDC configuration only when the durable state changed. Create, edit, disable, and delete therefore take effect on the next request to each replica without a deploy or process-local broadcast. Refreshes are serialized within a replica so an older slow read cannot overtake and replace a newer snapshot.
Authentication fails closed when the registry is unavailable
503 authentication_registry_unavailable instead of serving a stale or silently empty provider set.Configuring the IdP
In the identity provider, create an OIDC web application with:
- Grant type — authorization code.
- Scopes —
openid email profile. - Redirect (callback) URI — the provider-specific callback on your eli.ai host:
Then copy the IdP's issuer URL, client id, and client secret into the workspace's provider form. If you configure an email domain, publish the displayed TXT challenge and click Verify domain before testing email-routed sign-in.
The IdP remains a trust boundary
SSO_ALLOWED_ISSUER_ORIGINS. Better Auth still performs later discovery, token, user-info, and signing-key resolution outside eli.ai's address-pinned HTTP client. Production networks must therefore allowlist intended IdP destinations and block private and cloud-metadata ranges after DNS resolution.Related
- Tenancy & security — the workspace isolation model SSO members land inside.
- Authentication (API) — API keys and programmatic auth, unaffected by SSO.
- Deployment — host and TLS prerequisites for the callback URL.