Subchapter 9.1
references/enterprise-sso.mdMarkdown7 KBView on GitHub
Per-organization SAML or OIDC. Configured via Dashboard → Configure → Enterprise Connections (opens in a new tab) or via clerk api -X POST /v1/enterprise_connections (requires a plan with the SAML feature enabled). New users from a matching domain auto-join via JIT Provisioning.
acme.com). Clerk routes any sign-in with that email domain through the connection.Each org can have multiple SSO connections (e.g., SAML + OIDC, or SAML for two different IdPs). Each connection covers one domain.
Enterprise SSO ≠ Verified Domains. These are distinct features. A domain used for Enterprise SSO cannot also be a Verified Domain for the same Organization. Use SSO for IdP-mandated auth; use Verified Domains for auto-invite / auto-suggest flows without SSO. See
docs/guides/organizations/add-members/sso.mdxanddocs/guides/organizations/add-members/verified-domains.mdx.
Permission required to manage: org:sys_domains:manage.
// Current SDK (Core 3+)
strategy: 'enterprise_sso'Used in signIn.supportedFirstFactors when building custom sign-in flows.
Core 2 ONLY (skip if current SDK): Uses
strategy: 'saml'anduser.samlAccountsinstead of the Core 3 names.
provider and protocol metadata live on the nested enterpriseConnection, not directly on the enterprise account. Correct paths:
import { currentUser } from '@clerk/nextjs/server'
const user = await currentUser()
const ssoAccount = user?.enterpriseAccounts?.[0]
if (ssoAccount) {
// Directly on EnterpriseAccount:
ssoAccount.emailAddress // the email used for SSO
ssoAccount.active // boolean — is the account active
ssoAccount.firstName, ssoAccount.lastName
ssoAccount.lastAuthenticatedAt // Date | null
// Provider metadata lives on the nested EnterpriseAccountConnection:
const conn = ssoAccount.enterpriseConnection
conn?.provider // 'saml_okta' | 'saml_google' | 'saml_microsoft' | 'saml_custom' | 'oauth_<provider>'
conn?.protocol // 'saml' | 'oauth'
conn?.domain // the verified domain
conn?.name // display name of the connection
conn?.active
}// ❌ Wrong — `provider` is not a field on EnterpriseAccount
ssoAccount.provider
// ✓ Right — `provider` lives on the nested connection
ssoAccount.enterpriseConnection?.providerenterpriseConnection is null if the connection was deleted after the account was provisioned. Always guard with ?..
Verified Domains are a different feature from Enterprise SSO and cannot coexist on the same domain for the same Organization. Short reference:
<OrganizationSwitcher /> / <OrganizationProfile /> flow).org:sys_domains:manage.When a user signs in via an Enterprise SSO connection scoped to an org, Clerk’s Just-in-Time (JIT) Provisioning (opens in a new tab) automatically adds them as a member of that org and assigns the org’s Default Role. No invitation is required.
JIT runs on the Enterprise Connection, not on the Verified Domain. The two features enforce different pathways and are mutually exclusive per-domain.
Typical pattern (Core 3 canonical):
const { signIn } = useSignIn()
const { error } = await signIn.sso({
strategy: 'enterprise_sso',
identifier: emailAddress,
redirectUrl: '/dashboard', // where to land on successful sign-in
redirectCallbackUrl: '/sign-in/callback', // where to land when additional requirements are needed
})The identifier is the user’s email. Clerk uses the domain to route to the correct Enterprise SSO connection. If no matching connection exists, the sign-in falls back to standard email/password or returns an error.
Core 2 / legacy:
signIn.authenticateWithRedirect({ strategy: 'enterprise_sso', identifier, redirectUrl, redirectUrlComplete })still exists on the SDK for backwards compatibility, but for new code usesignIn.sso()per the current enterprise-connections custom flow doc.
provider is nested. Always enterpriseAccounts[i].enterpriseConnection?.provider — not directly on the account.'enterprise_sso'; Core 2 used 'saml'. They are NOT interchangeable.clerk api for scripted setup: clerk api -X POST /v1/enterprise_connections (create), clerk api -X PATCH /v1/enterprise_connections/{id} (update), clerk api -X DELETE /v1/enterprise_connections/{id} (remove). Pass the IdP metadata or client credentials in the request body; Clerk returns the ACS URL + Entity ID in the response. Create / update endpoints require a plan with the SAML feature enabled. The legacy /v1/saml_connections endpoint is deprecated, use /v1/enterprise_connections instead.