Skip to content

feat(ui): Add support for custom SAML provider in <ConfigureSSO />#8564

Open
LauraBeatris wants to merge 4 commits into
mainfrom
laura/orgs-1539-configuresso-support-custom-saml-provider-on-configure-step
Open

feat(ui): Add support for custom SAML provider in <ConfigureSSO />#8564
LauraBeatris wants to merge 4 commits into
mainfrom
laura/orgs-1539-configuresso-support-custom-saml-provider-on-configure-step

Conversation

@LauraBeatris
Copy link
Copy Markdown
Member

@LauraBeatris LauraBeatris commented May 15, 2026

Description

  • Introduces different header subtitles per provider
  • Introduces localization support for custom SAML provider within configure steps
  • Update select provider step logic to go to add/verify email verification according to the user data

With Custom SAML

CleanShot.2026-05-15.at.17.56.24.mp4

With Okta

CleanShot.2026-05-15.at.17.56.24.mp4

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

@LauraBeatris LauraBeatris self-assigned this May 15, 2026
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 15, 2026

🦋 Changeset detected

Latest commit: c32fda9

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 20 packages
Name Type
@clerk/localizations Patch
@clerk/clerk-js Patch
@clerk/shared Patch
@clerk/ui Patch
@clerk/react Patch
@clerk/chrome-extension Patch
@clerk/expo Patch
@clerk/astro Patch
@clerk/backend Patch
@clerk/expo-passkeys Patch
@clerk/express Patch
@clerk/fastify Patch
@clerk/hono Patch
@clerk/msw Patch
@clerk/nextjs Patch
@clerk/nuxt Patch
@clerk/react-router Patch
@clerk/tanstack-react-start Patch
@clerk/testing Patch
@clerk/vue Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link
Copy Markdown

vercel Bot commented May 15, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment May 15, 2026 9:26pm

Request Review

@LauraBeatris LauraBeatris force-pushed the laura/orgs-1539-configuresso-support-custom-saml-provider-on-configure-step branch from 6f1a6dd to 14bdeb2 Compare May 15, 2026 20:53
@LauraBeatris LauraBeatris requested review from a team and NicolasLopes7 May 15, 2026 20:59
@LauraBeatris LauraBeatris marked this pull request as ready for review May 15, 2026 20:59
);
};

// TODO - Move IdP specific content to separate modules
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We'll need a better structure for this when introducing Google Workspace and Microsoft Entra, for now I'll keep everything in the same module, and next week I'll introduce separate ones per provider

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 15, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR extends the component to support custom SAML provider configuration alongside the existing Okta flow. It updates the localization schema with new headerTitle/headerSubtitle and expanded manual configuration fields; adds a typed translation-key helper module for step-specific localization; extends the ConfigureSSO context with createEnterpriseConnection() that derives email domain, calls the enterprise-connections API, and manages card loading/error state; refactors SelectProviderStep to add async email verification gating; updates VerifyDomainStep to use the context API for connection creation; and refactors ConfigureStep and sub-steps to use provider-scoped translation keys, conditional provider UIs, and inline error alerts.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • clerk/javascript#8553: Refactors SubmitSamlConfigSubStep to use typed step-translation helpers for segmented control and metadata/manual panel labeling, building on the configure-step refactoring infrastructure introduced in this PR.
  • clerk/javascript#8535: Continues the ConfigureSSO Okta workflow with localization/type schema and wizard step updates for metadata URL UI that align with the configuration checkpoint structure defined here.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main feature: adding support for custom SAML provider in the ConfigureSSO component.
Description check ✅ Passed The description is related to the changeset, detailing the introduction of provider-specific header subtitles, localization support for custom SAML, and email verification routing logic.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/ui/src/components/ConfigureSSO/steps/ConfigureStep.tsx (1)

855-857: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Manual certificate labels are still hardcoded to Okta keys

This path is shared by provider-based flows, but these strings are fixed to samlOkta.*. In custom SAML mode, this can show provider-inaccurate copy and bypass the new provider-specific translation mapping.

Suggested fix
                 {existingCertPresent && (
                   <Badge
-                    localizationKey={localizationKeys(
-                      'configureSSO.configureStep.samlOkta.manual.signingCertificate.fileUploaded',
-                    )}
+                    localizationKey={localizationKeys(key('manual.signingCertificate.fileUploaded'))}
                   />
                 )}
...
                   <Text
                     as='span'
