Skip to content

Commit 7ffc99b

Browse files
authoredJan 16, 2025··
chore(elements,types): Support enterprise_sso strategy (#4916)
1 parent 93e30ce commit 7ffc99b

File tree

11 files changed

+95
-24
lines changed

11 files changed

+95
-24
lines changed
 

‎.changeset/quiet-dingos-laugh.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@clerk/elements': patch
3+
'@clerk/types': patch
4+
---
5+
6+
Support `enterprise_sso` strategy (SAML, OIDC, EASIE) on custom flows with `@clerk/elements`

‎packages/elements/src/internals/machines/sign-in/router.machine.ts

+16
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,22 @@ export const SignInRouterMachine = setup({
220220
},
221221
})),
222222
},
223+
'AUTHENTICATE.ENTERPRISE_SSO': {
224+
actions: sendTo(ThirdPartyMachineId, ({ context }) => ({
225+
type: 'REDIRECT',
226+
params: {
227+
strategy: 'enterprise_sso',
228+
identifier: context.formRef.getSnapshot().context.fields.get('identifier')?.value,
229+
redirectUrl: `${
230+
context.router?.mode === ROUTING.virtual
231+
? context.clerk.__unstable__environment?.displayConfig.signInUrl
232+
: context.router?.basePath
233+
}${SSO_CALLBACK_PATH_ROUTE}`,
234+
redirectUrlComplete:
235+
context.router?.searchParams().get('redirect_url') || context.clerk.buildAfterSignInUrl(),
236+
},
237+
})),
238+
},
223239
'FORM.ATTACH': {
224240
description: 'Attach/re-attach the form to the router.',
225241
actions: enqueueActions(({ enqueue, event }) => {

‎packages/elements/src/internals/machines/sign-up/router.machine.ts

+16
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,22 @@ export const SignUpRouterMachine = setup({
220220
},
221221
})),
222222
},
223+
'AUTHENTICATE.ENTERPRISE_SSO': {
224+
actions: sendTo(ThirdPartyMachineId, ({ context }) => ({
225+
type: 'REDIRECT',
226+
params: {
227+
strategy: 'enterprise_sso',
228+
emailAddress: context.formRef.getSnapshot().context.fields.get('emailAddress')?.value,
229+
redirectUrl: `${
230+
context.router?.mode === ROUTING.virtual
231+
? context.clerk.__unstable__environment?.displayConfig.signUpUrl
232+
: context.router?.basePath
233+
}${SSO_CALLBACK_PATH_ROUTE}`,
234+
redirectUrlComplete:
235+
context.router?.searchParams().get('redirect_url') || context.clerk.buildAfterSignUpUrl(),
236+
},
237+
})),
238+
},
223239
'AUTHENTICATE.WEB3': {
224240
actions: sendTo('start', ({ event }) => event),
225241
},

‎packages/elements/src/internals/machines/sign-up/start.types.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { ClerkAPIResponseError } from '@clerk/shared/error';
2-
import type { OAuthStrategy, SamlStrategy, Web3Strategy } from '@clerk/types';
2+
import type { EnterpriseSSOStrategy, OAuthStrategy, SamlStrategy, Web3Strategy } from '@clerk/types';
33
import type { ActorRefFrom, ErrorActorEvent } from 'xstate';
44

55
import type { FormMachine } from '~/internals/machines/form';
@@ -18,12 +18,17 @@ export type SignUpStartSubmitEvent = { type: 'SUBMIT'; action: 'submit' };
1818
// TODO: Consolidate with SignInStartMachine
1919
export type SignUpStartRedirectOauthEvent = { type: 'AUTHENTICATE.OAUTH'; strategy: OAuthStrategy };
2020
export type SignUpStartRedirectSamlEvent = { type: 'AUTHENTICATE.SAML'; strategy?: SamlStrategy };
21+
export type SignUpStartRedirectEnterpriseSSOEvent = {
22+
type: 'AUTHENTICATE.ENTERPRISE_SSO';
23+
strategy?: EnterpriseSSOStrategy;
24+
};
2125
export type SignUpStartRedirectWeb3Event = { type: 'AUTHENTICATE.WEB3'; strategy: Web3Strategy };
2226

2327
export type SignUpStartRedirectEvent =
2428
| SignUpStartRedirectOauthEvent
2529
| SignUpStartRedirectSamlEvent
26-
| SignUpStartRedirectWeb3Event;
30+
| SignUpStartRedirectWeb3Event
31+
| SignUpStartRedirectEnterpriseSSOEvent;
2732

2833
export type SignUpStartEvents = ErrorActorEvent | SignUpStartSubmitEvent | SignUpStartRedirectEvent | SetFormEvent;
2934

