Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -61,26 +61,19 @@ Enabling SAML with Okta Workforce allows your users to sign up and sign in to yo

We expect your SAML responses to have the following specific attributes:

- Email address (required). This is the email address that your users will use to authenticate into your app:
- Claim name: `user.email`
- First name (optional):
- Claim name: `user.firstName`
- Last name (optional):
- Claim name: `user.lastName`

These are the defaults, and probably won't need you to change them. However, many SAML configuration errors are due to incorrect attribute mappings, so it's worth double-checking. Here's how:

1. In the Okta dashboard, find the **Attribute Statements (optional)** section.
1. For the **Name** field, enter `mail`.
1. For the **Value** field, choose `user.email` from the dropdown.
1. Select the **Add Another** button to add another attribute.
1. For the **Name** field, enter `firstName`.
1. For the **Value** field, choose `user.firstName` from the dropdown.
1. Select the **Add Another** button to add another attribute.
1. For the **Name** field, enter `lastName`.
1. For the **Value** field, choose `user.lastName` from the dropdown.
1. Scroll to the bottom of the page and select the **Next** button to continue.
1. You will be redirected to the **Feedback** page. Fill out the feedback however you would like and select the **Finish** button to complete the setup.
| Attribute | Required | Claim name |
| - | - | - |
| Email address | ✅ | `user.email` |
| First name | ❌ | `user.firstName` |
| Last name | ❌ | `user.lastName` |

Okta uses these values by default, so you probably won't need to configure them manually. However, incorrect attribute mappings cause many SAML configuration errors. If the integration doesn't work as expected, define the attributes explicitly:

1. In the Okta dashboard, find the **Attribute Statements** section.
1. Select **Add expression** for each attribute, and enter the following name and expression pairs:
- `mail` and `user.profile.email`
Comment on lines -72 to +74
Copy link
Copy Markdown
Member

@LauraBeatris LauraBeatris May 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this due to the Okta UI changes? They recently updated the UI for attribute statements and our copy here was using the "legacy" UI

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, this is the new ui changes. using expressions instead of legacy ui

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

e75b5d5

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should also update self-serve sso to use these instructions too 👀

- `firstName` and `user.profile.firstName`
- `lastName` and `user.profile.lastName`.

**Step 3: Assign selected user or group in Okta**

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
title: Self-serve SSO
description: Learn how to let your customers' IT admins configure their own enterprise SSO connections from inside your application.
---

By default, enterprise SSO connections are configured by your team inside the Clerk Dashboard. For every enterprise customer that needs SSO, someone on your side has to create the connection, exchange metadata with the customer's IT admin, test the connection, and activate it. As your enterprise motion scales, this becomes a bottleneck.

Self-serve SSO lets you delegate that configuration directly to your customers' IT admins by embedding the [`<ConfigureSSO />`](/docs/reference/components/authentication/configure-sso) component inside your own application. The IT admin signs into your app with their Clerk account and uses the component to handle all identity provider (IdP) specific setup end-to-end — choosing an IdP, verifying the domain, exchanging metadata, and testing the connection — without ever touching the Clerk Dashboard.

`<ConfigureSSO />` works whether or not your application uses [Clerk Organizations](/docs/guides/organizations/overview):

- **With Clerk Organizations** — the connection is attached to the IT admin's active Organization.
- **Without Clerk Organizations** — the connection is attached to an email domain at the application level. No Organization is required.

> [!NOTE]
> In its current implementation, `<ConfigureSSO />` is the only way to use self-serve SSO, and it requires an active Clerk session. The IT admin must have a Clerk user account in your application and be signed in to use the flow. It currently only supports Okta and custom SAML.

## Enable self-serve SSO

You must enable self-serve SSO at the instance level before the `<ConfigureSSO />` component will render.