-                    localizationKey={localizationKeys(
-                      existingCertPresent
-                        ? 'configureSSO.configureStep.samlOkta.manual.signingCertificate.replaceFile'
-                        : 'configureSSO.configureStep.samlOkta.manual.signingCertificate.uploadFile',
-                    )}
+                    localizationKey={localizationKeys(
+                      existingCertPresent
+                        ? key('manual.signingCertificate.replaceFile')
+                        : key('manual.signingCertificate.uploadFile'),
+                    )}
                   />
...
                  aria-label={t(
-                    localizationKeys('configureSSO.configureStep.samlOkta.manual.signingCertificate.removeFile'),
+                    localizationKeys(key('manual.signingCertificate.removeFile')),
                   )}

Also applies to: 874-877, 899-900

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ui/src/components/ConfigureSSO/steps/ConfigureStep.tsx` around lines
855 - 857, The UI uses hardcoded 'samlOkta' translation keys in
ConfigureStep.tsx (see localizationKeys calls) causing wrong labels for non-Okta
providers; update those localizationKey calls to build the translation path
dynamically from the current provider/SAML mode (e.g., derive a provider
translation prefix from the component's provider/samlMode value and use
localizationKeys(`${providerPrefix}.configureStep.saml...`) instead of
'samlOkta'), and apply the same change for the other occurrences noted (around
the other localizationKeys calls at the indicated locations) so
provider-specific translations are used consistently.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/ui/src/components/ConfigureSSO/ConfigureSSOContext.tsx`:
- Around line 63-85: createEnterpriseConnection currently swallows failures (it
handles errors with handleError/card.setError and returns early if emailDomain
is missing), causing callers like SelectProviderStep and
EnterVerificationCodeStep to continue as if the connection succeeded; change
createEnterpriseConnection so that after calling
enterpriseConnectionApi.createEnterpriseConnection it rethrows the caught error
(or returns a rejected Promise) instead of only calling card.setError, and for
the missing-domain branch return a rejected Promise (or throw) with a clear
error so callers can await and react to failure; update references around
createEnterpriseConnection, enterpriseConnectionApi.createEnterpriseConnection,
and card.setError/handleError to ensure errors propagate to the caller.

In `@packages/ui/src/components/ConfigureSSO/steps/ConfigureStep.tsx`:
- Around line 759-762: The Continue button is blocked by card.error so users
can't retry; remove card.error from the disabled condition and instead only
disable based on canSubmit and loading (change isDisabled to use {!canSubmit ||
card.isLoading}), and ensure handleContinue immediately clears the stale error
(e.g., set card.error = undefined at start of handleContinue) so any previous
error is removed when a retry begins; update references in the Continue button
props and the handleContinue function accordingly.

In `@packages/ui/src/components/ConfigureSSO/steps/SelectProviderStep.tsx`:
- Around line 49-72: In handleContinue, persist the chosen provider before any
early navigation so EnterVerificationCodeStep can complete
createEnterpriseConnection() after verification: call setProvider(selected)
immediately after the selected/user checks and before routing to 'provide-email'
or 'verify-email-address', and keep the existing setProvider + await
createEnterpriseConnection(selected) on the verified path; update references in
handleContinue and ensure EnterVerificationCodeStep still reads the provider
state when continuing post-verification.

---

Outside diff comments:
In `@packages/ui/src/components/ConfigureSSO/steps/ConfigureStep.tsx`:
- Around line 855-857: The UI uses hardcoded 'samlOkta' translation keys in
ConfigureStep.tsx (see localizationKeys calls) causing wrong labels for non-Okta
providers; update those localizationKey calls to build the translation path
dynamically from the current provider/SAML mode (e.g., derive a provider
translation prefix from the component's provider/samlMode value and use
localizationKeys(`${providerPrefix}.configureStep.saml...`) instead of
'samlOkta'), and apply the same change for the other occurrences noted (around
the other localizationKeys calls at the indicated locations) so
provider-specific translations are used consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 42d3ee0e-5fc9-45f4-acd9-b7c15abf572e

📥 Commits

Reviewing files that changed from the base of the PR and between 5a7225e and 9f50403.

📒 Files selected for processing (8)
  • .changeset/public-parts-chew.md
  • packages/localizations/src/en-US.ts
  • packages/shared/src/types/localization.ts
  • packages/ui/src/components/ConfigureSSO/ConfigureSSOContext.tsx
  • packages/ui/src/components/ConfigureSSO/steps/ConfigureStep.tsx
  • packages/ui/src/components/ConfigureSSO/steps/SelectProviderStep.tsx
  • packages/ui/src/components/ConfigureSSO/steps/VerifyDomainStep.tsx
  • packages/ui/src/components/ConfigureSSO/steps/configureStepTranslations.ts

