feat(ui): Add Google Workspace SAML to self-serve SSO#8690
feat(ui): Add Google Workspace SAML to self-serve SSO#8690LauraBeatris wants to merge 11 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: a1018c2 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 |
@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: |
3fe1741 to
b407275
Compare
b407275 to
f6e8d22
Compare
f6e8d22 to
20ffc64
Compare
20ffc64 to
e22691d
Compare
e22691d to
1e68b4e
Compare
0db7c4c to
10ce4d7
Compare
Previously, the 'Refresh logs' button was triggering a loading state on mount, since the step gets focused and the query gets triggered. We don't need to refetch on window focus, in order to rely on the refresh logs button only + the current internal polling mechanism.
f5f6f55 to
a1018c2
Compare
API Changes Report
Summary
@clerk/sharedCurrent version: 4.14.0 Subpath
|
📝 WalkthroughWalkthroughThis PR adds Google Workspace as a new SAML provider option to the self-serve ConfigureSSO wizard. It introduces shared form infrastructure ( Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 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
🧹 Nitpick comments (1)
packages/ui/src/components/ConfigureSSO/steps/__tests__/SelectProviderStep.test.tsx (1)
105-132: ⚡ Quick winAdd a submit-path test for the new Google provider.
These assertions cover rendering/icons, but they don’t verify wiring. Please add a case that selects Google Workspace, clicks Continue, and asserts
setProvider('saml_google'),createEnterpriseConnection('saml_google', ...), and navigation toconfigure.As per coding guidelines:
**/*.{test,spec}.{ts,tsx}: Unit tests are required for all new functionality.🤖 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/__tests__/SelectProviderStep.test.tsx` around lines 105 - 132, Add a new test in SelectProviderStep.test.tsx that simulates selecting the "Google Workspace" radio, clicking the Continue button, and asserting the wiring: mock and verify setProvider was called with 'saml_google', createEnterpriseConnection was invoked with 'saml_google' and the expected args, and the app navigated to the "configure" route (assert the mocked router/navigation push was called with 'configure'); use the existing createFixtures()/renderStep(wrapper) helpers and the same mocking utilities used elsewhere in this file to locate and click the Continue button and to spy on setProvider, createEnterpriseConnection, and the navigation method.
🤖 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/steps/ConfigureStep/saml/SamlCustomConfigureSteps.tsx`:
- Around line 270-280: The initial mode logic currently sets mode to 'manual'
whenever any SAML config exists (see samlConnection and hasExistingConfig),
which overrides metadata-URL-only setups; change the initializer for the React
state in SamlCustomConfigureSteps (the useState for mode / IdpConfigurationMode)
to prefer 'metadataUrl' when samlConnection?.idpMetadataUrl is present,
otherwise fall back to 'manual' if any other config exists, or 'metadataUrl'
when no config exists per previous behavior; update references to
hasExistingConfig/idpMetadataUrl in the mode initializer accordingly so initial
UI reflects metadata URL setups.
In
`@packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlOktaConfigureSteps.tsx`:
- Around line 468-478: The initial mode logic currently sets mode to 'manual'
whenever any SAML config exists; change this to prefer 'metadataUrl' when the
saved config only contains idpMetadataUrl. Update the initialization of mode
(the React.useState<IdpConfigurationMode> call) to compute an initialMode that
checks samlConnection: if samlConnection?.idpMetadataUrl is present and
idpEntityId, idpSsoUrl, and idpCertificate are absent then use 'metadataUrl',
otherwise if any other fields or idpCertificate exist use 'manual', and fall
back to 'metadataUrl' when no config exists; keep references to samlConnection,
hasExistingConfig (or replace with the new computed initialMode) and
IdpConfigurationMode to locate the change.
In
`@packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/shared/IdentityProviderConfigurationForm.tsx`:
- Around line 161-168: The certificate upload is currently allowing private key
files via the accept prop ('.key') on the FileUploadField inside
IdentityProviderConfigurationForm; remove '.key' from the accept list (keep
.pem, .crt, .cer, .cert) and add server/client-side validation in the
FileUploadField upload handler (used by form.onCertFileChange / form.certFile)
to reject files that contain private key markers (e.g. "-----BEGIN PRIVATE
KEY-----" or "-----BEGIN RSA PRIVATE KEY-----") and surface a clear validation
error to the user; this ensures the accept prop and the FileUploadField both
prevent private-key uploads.
---
Nitpick comments:
In
`@packages/ui/src/components/ConfigureSSO/steps/__tests__/SelectProviderStep.test.tsx`:
- Around line 105-132: Add a new test in SelectProviderStep.test.tsx that
simulates selecting the "Google Workspace" radio, clicking the Continue button,
and asserting the wiring: mock and verify setProvider was called with
'saml_google', createEnterpriseConnection was invoked with 'saml_google' and the
expected args, and the app navigated to the "configure" route (assert the mocked
router/navigation push was called with 'configure'); use the existing
createFixtures()/renderStep(wrapper) helpers and the same mocking utilities used
elsewhere in this file to locate and click the Continue button and to spy on
setProvider, createEnterpriseConnection, and the navigation method.
🪄 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: 48c9bbf8-15ce-459e-91a0-1010da42cdcd
📒 Files selected for processing (18)
.changeset/beige-breads-bathe.mdpackages/localizations/src/en-US.tspackages/shared/src/react/hooks/useEnterpriseConnectionTestRuns.tsxpackages/shared/src/types/elementIds.tspackages/shared/src/types/localization.tspackages/ui/src/components/ConfigureSSO/elements/Stepper/Stepper.tsxpackages/ui/src/components/ConfigureSSO/steps/ConfigureStep/index.tsxpackages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlCustomConfigureSteps.tsxpackages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlGoogleConfigureSteps.tsxpackages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlOktaConfigureSteps.tsxpackages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/index.tsxpackages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/shared/IdentityProviderConfigurationForm.tsxpackages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/shared/IdentityProviderConfigurationModes.tsxpackages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/shared/IdentityProviderMetadataForm.tsxpackages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/shared/useIdentityProviderMetadataForm.tspackages/ui/src/components/ConfigureSSO/steps/SelectProviderStep.tsxpackages/ui/src/components/ConfigureSSO/steps/__tests__/SelectProviderStep.test.tsxpackages/ui/src/components/ConfigureSSO/types.ts
💤 Files with no reviewable changes (2)
- packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/shared/IdentityProviderMetadataForm.tsx
- packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/shared/useIdentityProviderMetadataForm.ts
| <FileUploadField | ||
| field={form.certificateField} | ||
| file={form.certFile} | ||
| onFileChange={form.onCertFileChange} | ||
| existingFilePresent={Boolean(form.existingCertPresent)} | ||
| labels={labels} | ||
| accept='.pem,.key,.crt,.cer,.cert' | ||
| /> |
There was a problem hiding this comment.
Disallow private-key uploads in the certificate field
Line 167 includes .key in accepted extensions. That can lead users to upload private keys as “certificates,” risking secret leakage.
Suggested fix
- accept='.pem,.key,.crt,.cer,.cert'
+ accept='.pem,.crt,.cer,.cert'📝 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.
| <FileUploadField | |
| field={form.certificateField} | |
| file={form.certFile} | |
| onFileChange={form.onCertFileChange} | |
| existingFilePresent={Boolean(form.existingCertPresent)} | |
| labels={labels} | |
| accept='.pem,.key,.crt,.cer,.cert' | |
| /> | |
| <FileUploadField | |
| field={form.certificateField} | |
| file={form.certFile} | |
| onFileChange={form.onCertFileChange} | |
| existingFilePresent={Boolean(form.existingCertPresent)} | |
| labels={labels} | |
| accept='.pem,.crt,.cer,.cert' | |
| /> |
🤖 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/saml/shared/IdentityProviderConfigurationForm.tsx`
around lines 161 - 168, The certificate upload is currently allowing private key
files via the accept prop ('.key') on the FileUploadField inside
IdentityProviderConfigurationForm; remove '.key' from the accept list (keep
.pem, .crt, .cer, .cert) and add server/client-side validation in the
FileUploadField upload handler (used by form.onCertFileChange / form.certFile)
to reject files that contain private key markers (e.g. "-----BEGIN PRIVATE
KEY-----" or "-----BEGIN RSA PRIVATE KEY-----") and surface a clear validation
error to the user; this ensures the accept prop and the FileUploadField both
prevent private-key uploads.
Description
Introduces Google Workspace SAML provider with tailored configure steps
CleanShot.2026-05-28.at.14.28.17.mp4
Unrelated changes/fixes
Checklist
pnpm testruns as expected.pnpm buildruns as expected.Type of change