From 7eebf51d5803b73b8533d365264e9f5659499b34 Mon Sep 17 00:00:00 2001 From: Laura Beatris <48022589+LauraBeatris@users.noreply.github.com> Date: Thu, 27 Nov 2025 19:18:28 -0300 Subject: [PATCH 1/2] Remove deprecated `saml` strategy --- .../clerk-js/src/core/resources/SignIn.ts | 9 +----- .../__tests__/completeSignUpFlow.test.ts | 28 ------------------- .../internal/clerk-js/completeSignUpFlow.ts | 2 +- packages/shared/src/types/factors.ts | 10 ------- packages/shared/src/types/redirects.ts | 6 ++-- packages/shared/src/types/signInCommon.ts | 8 +----- packages/shared/src/types/signInFuture.ts | 2 +- packages/shared/src/types/signUpCommon.ts | 6 ++-- packages/shared/src/types/strategies.ts | 5 ---- .../ui/src/components/SignIn/SignInStart.tsx | 7 ++--- .../SignIn/__tests__/SignInStart.test.tsx | 24 ---------------- .../SignIn/handleCombinedFlowTransfer.ts | 4 +-- .../ui/src/components/SignUp/SignUpStart.tsx | 2 +- .../__tests__/AccountPage.test.tsx | 6 ++-- .../EnterpriseAccountsSection.test.tsx | 5 ++-- .../__tests__/PasswordSection.test.tsx | 8 +++--- .../__tests__/SecurityPage.test.tsx | 4 +-- .../__tests__/UserProfileSection.test.tsx | 4 +-- 18 files changed, 27 insertions(+), 113 deletions(-) diff --git a/packages/clerk-js/src/core/resources/SignIn.ts b/packages/clerk-js/src/core/resources/SignIn.ts index 1eeed1b2ae0..a0704986521 100644 --- a/packages/clerk-js/src/core/resources/SignIn.ts +++ b/packages/clerk-js/src/core/resources/SignIn.ts @@ -32,7 +32,6 @@ import type { ResetPasswordEmailCodeFactorConfig, ResetPasswordParams, ResetPasswordPhoneCodeFactorConfig, - SamlConfig, SignInCreateParams, SignInFirstFactor, SignInFutureBackupCodeVerifyParams, @@ -211,12 +210,6 @@ export class SignIn extends BaseResource implements SignInResource { case 'reset_password_email_code': config = { emailAddressId: params.emailAddressId } as ResetPasswordEmailCodeFactorConfig; break; - case 'saml': - config = { - redirectUrl: params.redirectUrl, - actionCompleteRedirectUrl: params.actionCompleteRedirectUrl, - } as SamlConfig; - break; case 'enterprise_sso': config = { redirectUrl: params.redirectUrl, @@ -336,7 +329,7 @@ export class SignIn extends BaseResource implements SignInResource { }); } - if (strategy === 'saml' || strategy === 'enterprise_sso') { + if (strategy === 'enterprise_sso') { await this.prepareFirstFactor({ strategy, redirectUrl, diff --git a/packages/shared/src/internal/clerk-js/__tests__/completeSignUpFlow.test.ts b/packages/shared/src/internal/clerk-js/__tests__/completeSignUpFlow.test.ts index 237bebe54ce..587b2547215 100644 --- a/packages/shared/src/internal/clerk-js/__tests__/completeSignUpFlow.test.ts +++ b/packages/shared/src/internal/clerk-js/__tests__/completeSignUpFlow.test.ts @@ -85,34 +85,6 @@ describe('completeSignUpFlow', () => { expect(mockNavigate).not.toHaveBeenCalled(); }); - it('initiates a SAML flow if saml is listed as a missing field', async () => { - const redirectUrl = 'https://www.in.gr/acs'; - const redirectUrlComplete = 'https://www.in.gr/tada'; - - const mockSignUp = { - status: 'missing_requirements', - missingFields: ['saml'], - authenticateWithRedirect: mockAuthenticateWithRedirect, - } as unknown as SignUpResource; - - await completeSignUpFlow({ - signUp: mockSignUp, - handleComplete: mockHandleComplete, - navigate: mockNavigate, - redirectUrl: 'https://www.in.gr/acs', - redirectUrlComplete: 'https://www.in.gr/tada', - }); - - expect(mockHandleComplete).not.toHaveBeenCalled(); - expect(mockNavigate).not.toHaveBeenCalled(); - expect(mockAuthenticateWithRedirect).toHaveBeenCalledWith({ - strategy: 'enterprise_sso', - redirectUrl, - redirectUrlComplete, - continueSignUp: true, - }); - }); - it('initiates a Enterprise SSO flow if enterprise_sso is listed as a missing field', async () => { const redirectUrl = 'https://www.in.gr/acs'; const redirectUrlComplete = 'https://www.in.gr/tada'; diff --git a/packages/shared/src/internal/clerk-js/completeSignUpFlow.ts b/packages/shared/src/internal/clerk-js/completeSignUpFlow.ts index 0d2ac718471..09b39203e0a 100644 --- a/packages/shared/src/internal/clerk-js/completeSignUpFlow.ts +++ b/packages/shared/src/internal/clerk-js/completeSignUpFlow.ts @@ -27,7 +27,7 @@ export const completeSignUpFlow = ({ if (signUp.status === 'complete') { return handleComplete && handleComplete(); } else if (signUp.status === 'missing_requirements') { - if (signUp.missingFields.some(mf => mf === 'saml' || mf === 'enterprise_sso')) { + if (signUp.missingFields.some(mf => mf === 'enterprise_sso')) { return signUp.authenticateWithRedirect({ strategy: 'enterprise_sso', redirectUrl, diff --git a/packages/shared/src/types/factors.ts b/packages/shared/src/types/factors.ts index 9dff219ff14..370637ebce3 100644 --- a/packages/shared/src/types/factors.ts +++ b/packages/shared/src/types/factors.ts @@ -11,7 +11,6 @@ import type { PhoneCodeStrategy, ResetPasswordEmailCodeStrategy, ResetPasswordPhoneCodeStrategy, - SamlStrategy, TOTPStrategy, Web3Strategy, } from './strategies'; @@ -57,10 +56,6 @@ export type OauthFactor = { strategy: OAuthStrategy; }; -export type SamlFactor = { - strategy: SamlStrategy; -}; - export type EnterpriseSSOFactor = { strategy: EnterpriseSSOStrategy; /** @@ -115,11 +110,6 @@ export type OAuthConfig = OauthFactor & { oidcLoginHint?: string; }; -export type SamlConfig = SamlFactor & { - redirectUrl: string; - actionCompleteRedirectUrl: string; -}; - export type EnterpriseSSOConfig = EnterpriseSSOFactor & { redirectUrl: string; actionCompleteRedirectUrl: string; diff --git a/packages/shared/src/types/redirects.ts b/packages/shared/src/types/redirects.ts index 478688bacae..bafcdf1db63 100644 --- a/packages/shared/src/types/redirects.ts +++ b/packages/shared/src/types/redirects.ts @@ -1,4 +1,4 @@ -import type { EnterpriseSSOStrategy, OAuthStrategy, SamlStrategy } from './strategies'; +import type { EnterpriseSSOStrategy, OAuthStrategy } from './strategies'; export type AfterSignOutUrl = { /** @@ -50,9 +50,9 @@ export type AuthenticateWithRedirectParams = { /** * One of the supported OAuth providers you can use to authenticate with, eg 'oauth_google'. - * Alternatively `saml` or `enterprise_sso`, to authenticate with Enterprise SSO. + * Alternatively `enterprise_sso`, to authenticate with Enterprise SSO. */ - strategy: OAuthStrategy | SamlStrategy | EnterpriseSSOStrategy; + strategy: OAuthStrategy | EnterpriseSSOStrategy; /** * Identifier to use for targeting a Enterprise Connection at sign-in diff --git a/packages/shared/src/types/signInCommon.ts b/packages/shared/src/types/signInCommon.ts index de07635a6d3..66f6f816562 100644 --- a/packages/shared/src/types/signInCommon.ts +++ b/packages/shared/src/types/signInCommon.ts @@ -26,8 +26,6 @@ import type { ResetPasswordPhoneCodeAttempt, ResetPasswordPhoneCodeFactor, ResetPasswordPhoneCodeFactorConfig, - SamlConfig, - SamlFactor, TOTPAttempt, TOTPFactor, Web3Attempt, @@ -53,7 +51,6 @@ import type { PhoneCodeStrategy, ResetPasswordEmailCodeStrategy, ResetPasswordPhoneCodeStrategy, - SamlStrategy, TicketStrategy, TOTPStrategy, Web3Strategy, @@ -83,7 +80,6 @@ export type SignInFirstFactor = | ResetPasswordEmailCodeFactor | Web3SignatureFactor | OauthFactor - | SamlFactor | EnterpriseSSOFactor; export type SignInSecondFactor = PhoneCodeFactor | TOTPFactor | BackupCodeFactor | EmailCodeFactor | EmailLinkFactor; @@ -106,7 +102,6 @@ export type PrepareFirstFactorParams = | ResetPasswordPhoneCodeFactorConfig | ResetPasswordEmailCodeFactorConfig | OAuthConfig - | SamlConfig | EnterpriseSSOConfig; export type AttemptFirstFactorParams = @@ -124,7 +119,7 @@ export type AttemptSecondFactorParams = PhoneCodeAttempt | TOTPAttempt | BackupC export type SignInCreateParams = ( | { - strategy: OAuthStrategy | SamlStrategy | EnterpriseSSOStrategy; + strategy: OAuthStrategy | EnterpriseSSOStrategy; redirectUrl: string; actionCompleteRedirectUrl?: string; identifier?: string; @@ -195,5 +190,4 @@ export type SignInStrategy = | TOTPStrategy | BackupCodeStrategy | OAuthStrategy - | SamlStrategy | EnterpriseSSOStrategy; diff --git a/packages/shared/src/types/signInFuture.ts b/packages/shared/src/types/signInFuture.ts index 48deaf145ef..85673534f7e 100644 --- a/packages/shared/src/types/signInFuture.ts +++ b/packages/shared/src/types/signInFuture.ts @@ -15,7 +15,7 @@ export interface SignInFutureCreateParams { * The first factor verification strategy to use in the sign-in flow. Depends on the `identifier` value. Each * authentication identifier supports different verification strategies. */ - strategy?: OAuthStrategy | 'saml' | 'enterprise_sso' | PasskeyStrategy; + strategy?: OAuthStrategy | 'enterprise_sso' | PasskeyStrategy; /** * The full URL or path that the OAuth provider should redirect to after successful authorization on their part. */ diff --git a/packages/shared/src/types/signUpCommon.ts b/packages/shared/src/types/signUpCommon.ts index a40504a0c2a..5af4088d0fd 100644 --- a/packages/shared/src/types/signUpCommon.ts +++ b/packages/shared/src/types/signUpCommon.ts @@ -16,7 +16,6 @@ import type { GoogleOneTapStrategy, OAuthStrategy, PhoneCodeStrategy, - SamlStrategy, TicketStrategy, Web3Strategy, } from './strategies'; @@ -50,7 +49,7 @@ export type PrepareVerificationParams = oidcLoginHint?: string; } | { - strategy: SamlStrategy | EnterpriseSSOStrategy; + strategy: EnterpriseSSOStrategy; redirectUrl?: string; actionCompleteRedirectUrl?: string; }; @@ -76,7 +75,7 @@ export type SignUpVerifiableField = | Web3WalletIdentifier; // TODO: Does it make sense that the identification *field* holds a *strategy*? -export type SignUpIdentificationField = SignUpVerifiableField | OAuthStrategy | SamlStrategy | EnterpriseSSOStrategy; +export type SignUpIdentificationField = SignUpVerifiableField | OAuthStrategy | EnterpriseSSOStrategy; // TODO: Replace with discriminated union type export type SignUpCreateParams = Partial< @@ -86,7 +85,6 @@ export type SignUpCreateParams = Partial< externalAccountActionCompleteRedirectUrl: string; strategy: | OAuthStrategy - | SamlStrategy | EnterpriseSSOStrategy | TicketStrategy | GoogleOneTapStrategy diff --git a/packages/shared/src/types/strategies.ts b/packages/shared/src/types/strategies.ts index b8391619931..eb6dde71ed5 100644 --- a/packages/shared/src/types/strategies.ts +++ b/packages/shared/src/types/strategies.ts @@ -18,8 +18,3 @@ export type EnterpriseSSOStrategy = 'enterprise_sso'; export type OAuthStrategy = `oauth_${OAuthProvider}` | CustomOAuthStrategy; export type Web3Strategy = `web3_${Web3Provider}_signature`; - -/** - * @deprecated Use `EnterpriseSSOStrategy` instead. - */ -export type SamlStrategy = 'saml'; diff --git a/packages/ui/src/components/SignIn/SignInStart.tsx b/packages/ui/src/components/SignIn/SignInStart.tsx index 6048dc1d8c5..b9004e4e1d7 100644 --- a/packages/ui/src/components/SignIn/SignInStart.tsx +++ b/packages/ui/src/components/SignIn/SignInStart.tsx @@ -338,10 +338,7 @@ function SignInStartInternal(): JSX.Element { * For instances with Enterprise SSO enabled, perform sign in with password only when it is allowed for the identified user. */ const passwordField = fields.find(f => f.name === 'password')?.value; - if ( - !passwordField || - signInResource.supportedFirstFactors?.some(ff => ff.strategy === 'saml' || ff.strategy === 'enterprise_sso') - ) { + if (!passwordField || signInResource.supportedFirstFactors?.some(ff => ff.strategy === 'enterprise_sso')) { return signInResource; } return signInResource.attemptFirstFactor({ strategy: 'password', password: passwordField }); @@ -380,7 +377,7 @@ function SignInStartInternal(): JSX.Element { switch (res.status) { case 'needs_identifier': // Check if we need to initiate an enterprise sso flow - if (res.supportedFirstFactors?.some(ff => ff.strategy === 'saml' || ff.strategy === 'enterprise_sso')) { + if (res.supportedFirstFactors?.some(ff => ff.strategy === 'enterprise_sso')) { await authenticateWithEnterpriseSSO(); } break; diff --git a/packages/ui/src/components/SignIn/__tests__/SignInStart.test.tsx b/packages/ui/src/components/SignIn/__tests__/SignInStart.test.tsx index e5f4bf4e64f..27badf3fc20 100644 --- a/packages/ui/src/components/SignIn/__tests__/SignInStart.test.tsx +++ b/packages/ui/src/components/SignIn/__tests__/SignInStart.test.tsx @@ -312,30 +312,6 @@ describe('SignInStart', () => { }); }); - describe('SAML', () => { - it('initiates a SAML flow if saml is listed as a supported first factor', async () => { - const { wrapper, fixtures } = await createFixtures(f => { - f.withEmailAddress(); - }); - fixtures.signIn.create.mockReturnValueOnce( - Promise.resolve({ - status: 'needs_identifier', - supportedFirstFactors: [{ strategy: 'saml' }], - } as unknown as SignInResource), - ); - const { userEvent } = render(, { wrapper }); - await userEvent.type(screen.getByLabelText(/email address/i), 'hello@clerk.com'); - await userEvent.click(screen.getByText('Continue')); - expect(fixtures.signIn.create).toHaveBeenCalled(); - expect(fixtures.signIn.authenticateWithRedirect).toHaveBeenCalledWith({ - strategy: 'enterprise_sso', - redirectUrl: 'http://localhost:3000/#/sso-callback', - redirectUrlComplete: '/', - continueSignIn: true, - }); - }); - }); - describe('Enterprise SSO', () => { it('initiates a Enterprise SSO flow if enterprise_sso is listed as the only supported first factor', async () => { const { wrapper, fixtures } = await createFixtures(f => { diff --git a/packages/ui/src/components/SignIn/handleCombinedFlowTransfer.ts b/packages/ui/src/components/SignIn/handleCombinedFlowTransfer.ts index 7cf3c7280c6..5ed1926acb8 100644 --- a/packages/ui/src/components/SignIn/handleCombinedFlowTransfer.ts +++ b/packages/ui/src/components/SignIn/handleCombinedFlowTransfer.ts @@ -115,8 +115,8 @@ export function hasOptionalFields( identifierAttribute: 'emailAddress' | 'phoneNumber' | 'username', ) { const filteredFields = signUp.optionalFields.filter(field => { - // OAuth, Web3, and SAML fields, while optional, are not relevant once sign up has been initiated with an identifier. - if (field.startsWith('oauth_') || field.startsWith('web3_') || ['enterprise_sso', 'saml'].includes(field)) { + // OAuth, Web3, and Enterprise SSO fields, while optional, are not relevant once sign up has been initiated with an identifier. + if (field.startsWith('oauth_') || field.startsWith('web3_') || field === 'enterprise_sso') { return false; } diff --git a/packages/ui/src/components/SignUp/SignUpStart.tsx b/packages/ui/src/components/SignUp/SignUpStart.tsx index 20fa3d3475d..b7f1b73a6f4 100644 --- a/packages/ui/src/components/SignUp/SignUpStart.tsx +++ b/packages/ui/src/components/SignUp/SignUpStart.tsx @@ -188,7 +188,7 @@ function SignUpStartInternal(): JSX.Element { // Keep the card in loading state during SSO redirect to prevent UI flicker // This is necessary because there's a brief delay between initiating the SSO flow // and the actual redirect to the external Identity Provider - const isRedirectingToSSOProvider = signUp.missingFields.some(mf => mf === 'saml' || mf === 'enterprise_sso'); + const isRedirectingToSSOProvider = signUp.missingFields.some(mf => mf === 'enterprise_sso'); if (isRedirectingToSSOProvider) { return; } diff --git a/packages/ui/src/components/UserProfile/__tests__/AccountPage.test.tsx b/packages/ui/src/components/UserProfile/__tests__/AccountPage.test.tsx index 3af7b0b0f56..bdef0fbc4c9 100644 --- a/packages/ui/src/components/UserProfile/__tests__/AccountPage.test.tsx +++ b/packages/ui/src/components/UserProfile/__tests__/AccountPage.test.tsx @@ -124,7 +124,7 @@ describe('AccountPage', () => { }, verification: { status: 'verified', - strategy: 'saml', + strategy: 'enterprise_sso', verified_at_client: 'foo', attempts: 0, error: { @@ -190,7 +190,7 @@ describe('AccountPage', () => { }, verification: { status: 'verified', - strategy: 'saml', + strategy: 'enterprise_sso', verified_at_client: 'foo', attempts: 0, error: { @@ -250,7 +250,7 @@ describe('AccountPage', () => { }, verification: { status: 'verified', - strategy: 'saml', + strategy: 'enterprise_sso', verified_at_client: 'foo', attempts: 0, error: { diff --git a/packages/ui/src/components/UserProfile/__tests__/EnterpriseAccountsSection.test.tsx b/packages/ui/src/components/UserProfile/__tests__/EnterpriseAccountsSection.test.tsx index af526fe2041..9ee0ee40d0e 100644 --- a/packages/ui/src/components/UserProfile/__tests__/EnterpriseAccountsSection.test.tsx +++ b/packages/ui/src/components/UserProfile/__tests__/EnterpriseAccountsSection.test.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import { describe, expect, it } from 'vitest'; import { bindCreateFixtures } from '@/test/create-fixtures'; @@ -50,7 +49,7 @@ const withInactiveEnterpriseConnection = createFixtures.config(f => { }, verification: { status: 'verified', - strategy: 'saml', + strategy: 'enterprise_sso', verified_at_client: 'foo', attempts: 0, error: { @@ -201,7 +200,7 @@ const withSamlEnterpriseConnection = createFixtures.config(f => { }, verification: { status: 'verified', - strategy: 'saml', + strategy: 'enterprise_sso', verified_at_client: 'foo', attempts: 0, error: { diff --git a/packages/ui/src/components/UserProfile/__tests__/PasswordSection.test.tsx b/packages/ui/src/components/UserProfile/__tests__/PasswordSection.test.tsx index bfe8e96d82c..45a0b7f6afc 100644 --- a/packages/ui/src/components/UserProfile/__tests__/PasswordSection.test.tsx +++ b/packages/ui/src/components/UserProfile/__tests__/PasswordSection.test.tsx @@ -142,7 +142,7 @@ describe('PasswordSection', () => { }, verification: { status: 'verified', - strategy: 'saml', + strategy: 'enterprise_sso', verified_at_client: 'foo', attempts: 0, error: { @@ -215,7 +215,7 @@ describe('PasswordSection', () => { }, verification: { status: 'verified', - strategy: 'saml', + strategy: 'enterprise_sso', verified_at_client: 'foo', attempts: 0, error: { @@ -381,7 +381,7 @@ describe('PasswordSection', () => { }, verification: { status: 'verified', - strategy: 'saml', + strategy: 'enterprise_sso', verified_at_client: 'foo', attempts: 0, error: { @@ -455,7 +455,7 @@ describe('PasswordSection', () => { }, verification: { status: 'verified', - strategy: 'saml', + strategy: 'enterprise_sso', verified_at_client: 'foo', attempts: 0, error: { diff --git a/packages/ui/src/components/UserProfile/__tests__/SecurityPage.test.tsx b/packages/ui/src/components/UserProfile/__tests__/SecurityPage.test.tsx index d059b444ba3..45b62d02155 100644 --- a/packages/ui/src/components/UserProfile/__tests__/SecurityPage.test.tsx +++ b/packages/ui/src/components/UserProfile/__tests__/SecurityPage.test.tsx @@ -134,7 +134,7 @@ describe('SecurityPage', () => { }, verification: { status: 'verified', - strategy: 'saml', + strategy: 'enterprise_sso', verified_at_client: 'foo', attempts: 0, error: { @@ -206,7 +206,7 @@ describe('SecurityPage', () => { }, verification: { status: 'verified', - strategy: 'saml', + strategy: 'enterprise_sso', verified_at_client: 'foo', attempts: 0, error: { diff --git a/packages/ui/src/components/UserProfile/__tests__/UserProfileSection.test.tsx b/packages/ui/src/components/UserProfile/__tests__/UserProfileSection.test.tsx index d0f9cd41e66..66ea2b2e42e 100644 --- a/packages/ui/src/components/UserProfile/__tests__/UserProfileSection.test.tsx +++ b/packages/ui/src/components/UserProfile/__tests__/UserProfileSection.test.tsx @@ -95,7 +95,7 @@ describe('ProfileSection', () => { }, verification: { status: 'verified', - strategy: 'saml', + strategy: 'enterprise_sso', verified_at_client: 'foo', attempts: 0, error: { @@ -170,7 +170,7 @@ describe('ProfileSection', () => { }, verification: { status: 'verified', - strategy: 'saml', + strategy: 'enterprise_sso', verified_at_client: 'foo', attempts: 0, error: { From 933436a0ae6fcc9c808e4e4da336ceb75e591fda Mon Sep 17 00:00:00 2001 From: Laura Beatris <48022589+LauraBeatris@users.noreply.github.com> Date: Thu, 27 Nov 2025 19:25:58 -0300 Subject: [PATCH 2/2] Add changeset --- .changeset/salty-maps-fry.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/salty-maps-fry.md diff --git a/.changeset/salty-maps-fry.md b/.changeset/salty-maps-fry.md new file mode 100644 index 00000000000..17fcbef3683 --- /dev/null +++ b/.changeset/salty-maps-fry.md @@ -0,0 +1,7 @@ +--- +'@clerk/clerk-js': major +'@clerk/shared': major +'@clerk/ui': major +--- + +Remove deprecated `saml` strategy in favor of `enterprise_sso`