Skip to content

Enterprise SSO

Customers sign in with Okta, Entra ID, Google Workspace, Keycloak, ADFS and other identity providers (IdPs). Each provider is bound to one or more email domains. signInWithSSO({ email }) or { domain } picks the provider of that domain (a subdomain such as eng.acme.com matches acme.com; the most specific domain wins). The flow is SP-initiated and ends like OAuth with a normal PotaLab Base session.

// login page: "Continue with SSO"
await base.auth.signInWithSSO({ email: "alice@acme.com", redirectTo: "https://app.example.com/auth/callback" })
// on /auth/callback
const code = new URL(location.href).searchParams.get("code")!
const { data, error } = await base.auth.exchangeCodeForSession(code)

signInWithSSO also accepts domain or providerId, and skipBrowserRedirect to return the URL instead of navigating. Errors come back to redirectTo as ?error=<code>&error_description=....

Providers are managed by the project owner in the dashboard or with the Management API (POST /v1/projects/{ref}/auth/providers/sso).

{ "kind": "oidc", "name": "Acme Okta", "issuer": "https://acme.okta.com",
"client_id": "...", "client_secret": "...",
"domains": ["acme.com"], "scopes": ["openid", "email", "profile"],
"attribute_mapping": { "email_verified": "email_verified", "extra": { "department": "department" } } }

Base runs OIDC discovery when you save and checks that the discovered issuer matches. The client secret is write-only. Register the returned callback_url as the redirect URI at your IdP.

{ "kind": "saml", "name": "Acme ADFS",
"metadata_url": "https://.../FederationMetadata.xml", "domains": ["acme.com"] }

You can pass metadata_xml instead of metadata_url. The IdP metadata must contain the signing certificate. Give your IdP admin the returned sp_metadata_url (or acs_url and sp_entity_id). Base requires signed assertions and the email NameID format. When the IdP rotates its certificate, PATCH .../sso/{id} with { "refresh_metadata": true } re-reads the metadata.

Use POST /v1/projects/{ref}/auth/providers/{id}/test to re-run discovery or the metadata download without changing anything.

attribute_mapping supports email, email_verified, name, first_name, last_name, image and extra: { key: claim } (copied into the new user’s user_metadata). Defaults: OIDC email, email_verified, name, picture; SAML email (else the NameID), givenName plus surname or displayName.

  • An identity seen before signs in as its user.
  • The asserted email must be inside the provider’s domains, otherwise email_domain_not_allowed.
  • An existing user with the same email is linked only when the project allows linking, the IdP asserts a verified email (or the provider has trust_email: true), and the local account’s email is verified. Otherwise sign-in is refused with email_exists.
  • Otherwise the user is created just in time (jit: true, the default) unless jit is false or sign-ups are off (signup_disabled).
  • Banned users are refused (user_banned).

IdP-initiated SAML, SAML single logout, encrypted assertions, signed AuthnRequests, private_key_jwt client authentication, SCIM provisioning and domain-ownership verification.

Error Meaning
404 sso_provider_not_found no enabled provider for that domain or id
?error=email_exists an account with that email exists and the linking rules did not allow linking
?error=email_domain_not_allowed the IdP returned an email outside the provider’s domains
?error=invalid_saml_response signature, audience, recipient, timestamps or request binding did not validate
402 feature_not_in_plan your plan does not include SSO