Skip to content

feat(ui): add OIDC ConfigureSSO wizard skeleton#9200

Open
NicolasLopes7 wants to merge 1 commit into
mainfrom
nicolas/oidc-self-serve-configure
Open

feat(ui): add OIDC ConfigureSSO wizard skeleton#9200
NicolasLopes7 wants to merge 1 commit into
mainfrom
nicolas/oidc-self-serve-configure

Conversation

@NicolasLopes7

@NicolasLopes7 NicolasLopes7 commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds an experimental OIDC provider path to the ConfigureSSO wizard.
  • Provides redirect URI, claims, endpoints, and credentials step skeletons.
  • Handles derived OIDC provider keys safely and adds localization and coverage.

Testing

  • The focused ConfigureSSO domain and hook tests pass.
  • Component-mount tests and UI type-checking are currently blocked by existing cross-package checkout failures, including a missing timeLimit export during Clerk initialization.
CleanShot.2026-07-20.at.17.28.42.mp4

@vercel

vercel Bot commented Jul 20, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment Jul 20, 2026 8:00pm
swingset Ready Ready Preview, Comment Jul 20, 2026 8:00pm

Request Review

@changeset-bot

changeset-bot Bot commented Jul 20, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 09cfbe7

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

This PR includes changesets to release 0 packages

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

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

@pkg-pr-new

pkg-pr-new Bot commented Jul 20, 2026

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

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

@clerk/backend

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

@clerk/chrome-extension

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

@clerk/clerk-js

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

@clerk/electron

npm i https://pkg.pr.new/@clerk/electron@9200

@clerk/electron-passkeys

npm i https://pkg.pr.new/@clerk/electron-passkeys@9200

@clerk/eslint-plugin

npm i https://pkg.pr.new/@clerk/eslint-plugin@9200

@clerk/expo

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

@clerk/expo-passkeys

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

@clerk/express

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

@clerk/fastify

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

@clerk/hono

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

@clerk/localizations

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

@clerk/nextjs

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

@clerk/nuxt

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

@clerk/react

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

@clerk/react-router

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

@clerk/shared

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

@clerk/tanstack-react-start

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

@clerk/testing

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

@clerk/ui

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

@clerk/upgrade

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

@clerk/vue

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

commit: 09cfbe7

@NicolasLopes7
NicolasLopes7 marked this pull request as ready for review July 20, 2026 20:29
@NicolasLopes7
NicolasLopes7 requested a review from dstaley July 20, 2026 20:31
@github-actions

Copy link
Copy Markdown
Contributor

API Changes Report

Generated by Break Check on 2026-07-20T20:32:41.495Z

Summary

Metric Count
Packages analyzed 19
Packages with changes 1
🔴 Breaking changes 0
🟡 Non-breaking changes 1
🟢 Additions 0

🤖 This report was reviewed by claude-sonnet-4-6.


@clerk/shared

Current version: 4.25.5
Recommended bump: MINOR → 4.26.0

Subpath ./types

🟡 Non-breaking Changes (1)

Modified: __internal_LocalizationResource
Diff (before: 1980 lines, after: 1999 lines). Click to expand.
// ... 1309 unchanged lines elided ...
          google: LocalizationValue;
          microsoft: LocalizationValue;
        };
+       oidc: {
+         groupLabel: LocalizationValue;
+         oidcProvider: LocalizationValue;
+       };
        warning: LocalizationValue;
      };
      changeProviderDialog: {
        title: LocalizationValue<'provider'>;
        subtitle: LocalizationValue<'provider' | 'currentProvider'>;
        cancelButton: LocalizationValue;
        confirmButton: LocalizationValue;
      };
      organizationDomainsStep: {
        title: LocalizationValue;
        subtitle: LocalizationValue;
        formFieldLabel__domain: LocalizationValue;
        formFieldInputPlaceholder__domain: LocalizationValue;
        formButtonPrimary__add: LocalizationValue;
        domainSuggestion: {
          messageLabel: LocalizationValue<'domain'>;
          formButtonPrimary__add: LocalizationValue<'domain'>;
        };
        domainCard: {
          badge__verified: LocalizationValue;
          badge__unverified: LocalizationValue;
          badge__expired: LocalizationValue;
          verifiedAtLabel: LocalizationValue<'date'>;
          expiredAtLabel: LocalizationValue<'date'>;
          expiredLabel: LocalizationValue;
          verifyAgainButton: LocalizationValue;
          removeButtonTooltip__lastVerifiedDomain: LocalizationValue;
          removeButtonTooltip__lastVerifiedDomainActive: LocalizationValue;
          txtRecord: {
            instructions: LocalizationValue;
            typeLabel: LocalizationValue;
            hostLabel: LocalizationValue;
            valueLabel: LocalizationValue;
          };
        };
        removeDomainDialog: {
          title: LocalizationValue;
          subtitle__active: LocalizationValue<'domain'>;
          subtitle__inactive: LocalizationValue<'domain'>;
          cancelButton: LocalizationValue;
          removeButton: LocalizationValue;
        };
      };
      testConfigurationStep: {
        title: LocalizationValue;
        subtitle: LocalizationValue;
        error__noSuccessfulTestRun: LocalizationValue;
        testUrl: {
          actionLabel__open: LocalizationValue;
        };
        testResults: {
          title: LocalizationValue;
          actionLabel__refresh: LocalizationValue;
          polling: LocalizationValue;
          status__success: LocalizationValue;
          status__failed: LocalizationValue;
          status__pending: LocalizationValue;
          empty: {
            title: LocalizationValue;
            subtitle: LocalizationValue;
          };
        };
        testRunDetails: {
          title: LocalizationValue;
          runDetails: {
            sectionTitle: LocalizationValue;
            timestamp: LocalizationValue;
            status: LocalizationValue;
            errorCode: LocalizationValue;
            fullMessage: LocalizationValue;
            actionLabel__copy: LocalizationValue;
            actionLabel__copied: LocalizationValue;
          };
          parsedUserInfo: {
            sectionTitle: LocalizationValue;
            email: LocalizationValue;
            firstName: LocalizationValue;
          };
          howToFix: {
            sectionTitle: LocalizationValue;
            actionLabel__viewDocumentation: LocalizationValue;
            saml_user_attribute_missing: {
              intro: LocalizationValue;
              step1: LocalizationValue;
              step2: LocalizationValue;
              step3: LocalizationValue;
            };
            saml_response_relaystate_missing: {
              description: LocalizationValue;
            };
            saml_email_address_domain_mismatch: {
              description: LocalizationValue;
            };
            oauth_access_denied: {
              description: LocalizationValue;
            };
            oauth_token_exchange_error: {
              description: LocalizationValue;
            };
            oauth_fetch_user_error: {
              intro: LocalizationValue;
              step1: LocalizationValue;
              step2: LocalizationValue;
            };
          };
        };
      };
      configureStep: {
        attributeMappingTable: {
          badges: {
            required: LocalizationValue;
            optional: LocalizationValue;
          };
        };
        activeConnectionWarning: {
          title: LocalizationValue;
          dismiss: LocalizationValue;
+       };
+       oidcCustom: {
+         mainHeaderTitle: LocalizationValue;
+         redirectUriStep: {
+           headerSubtitle: LocalizationValue;
+         };
+         claimsStep: {
+           headerSubtitle: LocalizationValue;
+         };
+         endpointsStep: {
+           headerSubtitle: LocalizationValue;
+         };
+         credentialsStep: {
+           headerSubtitle: LocalizationValue;
+         };
        };
        samlOkta: {
          mainHeaderTitle: LocalizationValue;
// ... 548 unchanged lines elided ...

Static analyzer: Breaking change in type alias __internal_LocalizationResource: Type changed: {locale:string;maintenanceMode:import("@clerk/shared").LocalizationValue;roles:{[r:string]:import("@clerk/shared").Loca…{locale:string;maintenanceMode:import("@clerk/shared").LocalizationValue;roles:{[r:string]:import("@clerk/shared").Loca…

🤖 AI review (reclassified as non-breaking) (80%): The before/after snippets are structurally identical at both ends of the elided region; the only visible difference is '1900 lines elided' vs '1919 lines elided', indicating ~19 new properties were added to the large object. __internal_LocalizationResource is used exclusively as the source for LocalizationResource via DeepPartial<DeepLocalizationWithoutObjects<__internal_LocalizationResource>>, making it an output/read type. Adding new required properties to a type that consumers only read (not construct) is non-breaking per rule 11.


Report generated by Break Check

Last ran on 09cfbe7.

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds OIDC provider type definitions and provider-specific enterprise connection validation. The SSO provider selector now conditionally displays and normalizes OIDC providers behind a feature flag. Provider routing recognizes backend-derived OIDC identifiers and renders an unsupported state for unknown providers. A four-step OIDC configuration wizard was added with localized labels and navigation controls, alongside expanded domain, selector, routing, and hook tests and two changeset entries.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • clerk/javascript#9198: Uses the same isOIDCFlowEnabled flag to conditionally render the OIDC provider card and extends related tests.

Suggested reviewers: laurabeatris

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: adding an OIDC ConfigureSSO wizard skeleton.
Description check ✅ Passed The description matches the changeset and clearly describes the OIDC wizard path, steps, localization, and testing.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.

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

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

🤖 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/domain/organizationEnterpriseConnection.ts`:
- Line 16: Update isOidcProvider to require the `oidc_` prefix, matching the
OidcProviderType contract and excluding bare or malformed values such as `oidc`
and `oidcfoo`; add a regression test covering these unsupported inputs and
preserving valid OIDC values.

In `@packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/index.tsx`:
- Around line 90-96: Localize the unsupported-provider fallback in the
ConfigureStep component by adding typed
configureSSO.configureStep.unsupportedProvider resource keys for the title and
description, then render both through localizationKeys. Follow the existing OIDC
localization contract and keep the terminal UI on the same localization path
instead of using English literals.
🪄 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 Plus

Run ID: 7c43c83d-8790-40f9-a66e-d611f185371a

📥 Commits

Reviewing files that changed from the base of the PR and between c904fb4 and 09cfbe7.

📒 Files selected for processing (14)
  • .changeset/cool-dragons-march.md
  • .changeset/spotty-items-dream.md
  • packages/localizations/src/en-US.ts
  • packages/shared/src/types/localization.ts
  • packages/ui/src/components/ConfigureSSO/domain/__tests__/organizationEnterpriseConnection.test.ts
  • packages/ui/src/components/ConfigureSSO/domain/organizationEnterpriseConnection.ts
  • packages/ui/src/components/ConfigureSSO/hooks/__tests__/useOrganizationEnterpriseConnection.test.tsx
  • packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/__tests__/ConfigureStep.test.tsx
  • packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/index.tsx
  • packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/oidc/OidcCustomConfigureSteps.tsx
  • packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/oidc/index.tsx
  • packages/ui/src/components/ConfigureSSO/steps/SelectProviderStep.tsx
  • packages/ui/src/components/ConfigureSSO/steps/__tests__/SelectProviderStep.test.tsx
  • packages/ui/src/components/ConfigureSSO/types.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • clerk/clerk_go (manual)
  • clerk/dashboard (manual)
  • clerk/accounts (manual)
  • clerk/backoffice (manual)
  • clerk/clerk (manual)
  • clerk/clerk-docs (manual)
  • clerk/cloudflare-workers (manual)

* not a fixed enum. SAML providers stay exact literals. Single source of the
* prefix notion — dispatch and configuration checks both read it from here.
*/
export const isOidcProvider = (provider: string): provider is OidcProviderType => provider.startsWith('oidc');

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Match the guard to the OIDC key contract.

Line 16 classifies oidc and oidcfoo as OIDC even though they do not match OidcProviderType (oidc_${string}). This can route malformed backend values into the OIDC wizard instead of the unsupported-provider fallback. Require the underscore delimiter and add a regression test.

Proposed fix
-export const isOidcProvider = (provider: string): provider is OidcProviderType => provider.startsWith('oidc');
+export const isOidcProvider = (provider: string): provider is OidcProviderType => provider.startsWith('oidc_');
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const isOidcProvider = (provider: string): provider is OidcProviderType => provider.startsWith('oidc');
export const isOidcProvider = (provider: string): provider is OidcProviderType => provider.startsWith('oidc_');
🤖 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/domain/organizationEnterpriseConnection.ts`
at line 16, Update isOidcProvider to require the `oidc_` prefix, matching the
OidcProviderType contract and excluding bare or malformed values such as `oidc`
and `oidcfoo`; add a regression test covering these unsupported inputs and
preserving valid OIDC values.

Comment on lines +90 to +96
// A provider the SDK doesn't recognize (e.g. a newer backend family)
// degrades to a terminal state instead of white-screening the wizard.
<>
<Step.Header
title='Unsupported provider'
description='This identity provider isn’t supported in this version of Clerk. Update to the latest version to finish setting it up.'
/>

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Localize the unsupported-provider fallback.

These literals bypass the localization resource, so non-English installations always receive English. Add typed configureSSO.configureStep.unsupportedProvider keys and render them through localizationKeys.

Based on the existing OIDC localization contract, keep this terminal UI in the same localization path.

🤖 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/index.tsx` around
lines 90 - 96, Localize the unsupported-provider fallback in the ConfigureStep
component by adding typed configureSSO.configureStep.unsupportedProvider
resource keys for the title and description, then render both through
localizationKeys. Follow the existing OIDC localization contract and keep the
terminal UI on the same localization path instead of using English literals.

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