1. In the Clerk Dashboard, navigate to the [**SSO connections**](https://dashboard.clerk.com/~/user-authentication/sso-connections) page.
1. Open the **Self-serve** tab.
1. Toggle **Self-serve SSO** on.

If self-serve SSO is disabled, mounting `<ConfigureSSO />` in development will throw a runtime error to surface the misconfiguration. In production, it will simply not render.

## Requirements

To render `<ConfigureSSO />`, the following must be true:

- Self-serve SSO is enabled in the Clerk Dashboard (see above).
- The **Email address** identifier is enabled on your instance. The component uses the user's primary email address to derive and verify the domain being claimed.
- The IT admin is signed in with a Clerk user account in your application. The component reads the active Clerk session and does not currently support unauthenticated, token-based access.

If you use Clerk Organizations and want to scope a connection to an Organization, the signed-in user must have the `org:sys_enterprise_connections` system permission for that Organization. This permission ships with the default **Admin** role; if you've defined custom roles, add it to any role that should be able to manage enterprise connections. For more information, refer to the [roles and permissions guide](/docs/guides/organizations/control-access/roles-and-permissions).

## How the flow works

When the IT admin opens a page that renders `<ConfigureSSO />`, they are guided through a wizard with the following stages:

1. **Verify domain** — the component verifies that the user controls the email domain they're claiming. If the user doesn't have a primary email address yet, they're prompted to add one first.
1. **Configure** — the user selects an IdP and provides the protocol-specific configuration. IdP setup instructions are embedded inline, so you don't need to author or maintain your own walkthroughs.
1. **Test** — the user runs a test sign-in to confirm the connection works end-to-end.
1. **Confirmation** — once the test passes, you can review and enable the connection.

## Embed the component

The following example shows the minimal integration in a Next.js App Router app. The component is imported from `@clerk/nextjs/experimental` because it's still in early access.

```tsx {{ filename: 'app/sso-setup/page.tsx' }}
import { ConfigureSSO } from '@clerk/nextjs/experimental'

export default function SSOSetupPage() {
return <ConfigureSSO />
}
```

Wrap the page in your usual route protection (for example, [`auth.protect()`](/docs/reference/nextjs/app-router/auth#auth-protect)) so that only signed-in users can reach it.

For full prop and SDK reference, see the [`<ConfigureSSO />` component documentation](/docs/reference/components/authentication/configure-sso).

## What's next

Once a connection is created via `<ConfigureSSO />`, it behaves like any other Clerk enterprise connection. Users with matching email addresses can sign in via the configured IdP. To learn more, refer to:

- [Authentication flows](/docs/guides/configure/auth-strategies/enterprise-connections/authentication-flows)
- [Account linking](/docs/guides/configure/auth-strategies/enterprise-connections/account-linking)
- [Just-in-Time (JIT) provisioning](/docs/guides/configure/auth-strategies/enterprise-connections/jit-provisioning)
- [Directory Sync (SCIM)](/docs/guides/configure/auth-strategies/enterprise-connections/directory-sync)
16 changes: 16 additions & 0 deletions docs/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,10 @@
"tag": "(Beta)",
"href": "/docs/guides/configure/auth-strategies/enterprise-connections/custom-attribute-mapping"
},
{
"title": "Self-serve SSO",
"href": "/docs/guides/configure/auth-strategies/enterprise-connections/self-serve-sso"
},
{
"title": "SAML providers",
"items": [
Expand Down Expand Up @@ -2611,6 +2615,14 @@
"title": "Metadata types",
"href": "/docs/reference/types/metadata"
},
{
"title": "`OAuthConsentInfo`",
"href": "/docs/reference/types/oauth-consent-info"
},
{
"title": "`OAuthConsentScope`",
"href": "/docs/reference/types/oauth-consent-scope"
},
{
"title": "`OrganizationCreationDefaults`",
"href": "/docs/reference/types/organization-creation-defaults"
Expand Down Expand Up @@ -3642,6 +3654,10 @@
{
"title": "`<Waitlist />`",
"href": "/docs/reference/components/authentication/waitlist"
},
{
"title": "`<ConfigureSSO />`",
"href": "/docs/reference/components/authentication/configure-sso"
}
]
]
Expand Down
213 changes: 213 additions & 0 deletions docs/reference/components/authentication/configure-sso.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
---
title: '`<ConfigureSSO />` component'
description: Clerk's <ConfigureSSO /> component renders a self-serve UI that lets your customers' IT admins configure their own enterprise SSO connections from inside your application.
sdk: astro, nextjs, react, tanstack-react-start, vue, js-frontend
---

The `<ConfigureSSO />` component renders a UI with instructions that allows end-users, typically the IT admin at one of your enterprise customers, configure single sign-on directly from your application.

The wizard walks the user through selecting an Identity Provider (IdP), verifying their email domain, supplying the protocol-specific configuration (with IdP setup instructions embedded inline), running a test sign-in, and activating the connection.

`When Organizations are enabled, the connection is attached to the user's active Organization, otherwise it's attached to the email domain at the instance level.

To learn how the broader self-serve SSO feature works and how to enable it in the Clerk Dashboard, see the [self-serve SSO guide](/docs/guides/configure/auth-strategies/enterprise-connections/self-serve-sso).

> [!NOTE]
> In its current implementation, `<ConfigureSSO />` is the only way to use self-serve SSO, and it requires an active Clerk session. The IT admin must have a Clerk user account in your application and be signed in to use the flow. It currently only supports Okta and custom SAML.

## Requirements

`<ConfigureSSO />` will only render when all of the following are true:

- Self-serve SSO is enabled for your instance. See the [self-serve SSO guide](/docs/guides/configure/auth-strategies/enterprise-connections/self-serve-sso#enable-self-serve-sso) for instructions.
- The **Email address** identifier is enabled on your instance.
- The component is rendered to a signed-in user.

If any of these conditions are not met, the component will throw a runtime error in development and will not render in production.

If you use Clerk Organizations, the signed-in user must also have the `org:sys_enterprise_connections` system permission in their active Organization to manage enterprise connections. The permission ships with the default **Admin** role.

<If notSdk="js-frontend">
## Example

The following example includes a basic implementation of the `<ConfigureSSO />` component. You can use this as a starting point for your own implementation.

Because `<ConfigureSSO />` is experimental, it must be imported from the `experimental` subpath of your SDK.

<If sdk="nextjs">
```tsx {{ filename: 'app/sso-setup/page.tsx' }}
import { ConfigureSSO } from '@clerk/nextjs/experimental'

export default function SSOSetupPage() {
return <ConfigureSSO />
}
```
</If>

<If sdk="react">
```tsx {{ filename: 'src/sso-setup.tsx' }}
import { ConfigureSSO } from '@clerk/clerk-react/experimental'

export default function SSOSetupPage() {
return <ConfigureSSO />
}
```
</If>

<If sdk="tanstack-react-start">
```tsx {{ filename: 'src/routes/sso-setup.tsx' }}
import { ConfigureSSO } from '@clerk/tanstack-react-start/experimental'
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/sso-setup')({
component: SSOSetupPage,
})

