diff --git a/.changeset/wise-lions-prompt.md b/.changeset/wise-lions-prompt.md new file mode 100644 index 00000000000..279dc2f2316 --- /dev/null +++ b/.changeset/wise-lions-prompt.md @@ -0,0 +1,5 @@ +--- +'@clerk/ui': patch +--- + +Fix configured OIDC prompts being ignored by sign-up continuations, including enterprise SSO after email-link verification or direct combined-flow transfer and OAuth sign-ups embedded in ``. diff --git a/packages/ui/src/common/EmailLinkVerify.tsx b/packages/ui/src/common/EmailLinkVerify.tsx index 9358869871f..6c3931eccb3 100644 --- a/packages/ui/src/common/EmailLinkVerify.tsx +++ b/packages/ui/src/common/EmailLinkVerify.tsx @@ -15,6 +15,7 @@ export type EmailLinkVerifyProps = { redirectUrlComplete?: string; redirectUrl?: string; ssoCallbackUrl?: string; + oidcPrompt?: string; verifyEmailPath?: string; verifyPhonePath?: string; continuePath?: string; @@ -22,7 +23,15 @@ export type EmailLinkVerifyProps = { }; export const EmailLinkVerify = (props: EmailLinkVerifyProps) => { - const { redirectUrl, redirectUrlComplete, ssoCallbackUrl, verifyEmailPath, verifyPhonePath, continuePath } = props; + const { + redirectUrl, + redirectUrlComplete, + ssoCallbackUrl, + oidcPrompt, + verifyEmailPath, + verifyPhonePath, + continuePath, + } = props; const { handleEmailLinkVerification } = useClerk(); const { navigate } = useRouter(); const signUp = useCoreSignUp(); @@ -53,6 +62,7 @@ export const EmailLinkVerify = (props: EmailLinkVerifyProps) => { navigate, redirectUrl: ssoCallbackUrl, redirectUrlComplete: redirectUrlComplete || '/', + oidcPrompt, }); } catch (err: any) { if ( diff --git a/packages/ui/src/components/SignIn/SignInStart.tsx b/packages/ui/src/components/SignIn/SignInStart.tsx index 658643d83bb..a95040b8465 100644 --- a/packages/ui/src/components/SignIn/SignInStart.tsx +++ b/packages/ui/src/components/SignIn/SignInStart.tsx @@ -535,6 +535,7 @@ function SignInStartInternal(): JSX.Element { signUpMode: userSettings.signUp.mode, redirectUrl, redirectUrlComplete, + oidcPrompt: ctx.oidcPrompt, navigateOnSetActive, passwordEnabled: userSettings.attributes.password?.required ?? false, alternativePhoneCodeChannel: diff --git a/packages/ui/src/components/SignIn/__tests__/handleCombinedFlowTransfer.test.ts b/packages/ui/src/components/SignIn/__tests__/handleCombinedFlowTransfer.test.ts index c14adc916f7..9d8c13f8a35 100644 --- a/packages/ui/src/components/SignIn/__tests__/handleCombinedFlowTransfer.test.ts +++ b/packages/ui/src/components/SignIn/__tests__/handleCombinedFlowTransfer.test.ts @@ -22,7 +22,7 @@ describe('handleCombinedFlowTransfer', () => { vi.resetAllMocks(); }); - it('should call completeSignUpFlow', async () => { + it('should pass the OIDC prompt to completeSignUpFlow', async () => { const mockClerk = { client: { signUp: { @@ -42,9 +42,14 @@ describe('handleCombinedFlowTransfer', () => { afterSignUpUrl: 'https://test.com', passwordEnabled: false, navigateOnSetActive: vi.fn(), + oidcPrompt: 'select_account', }); - expect(mockCompleteSignUpFlow).toHaveBeenCalled(); + expect(mockCompleteSignUpFlow).toHaveBeenCalledWith( + expect.objectContaining({ + oidcPrompt: 'select_account', + }), + ); }); it('should pass unsafeMetadata to signUp.create', async () => { diff --git a/packages/ui/src/components/SignIn/handleCombinedFlowTransfer.ts b/packages/ui/src/components/SignIn/handleCombinedFlowTransfer.ts index caa2a834a9d..ca4569a5cd0 100644 --- a/packages/ui/src/components/SignIn/handleCombinedFlowTransfer.ts +++ b/packages/ui/src/components/SignIn/handleCombinedFlowTransfer.ts @@ -23,6 +23,7 @@ type HandleCombinedFlowTransferProps = { handleError: (err: any) => void; redirectUrl?: string; redirectUrlComplete?: string; + oidcPrompt?: string; passwordEnabled: boolean; alternativePhoneCodeChannel?: PhoneCodeChannel | null; navigateOnSetActive: (opts: { @@ -48,6 +49,7 @@ export function handleCombinedFlowTransfer({ handleError, redirectUrl, redirectUrlComplete, + oidcPrompt, passwordEnabled, navigateOnSetActive, alternativePhoneCodeChannel, @@ -111,6 +113,7 @@ export function handleCombinedFlowTransfer({ navigate, redirectUrl, redirectUrlComplete, + oidcPrompt, }); }) .catch(err => handleError(err)); diff --git a/packages/ui/src/components/SignIn/index.tsx b/packages/ui/src/components/SignIn/index.tsx index 46b784ceede..01c6a532497 100644 --- a/packages/ui/src/components/SignIn/index.tsx +++ b/packages/ui/src/components/SignIn/index.tsx @@ -118,6 +118,7 @@ function SignInRoutes(): JSX.Element { { await waitFor(() => expect(fixtures.clerk.handleEmailLinkVerification).toHaveBeenCalled()); screen.getByText(/success/i); }); + + it('preserves the OIDC prompt when continuing through enterprise SSO', async () => { + const { wrapper, fixtures } = await createFixtures(f => { + f.withEmailAddress({ required: true }); + }); + fixtures.signUp.status = 'missing_requirements'; + fixtures.signUp.missingFields = ['enterprise_sso']; + + render( + , + { wrapper }, + ); + + await waitFor(() => expect(fixtures.signUp.authenticateWithRedirect).toHaveBeenCalled(), { timeout: 3_000 }); + expect(fixtures.signUp.authenticateWithRedirect).toHaveBeenCalledWith({ + strategy: 'enterprise_sso', + redirectUrl: 'https://example.com/sso-callback', + redirectUrlComplete: 'https://example.com/complete', + continueSignUp: true, + oidcPrompt: 'select_account', + }); + }); }); describe('Error messages', () => { diff --git a/packages/ui/src/components/SignUp/index.tsx b/packages/ui/src/components/SignUp/index.tsx index ff68b5e1fe7..f5b94663dbe 100644 --- a/packages/ui/src/components/SignUp/index.tsx +++ b/packages/ui/src/components/SignUp/index.tsx @@ -72,6 +72,7 @@ function SignUpRoutes(): JSX.Element {