From 1383bf1a99678cad26c0321cc3dc5faf4be711e7 Mon Sep 17 00:00:00 2001 From: Iago Dahlem Lorensini Date: Wed, 20 Aug 2025 03:09:07 -0300 Subject: [PATCH 1/7] Pass query params to buildAfterSignInUrl --- .changeset/mean-pumas-cut.md | 5 +++++ packages/clerk-js/src/ui/components/SessionTasks/index.tsx | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 .changeset/mean-pumas-cut.md diff --git a/.changeset/mean-pumas-cut.md b/.changeset/mean-pumas-cut.md new file mode 100644 index 00000000000..8fbe35c2b50 --- /dev/null +++ b/.changeset/mean-pumas-cut.md @@ -0,0 +1,5 @@ +--- +'@clerk/clerk-js': patch +--- + +Fix SessionTasks redirectUrlComplete diff --git a/packages/clerk-js/src/ui/components/SessionTasks/index.tsx b/packages/clerk-js/src/ui/components/SessionTasks/index.tsx index 3baba7afd2e..e70691119ee 100644 --- a/packages/clerk-js/src/ui/components/SessionTasks/index.tsx +++ b/packages/clerk-js/src/ui/components/SessionTasks/index.tsx @@ -71,9 +71,14 @@ export const SessionTasks = withCardStateProvider(() => { const signInContext = useContext(SignInContext); const signUpContext = useContext(SignUpContext); const currentTaskContainer = useRef(null); + const { queryParams } = useRouter(); const redirectUrlComplete = - signInContext?.afterSignInUrl ?? signUpContext?.afterSignUpUrl ?? clerk?.buildAfterSignInUrl(); + signInContext?.afterSignInUrl ?? + signUpContext?.afterSignUpUrl ?? + clerk?.buildAfterSignInUrl({ + params: new URLSearchParams(queryParams), + }); // If there are no pending tasks, navigate away from the tasks flow. // This handles cases where a user with an active session returns to the tasks URL, From 1dc8080e6a47d541a5739698ed12c18bf80a5262 Mon Sep 17 00:00:00 2001 From: Laura Beatris <48022589+LauraBeatris@users.noreply.github.com> Date: Wed, 20 Aug 2025 09:56:42 -0300 Subject: [PATCH 2/7] Pass `redirectUrlComplete` as a route prop --- .../src/ui/components/SessionTasks/index.tsx | 19 ++++++------------- .../src/ui/components/SignIn/index.tsx | 4 ++-- .../src/ui/components/SignUp/index.tsx | 2 +- 3 files changed, 9 insertions(+), 16 deletions(-) diff --git a/packages/clerk-js/src/ui/components/SessionTasks/index.tsx b/packages/clerk-js/src/ui/components/SessionTasks/index.tsx index e70691119ee..95d7ae017eb 100644 --- a/packages/clerk-js/src/ui/components/SessionTasks/index.tsx +++ b/packages/clerk-js/src/ui/components/SessionTasks/index.tsx @@ -1,14 +1,13 @@ import { useClerk } from '@clerk/shared/react'; import { eventComponentMounted } from '@clerk/shared/telemetry'; import type { SessionResource } from '@clerk/types'; -import { useContext, useEffect, useRef } from 'react'; +import { useEffect, useRef } from 'react'; import { Card } from '@/ui/elements/Card'; import { withCardStateProvider } from '@/ui/elements/contexts'; import { LoadingCardContainer } from '@/ui/elements/LoadingCard'; import { INTERNAL_SESSION_TASK_ROUTE_BY_KEY } from '../../../core/sessionTasks'; -import { SignInContext, SignUpContext } from '../../../ui/contexts'; import { SessionTasksContext, TaskChooseOrganizationContext, @@ -62,23 +61,17 @@ function SessionTasksRoutes(): JSX.Element { ); } +type SessionTasksProps = { + redirectUrlComplete: string; +}; + /** * @internal */ -export const SessionTasks = withCardStateProvider(() => { +export const SessionTasks = withCardStateProvider(({ redirectUrlComplete }: SessionTasksProps) => { const clerk = useClerk(); const { navigate } = useRouter(); - const signInContext = useContext(SignInContext); - const signUpContext = useContext(SignUpContext); const currentTaskContainer = useRef(null); - const { queryParams } = useRouter(); - - const redirectUrlComplete = - signInContext?.afterSignInUrl ?? - signUpContext?.afterSignUpUrl ?? - clerk?.buildAfterSignInUrl({ - params: new URLSearchParams(queryParams), - }); // If there are no pending tasks, navigate away from the tasks flow. // This handles cases where a user with an active session returns to the tasks URL, diff --git a/packages/clerk-js/src/ui/components/SignIn/index.tsx b/packages/clerk-js/src/ui/components/SignIn/index.tsx index cf451cf5ab3..29ec373b367 100644 --- a/packages/clerk-js/src/ui/components/SignIn/index.tsx +++ b/packages/clerk-js/src/ui/components/SignIn/index.tsx @@ -136,7 +136,7 @@ function SignInRoutes(): JSX.Element { - + @@ -144,7 +144,7 @@ function SignInRoutes(): JSX.Element { )} - + diff --git a/packages/clerk-js/src/ui/components/SignUp/index.tsx b/packages/clerk-js/src/ui/components/SignUp/index.tsx index 6cfe5963605..a46993739fd 100644 --- a/packages/clerk-js/src/ui/components/SignUp/index.tsx +++ b/packages/clerk-js/src/ui/components/SignUp/index.tsx @@ -80,7 +80,7 @@ function SignUpRoutes(): JSX.Element { - + From 02bcaf9f1a63f0cf398801296cbfb009d77593f4 Mon Sep 17 00:00:00 2001 From: Laura Beatris <48022589+LauraBeatris@users.noreply.github.com> Date: Wed, 20 Aug 2025 09:59:23 -0300 Subject: [PATCH 3/7] Update changeset --- .changeset/mean-pumas-cut.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/mean-pumas-cut.md b/.changeset/mean-pumas-cut.md index 8fbe35c2b50..0bcb91d4890 100644 --- a/.changeset/mean-pumas-cut.md +++ b/.changeset/mean-pumas-cut.md @@ -2,4 +2,4 @@ '@clerk/clerk-js': patch --- -Fix SessionTasks redirectUrlComplete +Fix incorrect redirect when completing session tasks within `SignIn` and `SignUp` components From ceef8824abadf2f83f6cabf51e6fa6f155092630 Mon Sep 17 00:00:00 2001 From: Laura Beatris <48022589+LauraBeatris@users.noreply.github.com> Date: Wed, 20 Aug 2025 10:52:04 -0300 Subject: [PATCH 4/7] Adjust E2E tests --- integration/tests/session-tasks-sign-in.test.ts | 2 +- integration/tests/session-tasks-sign-up.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/integration/tests/session-tasks-sign-in.test.ts b/integration/tests/session-tasks-sign-in.test.ts index f91a3ec3f85..503d11dcb4b 100644 --- a/integration/tests/session-tasks-sign-in.test.ts +++ b/integration/tests/session-tasks-sign-in.test.ts @@ -56,7 +56,7 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withSessionTasks] })( await u.po.expect.toHaveResolvedTask(); // Navigates to after sign-in - await u.page.waitForAppUrl('/'); + await u.page.waitForAppUrl('/page-protected'); }); test('with sso, navigate to task on after sign-in', async ({ page, context }) => { diff --git a/integration/tests/session-tasks-sign-up.test.ts b/integration/tests/session-tasks-sign-up.test.ts index ca262f281e5..0a7c24c4eea 100644 --- a/integration/tests/session-tasks-sign-up.test.ts +++ b/integration/tests/session-tasks-sign-up.test.ts @@ -73,7 +73,7 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withSessionTasks] })( await u.po.expect.toHaveResolvedTask(); // Navigates to after sign-up - await u.page.waitForAppUrl('/'); + await u.page.waitForAppUrl('/page-protected'); }); test('with sso, navigate to task on after sign-up', async ({ page, context }) => { From a390785e6e2498d331e18cce30121ae381a418ae Mon Sep 17 00:00:00 2001 From: Laura Beatris <48022589+LauraBeatris@users.noreply.github.com> Date: Wed, 20 Aug 2025 12:11:04 -0300 Subject: [PATCH 5/7] Pass `afterSignInUrl` when building tasks URL from `Clerk` --- packages/clerk-js/src/core/clerk.ts | 15 ++++++++++----- packages/types/src/clerk.ts | 2 ++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/clerk-js/src/core/clerk.ts b/packages/clerk-js/src/core/clerk.ts index ac78f078b6b..1f06f3342fb 100644 --- a/packages/clerk-js/src/core/clerk.ts +++ b/packages/clerk-js/src/core/clerk.ts @@ -75,6 +75,7 @@ import type { SignUpRedirectOptions, SignUpResource, TaskChooseOrganizationProps, + TasksRedirectOptions, UnsubscribeCallback, UserButtonProps, UserProfileProps, @@ -1595,7 +1596,7 @@ export class Clerk implements ClerkInterface { return this.buildUrlWithAuth(this.environment.displayConfig.organizationProfileUrl); } - public buildTasksUrl(): string { + public buildTasksUrl(options?: TasksRedirectOptions): string { const currentTask = this.session?.currentTask; if (!currentTask) { return ''; @@ -1608,7 +1609,7 @@ export class Clerk implements ClerkInterface { return buildURL( { - base: this.buildSignInUrl(), + base: this.buildSignInUrl(options), hashPath: getTaskEndpoint(currentTask), }, { @@ -1707,9 +1708,9 @@ export class Clerk implements ClerkInterface { return; }; - public redirectToTasks = async (): Promise => { + public redirectToTasks = async (options?: TasksRedirectOptions): Promise => { if (inBrowser()) { - return this.navigate(this.buildTasksUrl()); + return this.navigate(this.buildTasksUrl(options)); } return; }; @@ -2044,7 +2045,11 @@ export class Clerk implements ClerkInterface { } if (this.session?.currentTask) { - await this.redirectToTasks(); + debugger; + + await this.redirectToTasks({ + redirectUrl: this.buildAfterSignInUrl(), + }); return; } diff --git a/packages/types/src/clerk.ts b/packages/types/src/clerk.ts index a9105e5b64e..731bbc39661 100644 --- a/packages/types/src/clerk.ts +++ b/packages/types/src/clerk.ts @@ -1162,6 +1162,8 @@ export type SignUpInitialValues = { username?: string; }; +export type TasksRedirectOptions = RedirectOptions & RedirectUrlProp; + export type SignInRedirectOptions = RedirectOptions & RedirectUrlProp & { /** From d5dd8ec2a2ae640dc311f95bf67dc32c576ab834 Mon Sep 17 00:00:00 2001 From: Laura Beatris <48022589+LauraBeatris@users.noreply.github.com> Date: Wed, 20 Aug 2025 12:11:52 -0300 Subject: [PATCH 6/7] Update changeset --- .changeset/mean-pumas-cut.md | 1 + packages/clerk-js/src/core/clerk.ts | 2 -- packages/react/src/components/controlComponents.tsx | 6 +++--- packages/react/src/isomorphicClerk.ts | 5 +++-- packages/react/src/types.ts | 2 ++ packages/types/src/clerk.ts | 4 +++- 6 files changed, 12 insertions(+), 8 deletions(-) diff --git a/.changeset/mean-pumas-cut.md b/.changeset/mean-pumas-cut.md index 0bcb91d4890..a5936ab2a2e 100644 --- a/.changeset/mean-pumas-cut.md +++ b/.changeset/mean-pumas-cut.md @@ -1,5 +1,6 @@ --- '@clerk/clerk-js': patch +'@clerk/types': patch --- Fix incorrect redirect when completing session tasks within `SignIn` and `SignUp` components diff --git a/packages/clerk-js/src/core/clerk.ts b/packages/clerk-js/src/core/clerk.ts index 1f06f3342fb..914fdcbdfb5 100644 --- a/packages/clerk-js/src/core/clerk.ts +++ b/packages/clerk-js/src/core/clerk.ts @@ -2045,8 +2045,6 @@ export class Clerk implements ClerkInterface { } if (this.session?.currentTask) { - debugger; - await this.redirectToTasks({ redirectUrl: this.buildAfterSignInUrl(), }); diff --git a/packages/react/src/components/controlComponents.tsx b/packages/react/src/components/controlComponents.tsx index 6ac89e1becb..8e954c8f2a5 100644 --- a/packages/react/src/components/controlComponents.tsx +++ b/packages/react/src/components/controlComponents.tsx @@ -6,7 +6,7 @@ import { useIsomorphicClerkContext } from '../contexts/IsomorphicClerkContext'; import { useSessionContext } from '../contexts/SessionContext'; import { useAuth } from '../hooks'; import { useAssertWrappedByClerkProvider } from '../hooks/useAssertWrappedByClerkProvider'; -import type { RedirectToSignInProps, RedirectToSignUpProps, WithClerkProp } from '../types'; +import type { RedirectToSignInProps, RedirectToSignUpProps, RedirectToTasksProps, WithClerkProp } from '../types'; import { withClerk } from './withClerk'; export const SignedIn = ({ children, treatPendingAsSignedOut }: React.PropsWithChildren) => { @@ -166,9 +166,9 @@ export const RedirectToSignUp = withClerk(({ clerk, ...props }: WithClerkProp { +export const RedirectToTasks = withClerk(({ clerk, ...props }: WithClerkProp) => { React.useEffect(() => { - void clerk.redirectToTasks(); + void clerk.redirectToTasks(props); }, []); return null; diff --git a/packages/react/src/isomorphicClerk.ts b/packages/react/src/isomorphicClerk.ts index 22f70b3aaa3..1e94bc0a6c9 100644 --- a/packages/react/src/isomorphicClerk.ts +++ b/packages/react/src/isomorphicClerk.ts @@ -45,6 +45,7 @@ import type { SignUpResource, State, TaskChooseOrganizationProps, + TasksRedirectOptions, UnsubscribeCallback, UserButtonProps, UserProfileProps, @@ -1276,8 +1277,8 @@ export class IsomorphicClerk implements IsomorphicLoadedClerk { } }; - redirectToTasks = async () => { - const callback = () => this.clerkjs?.redirectToTasks(); + redirectToTasks = async (opts?: TasksRedirectOptions) => { + const callback = () => this.clerkjs?.redirectToTasks(opts); if (this.clerkjs && this.loaded) { return callback(); } else { diff --git a/packages/react/src/types.ts b/packages/react/src/types.ts index b24a28a4df0..1865241e02c 100644 --- a/packages/react/src/types.ts +++ b/packages/react/src/types.ts @@ -9,6 +9,7 @@ import type { RedirectUrlProp, SignInRedirectOptions, SignUpRedirectOptions, + TasksRedirectOptions, Without, } from '@clerk/types'; import type React from 'react'; @@ -116,6 +117,7 @@ export type SignInWithMetamaskButtonProps = { export type RedirectToSignInProps = SignInRedirectOptions; export type RedirectToSignUpProps = SignUpRedirectOptions; +export type RedirectToTasksProps = TasksRedirectOptions; type PageProps = | { diff --git a/packages/types/src/clerk.ts b/packages/types/src/clerk.ts index 731bbc39661..f53dbddc0bb 100644 --- a/packages/types/src/clerk.ts +++ b/packages/types/src/clerk.ts @@ -769,8 +769,10 @@ export interface Clerk { /** * Redirects to the configured URL where tasks are mounted. + * + * @param opts A {@link RedirectOptions} object */ - redirectToTasks(): Promise; + redirectToTasks(opts?: TasksRedirectOptions): Promise; /** * Completes a Google One Tap redirection flow started by From 6427b9397d97293afbc734c10a33abb8c3595cbe Mon Sep 17 00:00:00 2001 From: Laura Beatris <48022589+LauraBeatris@users.noreply.github.com> Date: Wed, 20 Aug 2025 13:14:11 -0300 Subject: [PATCH 7/7] Update control component for Vue --- packages/vue/src/components/controlComponents.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/vue/src/components/controlComponents.ts b/packages/vue/src/components/controlComponents.ts index cb787b1d8cf..195dd0f1590 100644 --- a/packages/vue/src/components/controlComponents.ts +++ b/packages/vue/src/components/controlComponents.ts @@ -60,9 +60,9 @@ export const RedirectToSignUp = defineComponent((props: RedirectOptions) => { return () => null; }); -export const RedirectToTasks = defineComponent(() => { +export const RedirectToTasks = defineComponent((props: RedirectOptions) => { useClerkLoaded(clerk => { - void clerk.redirectToTasks(); + void clerk.redirectToTasks(props); }); return () => null;