Comment thread packages/ui/src/components/ConfigureSSO/ConfigureSSOContext.tsx
Comment thread packages/ui/src/components/ConfigureSSO/steps/ConfigureStep.tsx
@LauraBeatris LauraBeatris force-pushed the laura/orgs-1539-configuresso-support-custom-saml-provider-on-configure-step branch from 9f50403 to 51f8039 Compare May 15, 2026 21:12
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 15, 2026

Open in StackBlitz

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@8564

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@8564

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@8564

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@8564

@clerk/dev-cli

npm i https://pkg.pr.new/@clerk/dev-cli@8564

@clerk/expo

npm i https://pkg.pr.new/@clerk/expo@8564

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@8564

@clerk/express

npm i https://pkg.pr.new/@clerk/express@8564

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@8564

@clerk/hono

npm i https://pkg.pr.new/@clerk/hono@8564

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@8564

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@8564

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@8564

@clerk/react

npm i https://pkg.pr.new/@clerk/react@8564

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@8564

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@8564

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@8564

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@8564

@clerk/ui

npm i https://pkg.pr.new/@clerk/ui@8564

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@8564

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@8564

commit: c32fda9

@LauraBeatris LauraBeatris force-pushed the laura/orgs-1539-configuresso-support-custom-saml-provider-on-configure-step branch from 51f8039 to 04a3028 Compare May 15, 2026 21:17
@LauraBeatris LauraBeatris force-pushed the laura/orgs-1539-configuresso-support-custom-saml-provider-on-configure-step branch from 04a3028 to c32fda9 Compare May 15, 2026 21:25
return;
}

// If the user's primary email address is not verified, go to the verify email address step
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This will likely change with a "broader" verification aspect once we introduce DNS verification as well, but I'd avoid abstracting for now

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
packages/ui/src/components/ConfigureSSO/ConfigureSSOContext.tsx (1)

67-69: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Missing email domain resolves silently, advancing the wizard incorrectly.

When emailDomain is undefined, the function returns without throwing. Callers (e.g., SelectProviderStep) await this promise and proceed to the next step, so the wizard advances as if a connection was created when nothing happened.

Proposed fix
       if (!emailDomain) {
-        return;
+        card.setError('A verified primary email address is required to create an enterprise connection.');
+        throw new Error('Missing email domain');
       }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ui/src/components/ConfigureSSO/ConfigureSSOContext.tsx` around lines
67 - 69, The early-return when emailDomain is falsy in ConfigureSSOContext.tsx
silently resolves the calling promise and lets callers like SelectProviderStep
advance; change that check to throw or reject (e.g., throw new Error('Missing
emailDomain') or return Promise.reject(...)) instead of returning, so the caller
receives an error and the wizard does not proceed as if a connection was
created.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@packages/ui/src/components/ConfigureSSO/ConfigureSSOContext.tsx`:
- Around line 67-69: The early-return when emailDomain is falsy in
ConfigureSSOContext.tsx silently resolves the calling promise and lets callers
like SelectProviderStep advance; change that check to throw or reject (e.g.,
throw new Error('Missing emailDomain') or return Promise.reject(...)) instead of
returning, so the caller receives an error and the wizard does not proceed as if
a connection was created.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 6861d591-6375-4445-978d-0c30d7f21de2

📥 Commits

Reviewing files that changed from the base of the PR and between 04a3028 and c32fda9.

📒 Files selected for processing (5)
  • .changeset/public-parts-chew.md
  • packages/ui/src/components/ConfigureSSO/ConfigureSSOContext.tsx
  • packages/ui/src/components/ConfigureSSO/steps/ConfigureStep.tsx
  • packages/ui/src/components/ConfigureSSO/steps/SelectProviderStep.tsx
  • packages/ui/src/components/ConfigureSSO/steps/VerifyDomainStep.tsx
✅ Files skipped from review due to trivial changes (1)
  • .changeset/public-parts-chew.md
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/ui/src/components/ConfigureSSO/steps/SelectProviderStep.tsx
  • packages/ui/src/components/ConfigureSSO/steps/VerifyDomainStep.tsx
  • packages/ui/src/components/ConfigureSSO/steps/ConfigureStep.tsx


// Otherwise, set the provider and create the enterprise connection
try {
await createEnterpriseConnection(selected);
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Some UI tests are failing due to the introduction of the mutation here since we need to mock it - will do that now!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant