diff --git a/.changeset/hot-cats-smell.md b/.changeset/hot-cats-smell.md new file mode 100644 index 00000000000..ec9cbcbfa97 --- /dev/null +++ b/.changeset/hot-cats-smell.md @@ -0,0 +1,5 @@ +--- +'@clerk/clerk-js': patch +--- + +Fix issue where the SSO callback URL was incorrectly generated when using the transfer flow within a modal. diff --git a/packages/clerk-js/src/ui/common/__tests__/redirects.test.ts b/packages/clerk-js/src/ui/common/__tests__/redirects.test.ts index 10a23fdf420..11c706e8c65 100644 --- a/packages/clerk-js/src/ui/common/__tests__/redirects.test.ts +++ b/packages/clerk-js/src/ui/common/__tests__/redirects.test.ts @@ -209,8 +209,16 @@ describe('buildSSOCallbackURL(ctx, baseUrl)', () => { ).toBe('http://test.host/#/sso-callback?redirect_url=%2Ffoo'); // Custom SSO callback URL in the context - expect(buildSSOCallbackURL({ ssoCallbackUrl: 'http://test.host/ctx-sso-callback' })).toBe( + expect(buildSSOCallbackURL({ isCombinedFlow: true, ssoCallbackUrl: 'http://test.host/ctx-sso-callback' })).toBe( 'http://test.host/ctx-sso-callback', ); + // Does not use SSO callback URL from context when routing is virtual + expect( + buildSSOCallbackURL({ + isCombinedFlow: true, + ssoCallbackUrl: 'http://test.host/ctx-sso-callback', + routing: 'virtual', + }), + ).toBe('http://localhost/#/sso-callback'); }); }); diff --git a/packages/clerk-js/src/ui/common/redirects.ts b/packages/clerk-js/src/ui/common/redirects.ts index cf01cce2bb7..59636a9bb64 100644 --- a/packages/clerk-js/src/ui/common/redirects.ts +++ b/packages/clerk-js/src/ui/common/redirects.ts @@ -54,12 +54,13 @@ export function buildSSOCallbackURL( ctx: Partial, baseUrl: string | undefined = '', ): string { + const { routing, authQueryString, path } = ctx; // If the context contains an SSO callback URL, use it instead of building a new one, as it likely contains the - // combined flow path. - if ('ssoCallbackUrl' in ctx && ctx.ssoCallbackUrl) { + // combined flow path. However, if the routing is virtual, the callback URL from context will not have factored in + // baseUrl, so we fallback to buildRedirectUrl instead. + if (ctx.ssoCallbackUrl && ctx.isCombinedFlow && routing !== 'virtual') { return ctx.ssoCallbackUrl; } - const { routing, authQueryString, path } = ctx; return buildRedirectUrl({ routing, baseUrl,