function SSOSetupPage() {
return <ConfigureSSO />
}
```
</If>

<If sdk="astro">
```astro {{ filename: 'src/pages/sso-setup.astro' }}
---
import { __experimental_ConfigureSSO as ConfigureSSO } from '@clerk/astro/components'
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll remove the __experimental prefix from here before releasing it GA - this is just used in the SDK now so we can incrementally implement internally

---

<ConfigureSSO />
```
</If>

<If sdk="vue">
```vue {{ filename: 'pages/sso-setup.vue' }}
<script setup lang="ts">
import { ConfigureSSO } from '@clerk/vue/experimental'
</script>

<template>
<ConfigureSSO />
</template>
```
</If>
</If>

<If sdk="js-frontend">
## Usage with JavaScript

The following methods on an instance of the [`Clerk`](/docs/reference/objects/clerk) class are used to render and control the `<ConfigureSSO />` component:

- `__experimental_mountConfigureSSO()`
- `__experimental_unmountConfigureSSO()`

The following examples assume that you've followed the [quickstart](/docs/js-frontend/getting-started/quickstart) to add Clerk to your JavaScript app.

### <code>mountConfigureSSO()</code>

Render the `<ConfigureSSO />` component to an HTML `<div>` element.

```typescript
function __experimental_mountConfigureSSO(node: HTMLDivElement, props?: ConfigureSSOProps): void
```

#### <code>mountConfigureSSO()</code> params

<Properties>
- `node`
- [`HTMLDivElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDivElement)

