feat(ui): build out Okta Configure step UI in ConfigureSSO#8535
Open
iagodahlem wants to merge 18 commits into
Open
feat(ui): build out Okta Configure step UI in ConfigureSSO#8535iagodahlem wants to merge 18 commits into
iagodahlem wants to merge 18 commits into
Conversation
🦋 Changeset detectedLatest commit: efdc631 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.
|
9 tasks
| const ATTRIBUTE_PAIRS = [ | ||
| { | ||
| id: 'email', | ||
| name: localizationKeys('configureSSO.configureStep.samlOkta.configureAttributes.pairs.email.name'), |
Member
There was a problem hiding this comment.
In follow-up PRs, are we going to refactor those to receive the IdP type as a param in order to return different localization keys?
Member
Author
There was a problem hiding this comment.
Yep, that's the idea. The provider is already available from the ConfigureSSOContext. For now, it will always render as if Okta was selected.
LauraBeatris
approved these changes
May 13, 2026
facf667 to
fecd7a4
Compare
9ac22ff to
847bbd2
Compare
Adds the Okta SAML metadata URL path to the Configure step. The user
pastes their IdP metadata URL and the wizard advances on a successful
PATCH to user.updateEnterpriseConnection with { saml: { idpMetadataUrl } }.
The mutation is wrapped in useReverification, matching the established
convention for sensitive user.* mutations in @clerk/ui. useCardState
drives the loading state; handleError routes backend errors inline under
the field when the API returns idp_metadata_url, or to the card-level
error surface otherwise. Locale keys added under configureSSO.configureStep
in en-US.
Manual entry, file upload, SP-side copy rows, and the Okta admin-console
walkthrough are deferred to follow-up PRs.
Unblocks type-check for the SAML metadata URL input added to the ConfigureSSO Configure step.
…ider
Mirrors the existing createConnection pattern: ConfigureSSOCardContent
destructures updateEnterpriseConnection from
__internal_useUserEnterpriseConnections and passes it as a prop to
ConfigureSSOProvider, which wraps it once in useReverification and exposes
it as updateConnection on the context.
The id is taken implicitly from enterpriseConnection in context, so call
sites don't thread it through. ConfigureStep now just calls
updateConnection({ saml: { idpMetadataUrl } }) and gets both
reverification and query revalidation for free, since the hook owns the
revalidate call after a successful mutation.
Drops the infoText option on useFormControl (which renders the helper copy as a focus-triggered tooltip) and places the description as a static <Text> element above the input. Styling mirrors the muted-body treatment used in SelectProviderStep so the inline copy reads the same as the tooltip did. Also tightens the placeholder copy from the dummy metadata URL to a neutral 'Paste URL here...'.
Mirrors VerifyDomainStep's nested wizard pattern: the outer Step is now a pure shell wrapping an inner Wizard with four Wizard.Step children — create-app, configure-attributes, assign-users, submit-saml-config. Step.Header renders an InnerStepCounter so the body shows Step X/4 as the user moves through the sub-steps. The existing metadata URL form moves into SubmitSamlConfigSubStep unchanged — same useReverification, useCardState, handleError wiring, same field, same PATCH. The first three sub-steps are placeholders with Previous/Continue scaffolding; content lands in follow-up commits. goNext/goPrev bubble across the wizard boundary natively (the Wizard primitive supports nested parent navigation), so the form's Continue handler still advances to the outer Test step on a successful PATCH without any cross-boundary plumbing.
Adds flex:1 to SubmitSamlConfigSubStep's Step.Section (was missing, so the footer didn't sit flush with the card edge) and drops the align/justify props on the placeholder sub-steps. Pure layout polish.
The function previously ran deepCamelToSnake(params), producing a nested
body like { saml: { idp_metadata_url } }. The backend expects the SAML
and OIDC fields prefixed at the top level (saml_idp_metadata_url,
oidc_client_id, etc.), so IdP metadata submissions in
<__experimental_ConfigureSSO /> were silently rejected.
Replaces the helper with a manual flat-field mapper: top-level fields
stay top-level, SAML fields get a saml_ prefix, OIDC fields get an oidc_
prefix. attribute_mapping and custom_attributes pass through unchanged
since their inner keys are user-supplied and must not be transformed.
A small setIfDefined helper makes the omit-undefined / forward-null
semantics explicit, so users can clear a field by sending null without
the SDK silently dropping it.
Mirrors the fix Laura validated in the SAML POC PR.
Step.Body already fills the vertical space between header and footer,
but Step.Section as a flex item defaults to flex:0 — so sections inside
the body shrink to content height unless told to grow. Until now each
sub-step had to repeat sx={{ flex: 1 }} on its Step.Section.
Defaulting flex:1 on Step.Section doesn't work because Step.Header
reuses the same primitive internally and needs to stay content-height,
and a single sub-step may stack multiple Sections where only one should
fill.
Adds an opt-in fill boolean prop. <Step.Section fill> applies flex:1;
the default behavior stays unchanged. Updates the four Configure
sub-step bodies to use the new prop. Other consumers (VerifyDomain,
SelectProvider) keep the old sx={{ flex: 1 }} pattern and can adopt the
prop in follow-ups.
Replaces the placeholder body of the first inner sub-step with three
stacked content groups:
1. Create new Okta app — section heading + bulleted list of 5
Okta admin-console steps (Sign in to Okta, click Create App
Integration, select SAML 2.0, fill General Settings, click Next).
2. Configure service provider — section heading + 2 description
paragraphs + 2 read-only copy rows for the SP-side ACS URL and
Audience URI. Values pull from connection.samlConnection.acsUrl
and spEntityId in the provider context. Uses the existing
ClipboardInput primitive so each row gets a copy-to-clipboard
button.
3. Complete SAML integration — section heading + bulleted list of
2 follow-up Okta admin-console steps.
All three groups live in one Step.Section fill with a generous gap so
the body scrolls naturally if needed; Step.Header keeps the only
border-bottom separator.
Bold keywords inside instruction lines (Admin → Applications,
Create App Integration, SAML 2.0, etc.) are split into prefix / bold /
suffix localization keys per line. Clerk's localization helper only
supports {{token}} string interpolation, so this keeps the bold span
themable through the existing Text primitive while still letting
translators see each instruction line as discrete units.
Locale keys added under configureSSO.configureStep.createApp in en-US.
Layout tightening across the inner Configure wizard: - Move Step.Body inside each sub-step component so the wizard switches bodies cleanly between sub-steps instead of nesting Wizard.Step children under a single outer Step.Body. - Wrap the ACS URL and Audience URI copy rows in Form.ControlRow + Form.CommonInputWrapper + ClipboardInput so the rows reuse the standard form chrome (label rendering, error slot, spacing) and the ClipboardInput primitive's readOnly + copyIcon/copiedIcon API. Adds 'acsUrl' to the FieldId union to back the new useFormControl call sites. - Bring group headings down to textVariant='subtitle' so the body reads as supporting content under the existing Step.Header title. - Tighten vertical spacing: Step.Section gap drops from $6 to $5, inner-group heading-to-content gap from $3 to $1x5, list-item gap from $1 to $1x5. - Soften the bold span in instructional lines from $semibold + $colorForeground to $medium + $colorMutedForeground so the emphasis feels like keyword highlighting rather than full bold.
Replaces the placeholder body of the second inner sub-step with two stacked content groups: 1. SAML attribute mapping — section heading + a 3-row attribute table built from the Table primitives (Thead / Tbody / Tr / Th / Td) and rendered with monospace claim-name cells. Each row pairs the attribute label with a Badge: warning colorScheme for the required Email row, secondary colorScheme for the optional First/Last name rows. Claim names render in an inline code span using the same monospace + neutralAlpha100 background + small radius styling as the InstructionStepWithCode helper. 2. Verify the attribute mappings in Okta — description paragraph + a numbered ordered list of 9 Okta admin-console steps. Shape-A lines (1, 4, 7) use the existing InstructionStep helper (prefix / bold / suffix); Shape-B lines (2, 3, 5, 6, 8, 9) use the new InstructionStepWithCode helper (prefix / bold / middle / code / suffix) so the mail / firstName / lastName values render as inline code spans. Mirrors the layout conventions established in the sibling sub-step (Step.Body inside the sub-step, single Step.Section with gap $5, inner groups in Cols with gap $1x5, headings as textVariant subtitle, medium-weight muted bold span). Adds the matching locale type entries and English copy under configureSSO.configureStep.configureAttributes.
…table styling
Replaces sx={{ color: $colorMutedForeground }} with Text colorScheme='secondary'
across ConfigureAttributesSubStep — the prop already resolves to the same color
token, so the inline sx call drops out cleanly.
Tightens the attribute mapping table chrome: column headers shrink to
fontSize=$xs, the first column picks up an inline-start pad so the leading
cell breathes against the table edge, and the claim-name cells reduce to
fontFamily: monospace only (drops the background, border-radius, and
padding from the earlier 'code chip' treatment for a flatter look that
reads as data, not as inline code).
Inner Cols inside ConfigureAttributesSubStep step up from gap $1x5 to $3.
Numbered/bulleted list indents grow from paddingInlineStart $4 to $5.
…opt inline rich-text markup
Restructures localization keys under configureSSO.configureStep so future
SAML providers (Custom SAML) and OIDC can drop in alongside Okta without
duplicating shared copy:
- spFields and attributeMapping live at the top level since their labels,
table content, badges, and the "These are the defaults..." paragraph
read the same regardless of provider.
- samlOkta now owns provider-specific copy: title, subtitle, createApp
walkthrough, serviceProvider narrative, completeSamlIntegration steps,
configureAttributes pairs, metadataUrl. When Custom SAML lands, a
sibling samlCustom namespace mirrors this shape.
Replaces the InstructionStep and InstructionStepWithCode helpers (which
required 3 or 5 separate keys per sentence) with a single RichText
component that parses inline <strong>...</strong> and <code>...</code>
markup in a localized string. One key per sentence, translators see the
whole context, emphasis stays themable through Text spans.
ConfigureAttributesSubStep redesigned to match Figma 8032:14794:
- Claim names in the attribute mapping table are now user.email,
user.firstName, user.lastName (corrects user.profile.email).
- The verify-mappings list collapses from 9 separate numbered steps to 2,
with a nested bulleted sub-list of the name/expression pairs the user
enters in Okta.
- Table rows render from an ATTRIBUTE_ROWS constant so the row markup
isn't duplicated three times.
- Verify-mappings pairs render from an ATTRIBUTE_PAIRS constant for the
same reason.
Sweeps remaining sx={{ color: $colorMutedForeground }} call sites in the
Configure sub-steps over to Text colorScheme='secondary' to match the
pattern used elsewhere in the file.
…ns back to multi-key inline spans
Drops the RichText helper, parseRichText helper, and the
<strong>/<code> markup convention added in the previous commit.
Each instructional line in the Configure sub-steps now uses three
(or more) separate localization keys per sentence — prefix, bold,
suffix — rendered inline as Text-as-span children of a single
Text-as-li parent. Matches Laura's verifyEmailDomainStep precedent
and uses vanilla Clerk localization primitives end-to-end.
The attribute-mapping pairs in ConfigureAttributesSubStep render
as Badge components rather than inline monospace code spans. Each
pair is now name + conjunction + expression — three locale keys
per pair, with the conjunction localized so other languages can
pick their own.
Adds the third inner sub-step, AssignUsersSubStep, with the same
structure as the other sub-steps: section heading, description
paragraph, and a numbered ordered list of five Okta admin-console
steps walking the user through the Assignments tab flow. Step 2
has three emphasized keywords ("Assign", "Assign to people",
"Assign to groups") and uses a seven-key inline shape; the other
steps use the standard three-key shape, except step 3 which is
plain prose and renders as a single Text-as-li.
All new copy lives under configureSSO.configureStep.samlOkta so
Custom SAML and OIDC siblings can drop in without colliding.
Sets the Optional badge to colorScheme='primary' explicitly rather than falling through to Badge's default, so the styling is intentional. Swaps the pairs sub-list bullet from listStyleType: 'disc' to a literal '- ' marker so the dash sits closer to the badges and reads as a softer delimiter than the filled disc.
…n SubmitSamlConfigSubStep Mirrors the same pattern Iago adopted for SelectProviderStep: ConfigureSSOProvider no longer plumbs the enterprise-connection mutation through. SubmitSamlConfigSubStep now calls __internal_useUserEnterpriseConnections itself, grabs updateEnterpriseConnection, and wraps it in a local useReverification(useCallback(...)). Drops updateConnection from ConfigureSSOData, drops updateEnterpriseConnection from ConfigureSSOProviderProps, and stops threading the function through ConfigureSSO.tsx. The provider keeps ownership of provider-selection state (provider, setProvider, createConnection) since SelectProviderStep's create-flow still expects that shape until it gets the same treatment next.
fecd7a4 to
43b002f
Compare
…y per line Drops the prefix/bold/suffix (and the seven-key prefix/bold1/middle1/.../suffix on Assign Users step 2) shapes that we were threading through nested Text-as-span chains in the Configure sub-steps. Each Okta-walkthrough sentence now lives under one LocalizationValue, rendered as a single Text-as-li with localizationKey. A guide for safely embedding bold or other inline emphasis inside LocalizationValue strings is being prepared. Until that primitive lands the sub-steps read as plain prose — visually less hierarchy on the emphasized keywords, but a much smaller key surface and no fragile multi-span composition. The attribute-mapping pairs in Configure Attributes still use a pair of Badges plus a localized conjunction so each value stays themable as a distinct chip rather than collapsing into the surrounding sentence.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Builds out the Configure step UI for
<__experimental_ConfigureSSO />(Okta provider). The Configure step is now a nested 4-sub-step inner wizard, mirroring the pattern Laura established for the Verify Domain step:connection.samlConnection.{acsUrl, spEntityId}.user.email/user.firstName/user.lastNameclaim names) + guidance on setting up Okta's Attribute Statements, with name/expression pairs rendered as badges.PATCH /me/enterprise_connections/{id}with{ saml: { idpMetadataUrl } }.The mutation is hoisted onto
ConfigureSSOProviderand wrapped inuseReverification, matching the convention for sensitiveuser.*mutations in@clerk/ui.useCardStatedrives the loading state;handleErrorroutes backend errors inline under the field when the API returnsidp_metadata_url, or to the card-level error surface otherwise. The hook owns query revalidation after a successful mutation, so the in-contextenterpriseConnectionreflects the new IdP metadata without an explicit refetch.Locale keys live under
configureSSO.configureStep. Shared keys (attribute mapping table, badges, SP field labels) sit at the top of the namespace; provider-specific copy lives underconfigureSSO.configureStep.samlOkta. Future Custom SAML and OIDC providers can drop in a sibling namespace without colliding.Also fixes
toMeEnterpriseConnectionBodyin@clerk/clerk-jsto emit a flat snake-case body (saml_idp_metadata_url) instead of the nested shape (saml: { idp_metadata_url }) the previous helper produced. The backend expects flat-prefixed fields, so the prior shape was silently rejected foruser.createEnterpriseConnectionanduser.updateEnterpriseConnection.Linear: ORGS-1456
Follow-ups (separate PR)
The "Configure manually" segmented-control mode of sub-step 4 ships in a follow-up PR. That adds:
FieldIdentries)Tests for the Configure sub-steps ship alongside Laura's #8520 follow-up sweep once both land.
How to test
In a sandbox with the ConfigureSSO wizard, enter through Select Provider → Verify Domain → land on Configure. Walk through sub-steps 1 through 3 (Previous / Continue navigate the inner wizard), then on sub-step 4 paste a valid Okta SAML metadata URL → Continue → connection is patched and the wizard advances to Test. Backend errors keyed
idp_metadata_urlrender inline; others surface at the card level.Base
Stacked on #8503. GitHub will auto-retarget this PR to `main` once that merges.
Checklist
Type of change