diff --git a/packages/clerk-js/src/core/__tests__/clerk.test.ts b/packages/clerk-js/src/core/__tests__/clerk.test.ts index ccf7ca9a091..03bc4081051 100644 --- a/packages/clerk-js/src/core/__tests__/clerk.test.ts +++ b/packages/clerk-js/src/core/__tests__/clerk.test.ts @@ -2015,6 +2015,66 @@ describe('Clerk singleton', () => { expect(mockNavigate.mock.calls[0][0]).toBe('/sign-in#/reset-password'); }); }); + + it('reads redirect_url from URL search params and uses it as the redirect destination', async () => { + // Set window.location to include redirect_url in search params + const customRedirectUrl = '/custom-redirect-from-url'; + Object.defineProperty(global.window, 'location', { + value: { + ...mockWindowLocation, + search: `?redirect_url=${encodeURIComponent(customRedirectUrl)}`, + }, + }); + + mockEnvironmentFetch.mockReturnValue( + Promise.resolve({ + authConfig: {}, + userSettings: mockUserSettings, + displayConfig: mockDisplayConfig, + isSingleSession: () => false, + isProduction: () => false, + isDevelopmentOrStaging: () => true, + onWindowLocationHost: () => false, + }), + ); + + mockClientFetch.mockReturnValue( + Promise.resolve({ + signedInSessions: [], + signIn: new SignIn({ + status: 'complete', + first_factor_verification: { + status: 'verified', + strategy: 'oauth_google', + external_verification_redirect_url: null, + error: null, + }, + second_factor_verification: null, + identifier: 'test@example.com', + user_data: null, + created_session_id: 'sess_123', + } as any as SignInJSON), + signUp: new SignUp(null), + }), + ); + + const mockSetActive = vi.fn(async ({ navigate }) => { + // Simulate the navigate callback being called + await navigate({ session: { currentTask: null } }); + }); + + const sut = new Clerk(productionPublishableKey); + await sut.load(mockedLoadOptions); + sut.setActive = mockSetActive; + + await sut.handleRedirectCallback(); + + await waitFor(() => { + expect(mockSetActive).toHaveBeenCalled(); + // The redirect should include the custom redirect URL from URL search params + expect(mockNavigate.mock.calls[0][0]).toContain(customRedirectUrl); + }); + }); }); describe('.handleEmailLinkVerification()', () => { diff --git a/packages/clerk-js/src/core/clerk.ts b/packages/clerk-js/src/core/clerk.ts index 081f50af569..98d4e5ba365 100644 --- a/packages/clerk-js/src/core/clerk.ts +++ b/packages/clerk-js/src/core/clerk.ts @@ -2084,7 +2084,7 @@ export class Clerk implements ClerkInterface { buildURL({ base: displayConfig.signInUrl, hashPath: '/reset-password' }, { stringify: true }), ); - const redirectUrls = new RedirectUrls(this.#options, params); + const redirectUrls = new RedirectUrls(this.#options, params, new URLSearchParams(window.location.search)); const navigateToContinueSignUp = makeNavigate( params.continueSignUpUrl ||