The container `<div>` element used to render the `<ConfigureSSO />` component.

---

- `props?`
- [`ConfigureSSOProps`](#properties)

The properties to pass to the `<ConfigureSSO />` component.
</Properties>

#### <code>mountConfigureSSO()</code> usage

```js {{ filename: 'main.js', mark: [15] }}
import { Clerk } from '@clerk/clerk-js'

// Initialize Clerk with your Clerk Publishable Key
const clerkPubKey = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY

const clerk = new Clerk(clerkPubKey)
await clerk.load()

document.getElementById('app').innerHTML = `
<div id="configure-sso"></div>
`

const configureSSODiv = document.getElementById('configure-sso')

clerk.__experimental_mountConfigureSSO(configureSSODiv)
```

### <code>unmountConfigureSSO()</code>

Unmount and run cleanup on an existing `<ConfigureSSO />` component instance.

```typescript
function __experimental_unmountConfigureSSO(node: HTMLDivElement): void
```

#### <code>ConfigureSSO()</code> params

<Properties>
- `node`
- [`HTMLDivElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDivElement)

The container `<div>` element with a rendered `<ConfigureSSO />` component instance.
</Properties>

#### <code>unmountConfigureSSO()</code> usage

```js {{ filename: 'main.js', mark: [19] }}
import { Clerk } from '@clerk/clerk-js'

// Initialize Clerk with your Clerk Publishable Key
const clerkPubKey = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY

const clerk = new Clerk(clerkPubKey)
await clerk.load()

document.getElementById('app').innerHTML = `
<div id="configure-sso"></div>
`

const configureSSODiv = document.getElementById('configure-sso')

clerk.__experimental_mountConfigureSSO(configureSSODiv)

// ...

clerk.__experimental_unmountConfigureSSO(configureSSODiv)
```
</If>

## Properties

All props are optional.

<Properties>
- `appearance?`
- <code>[Appearance](/docs/guides/customizing-clerk/appearance-prop/overview) | undefined</code>

An object to style the component. Overrides and merges with the global `appearance` prop on `<ClerkProvider>` (if one is provided). Will only affect [Clerk components](/docs/reference/components/overview) and not [Account Portal](/docs/guides/account-portal/overview) pages.

<If notSdk="js-frontend">
---

- `fallback?`
- `ReactNode`

An element to be rendered while the component is mounting.
</If>
</Properties>

## Customization

To learn how to customize Clerk components, see the [appearance prop documentation](/docs/guides/customizing-clerk/appearance-prop/overview).
1 change: 1 addition & 0 deletions docs/reference/components/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Clerk offers a comprehensive suite of components designed to seamlessly integrat
- [`<TaskResetPassword />`](/docs/reference/components/authentication/task-reset-password)
- [`<TaskSetupMFA />`](/docs/reference/components/authentication/task-setup-mfa)
- [`<Waitlist />`](/docs/reference/components/authentication/waitlist)
- [`<ConfigureSSO />`](/docs/reference/components/authentication/configure-sso)

## User components

Expand Down
7 changes: 7 additions & 0 deletions docs/reference/types/oauth-consent-info.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
title: '`OAuthConsentInfo`'
description: An interface that represents OAuth consent information.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this added due to a bad git rebase?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this looks like it's from this PR

sdk: js-frontend, astro, chrome-extension, expo, nextjs, react, react-router, tanstack-react-start, nuxt, vue
---

<Typedoc src="shared/o-auth-consent-info" />
7 changes: 7 additions & 0 deletions docs/reference/types/oauth-consent-scope.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
title: '`OAuthConsentScope`'
description: An interface that represents an OAuth consent scope.
sdk: js-frontend, astro, chrome-extension, expo, nextjs, react, react-router, tanstack-react-start, nuxt, vue
---

<Typedoc src="shared/o-auth-consent-scope" />
Loading