feat(ui): Add support for custom SAML provider in <ConfigureSSO />#8564
feat(ui): Add support for custom SAML provider in <ConfigureSSO />#8564LauraBeatris wants to merge 4 commits into
<ConfigureSSO />#8564Conversation
🦋 Changeset detectedLatest commit: c32fda9 The changes in this PR will be included in the next version bump. This PR includes changesets to release 20 packages
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 |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
8c97f7e to
6f1a6dd
Compare
6f1a6dd to
14bdeb2
Compare
| ); | ||
| }; | ||
|
|
||
| // TODO - Move IdP specific content to separate modules |
There was a problem hiding this comment.
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
📝 WalkthroughWalkthroughThis 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
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
There was a problem hiding this comment.
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 winManual 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
📒 Files selected for processing (8)
.changeset/public-parts-chew.mdpackages/localizations/src/en-US.tspackages/shared/src/types/localization.tspackages/ui/src/components/ConfigureSSO/ConfigureSSOContext.tsxpackages/ui/src/components/ConfigureSSO/steps/ConfigureStep.tsxpackages/ui/src/components/ConfigureSSO/steps/SelectProviderStep.tsxpackages/ui/src/components/ConfigureSSO/steps/VerifyDomainStep.tsxpackages/ui/src/components/ConfigureSSO/steps/configureStepTranslations.ts
9f50403 to
51f8039
Compare
@clerk/astro
@clerk/backend
@clerk/chrome-extension
@clerk/clerk-js
@clerk/dev-cli
@clerk/expo
@clerk/expo-passkeys
@clerk/express
@clerk/fastify
@clerk/hono
@clerk/localizations
@clerk/nextjs
@clerk/nuxt
@clerk/react
@clerk/react-router
@clerk/shared
@clerk/tanstack-react-start
@clerk/testing
@clerk/ui
@clerk/upgrade
@clerk/vue
commit: |
51f8039 to
04a3028
Compare
04a3028 to
c32fda9
Compare
| return; | ||
| } | ||
|
|
||
| // If the user's primary email address is not verified, go to the verify email address step |
There was a problem hiding this comment.
This will likely change with a "broader" verification aspect once we introduce DNS verification as well, but I'd avoid abstracting for now
There was a problem hiding this comment.
♻️ Duplicate comments (1)
packages/ui/src/components/ConfigureSSO/ConfigureSSOContext.tsx (1)
67-69:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winMissing email domain resolves silently, advancing the wizard incorrectly.
When
emailDomainis 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
📒 Files selected for processing (5)
.changeset/public-parts-chew.mdpackages/ui/src/components/ConfigureSSO/ConfigureSSOContext.tsxpackages/ui/src/components/ConfigureSSO/steps/ConfigureStep.tsxpackages/ui/src/components/ConfigureSSO/steps/SelectProviderStep.tsxpackages/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); |
There was a problem hiding this comment.
Some UI tests are failing due to the introduction of the mutation here since we need to mock it - will do that now!
Description
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 testruns as expected.pnpm buildruns as expected.Type of change