‎packages/elements/src/internals/machines/types/router.types.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { ClerkRouter } from '@clerk/shared/router';
22
import type {
33
ClerkResource,
4+
EnterpriseSSOStrategy,
45
LoadedClerk,
56
OAuthStrategy,
67
SamlStrategy,
@@ -46,13 +47,18 @@ export type BaseRouterLoadingEvent<TSteps extends BaseRouterLoadingStep> = (
4647

4748
export type BaseRouterRedirectOauthEvent = { type: 'AUTHENTICATE.OAUTH'; strategy: OAuthStrategy };
4849
export type BaseRouterRedirectSamlEvent = { type: 'AUTHENTICATE.SAML'; strategy?: SamlStrategy };
50+
export type BaseRouterRedirectEnterpriseSSOEvent = {
51+
type: 'AUTHENTICATE.ENTERPRISE_SSO';
52+
strategy?: EnterpriseSSOStrategy;
53+
};
4954
export type BaseRouterRedirectWeb3Event = { type: 'AUTHENTICATE.WEB3'; strategy: Web3Strategy };
5055
export type BaseRouterSetClerkEvent = { type: 'CLERK.SET'; clerk: LoadedClerk };
5156

5257
export type BaseRouterRedirectEvent =
5358
| BaseRouterRedirectOauthEvent
5459
| BaseRouterRedirectSamlEvent
55-
| BaseRouterRedirectWeb3Event;
60+
| BaseRouterRedirectWeb3Event
61+
| BaseRouterRedirectEnterpriseSSOEvent;
5662

5763
// ---------------------------------- Input ---------------------------------- //
5864

‎packages/elements/src/react/common/connections.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { OAuthProvider, SamlStrategy, Web3Provider } from '@clerk/types';
1+
import type { EnterpriseSSOStrategy, OAuthProvider, SamlStrategy, Web3Provider } from '@clerk/types';
22
import { Slot } from '@radix-ui/react-slot';
33
import { createContext, useContext } from 'react';
44

@@ -29,7 +29,7 @@ export const useConnectionContext = () => {
2929

3030
export interface ConnectionProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
3131
asChild?: boolean;
32-
name: OAuthProvider | Web3Provider | SamlStrategy;
32+
name: OAuthProvider | Web3Provider | SamlStrategy | EnterpriseSSOStrategy;
3333
}
3434

3535
/**

‎packages/elements/src/react/common/loading.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useClerk } from '@clerk/shared/react';
22
import { eventComponentMounted } from '@clerk/shared/telemetry';
3-
import type { OAuthProvider, SamlStrategy, Web3Provider } from '@clerk/types';
3+
import type { EnterpriseSSOStrategy, OAuthProvider, SamlStrategy, Web3Provider } from '@clerk/types';
44
import { useSelector } from '@xstate/react';
55
import * as React from 'react';
66

@@ -15,7 +15,7 @@ import type { TSignUpStep } from '~/react/sign-up/step';
1515
import { SIGN_UP_STEPS } from '~/react/sign-up/step';
1616
import { isProviderStrategyScope, mapScopeToStrategy } from '~/react/utils/map-scope-to-strategy';
1717

18-
type Strategy = OAuthProvider | SamlStrategy | Web3Provider;
18+
type Strategy = OAuthProvider | SamlStrategy | EnterpriseSSOStrategy | Web3Provider;
1919
type LoadingScope<T extends TSignInStep | TSignUpStep> =
2020
| 'global'
2121
| `step:${T}`

‎packages/elements/src/react/hooks/use-third-party-provider.hook.ts

+25-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useClerk } from '@clerk/shared/react';
2-
import type { OAuthProvider, SamlStrategy, Web3Provider } from '@clerk/types';
2+
import type { EnterpriseSSOStrategy, OAuthProvider, SamlStrategy, Web3Provider } from '@clerk/types';
33
import type React from 'react';
44
import { useCallback } from 'react';
55
import type { ActorRef } from 'xstate';
@@ -11,21 +11,28 @@ import type { UseThirdPartyProviderReturn } from '~/react/common/connections';
1111
import {
1212
getEnabledThirdPartyProviders,
1313
isAuthenticatableOauthStrategy,
14+
isEnterpriseSSOStrategy,
1415
isSamlStrategy,
1516
isWeb3Strategy,
1617
providerToDisplayData,
1718
} from '~/utils/third-party-strategies';
1819

19-
const useIsProviderEnabled = (provider: OAuthProvider | Web3Provider | SamlStrategy): boolean | null => {
20+
const useIsProviderEnabled = (
21+
provider: OAuthProvider | Web3Provider | SamlStrategy | EnterpriseSSOStrategy,
22+
): boolean | null => {
2023
const clerk = useClerk();
2124

2225
// null indicates we don't know for sure
2326
if (!clerk.loaded) {
2427
return null;
2528
}
2629

27-
if (provider === 'saml') {
28-
return clerk.__unstable__environment?.userSettings.saml.enabled ?? false;
30+
if (provider === 'saml' || provider === 'enterprise_sso') {
31+
return (
32+
clerk.__unstable__environment?.userSettings.saml.enabled ??
33+
clerk.__unstable__environment?.userSettings.enterpriseSSO.enabled ??
34+
false
35+
);
2936
}
3037

3138
const data = getEnabledThirdPartyProviders(clerk.__unstable__environment);
@@ -40,16 +47,18 @@ export const useThirdPartyProvider = <
4047
TActor extends ActorRef<any, SignInRouterEvents> | ActorRef<any, SignUpRouterEvents>,
4148
>(
4249
ref: TActor,
43-
provider: OAuthProvider | Web3Provider | SamlStrategy,
50+
provider: OAuthProvider | Web3Provider | SamlStrategy | EnterpriseSSOStrategy,
4451
): UseThirdPartyProviderReturn => {
4552
const isProviderEnabled = useIsProviderEnabled(provider);
4653
const isSaml = isSamlStrategy(provider);
47-
const details = isSaml
48-
? {
49-
name: 'SAML',
50-
strategy: 'saml' as SamlStrategy,
51-
}
52-
: providerToDisplayData[provider];
54+
const isEnterpriseSSO = isEnterpriseSSOStrategy(provider);
55+
const details =
56+
isEnterpriseSSO || isSaml
57+
? {
58+
name: 'SSO',
59+
strategy: provider,
60+
}
61+
: providerToDisplayData[provider];
5362

5463
const authenticate = useCallback(
5564
(event: React.MouseEvent<Element>) => {
@@ -63,6 +72,10 @@ export const useThirdPartyProvider = <
6372
return ref.send({ type: 'AUTHENTICATE.SAML' });
6473
}
6574

75+
if (isEnterpriseSSO) {
76+
return ref.send({ type: 'AUTHENTICATE.ENTERPRISE_SSO' });
77+
}
78+
6679
if (provider === 'metamask') {
6780
return ref.send({ type: 'AUTHENTICATE.WEB3', strategy: 'web3_metamask_signature' });
6881
}
@@ -77,7 +90,7 @@ export const useThirdPartyProvider = <
7790

7891
return ref.send({ type: 'AUTHENTICATE.OAUTH', strategy: `oauth_${provider}` });
7992
},
80-
[provider, isProviderEnabled, isSaml, ref],
93+
[provider, isProviderEnabled, isSaml, isEnterpriseSSO, ref],
8194
);
8295

8396
if (isProviderEnabled === false) {

‎packages/elements/src/react/utils/map-scope-to-strategy.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import type { OAuthProvider, SamlStrategy, SignInStrategy, Web3Provider } from '@clerk/types';
1+
import type { EnterpriseSSOStrategy, OAuthProvider, SamlStrategy, SignInStrategy, Web3Provider } from '@clerk/types';
22

3-
type Strategy = OAuthProvider | SamlStrategy | Web3Provider;
3+
type Strategy = OAuthProvider | SamlStrategy | EnterpriseSSOStrategy | Web3Provider;
44

55
export function isProviderStrategyScope(value: string): value is Strategy {
66
return value.startsWith('provider:');
@@ -21,6 +21,10 @@ export function mapScopeToStrategy<T extends `provider:${Strategy}`>(scope: T):
2121
return 'saml';
2222
}
2323

24+
if (scope === 'provider:enterprise_sso') {
25+
return 'enterprise_sso';
26+
}
27+
2428
const scopeWithoutPrefix = scope.replace('provider:', '') as OAuthProvider;
2529

2630
return `oauth_${scopeWithoutPrefix}`;

‎packages/elements/src/utils/third-party-strategies.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { iconImageUrl } from '@clerk/shared/constants';
44
import { OAUTH_PROVIDERS } from '@clerk/shared/oauth';
55
import { WEB3_PROVIDERS } from '@clerk/shared/web3';
66
import type {
7+
EnterpriseSSOStrategy,
78
EnvironmentResource,
89
OAuthProvider,
910
OAuthStrategy,
@@ -21,7 +22,7 @@ export type ThirdPartyStrategy =
2122
name: string;
2223
}
2324
| {
24-
strategy: SamlStrategy;
25+
strategy: SamlStrategy | EnterpriseSSOStrategy;
2526
iconUrl?: never;
2627
name: string;
2728
};
@@ -33,7 +34,7 @@ export type ThirdPartyProvider =
3334
name: string;
3435
}
3536
| {
36-
strategy: SamlStrategy;
37+
strategy: SamlStrategy | EnterpriseSSOStrategy;
3738
iconUrl?: never;
3839
name: string;
3940
};
@@ -72,6 +73,10 @@ export function isSamlStrategy(strategy: any): strategy is SamlStrategy {
7273
return strategy === 'saml';
7374
}
7475

76+
export function isEnterpriseSSOStrategy(strategy: any): strategy is EnterpriseSSOStrategy {
77+
return strategy === 'enterprise_sso';
78+
}
79+
7580
export function isWeb3Strategy(
7681
strategy: any,
7782
available: EnabledThirdPartyProviders['web3Strategies'],

‎packages/types/src/signUp.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ export type PrepareVerificationParams =
130130
oidcLoginHint?: string;
131131
}
132132
| {
133-
strategy: SamlStrategy;
133+
strategy: SamlStrategy | EnterpriseSSOStrategy;
134134
redirectUrl?: string;
135135
actionCompleteRedirectUrl?: string;
136136
};

0 commit comments

Comments
 (0)
Please sign in to comment.