Skip to content

Commit 011afdd

Browse files
committed
Add redirect guards for root sign-in / sign-up AIOs
This makes it so that it's not possible to access `/sign-in` or `/sign-up` within AIOs if you have a current task. It navigates to the task with the base URL according to the sign-in or sign-up context.
1 parent 23a530f commit 011afdd

File tree

14 files changed

+121
-29
lines changed

14 files changed

+121
-29
lines changed

packages/clerk-js/src/core/clerk.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,8 +1257,6 @@ export class Clerk implements ClerkInterface {
12571257
}
12581258
}
12591259

1260-
debugger;
1261-
12621260
if (newSession?.status === 'pending') {
12631261
await this.#handlePendingSession(newSession, onPendingSession);
12641262
return;
@@ -1331,8 +1329,6 @@ export class Clerk implements ClerkInterface {
13311329
};
13321330

13331331
#handlePendingSession = async (session: PendingSessionResource, onPendingSession?: OnPendingSessionFn) => {
1334-
debugger;
1335-
13361332
if (!this.environment) {
13371333
return;
13381334
}
@@ -1355,12 +1351,12 @@ export class Clerk implements ClerkInterface {
13551351

13561352
if (currentSession.status === 'pending') {
13571353
const tracker = createBeforeUnloadTracker(this.#options.standardBrowser);
1354+
13581355
const onPendingSessionHook = this.#options['onPendingSession'] ?? onPendingSession;
13591356
const taskUrls = this.#options['taskUrls'];
13601357

13611358
await tracker.track(async () => {
13621359
if (onPendingSessionHook) {
1363-
debugger;
13641360
await onPendingSessionHook({ session: currentSession });
13651361
} else if (taskUrls) {
13661362
await this.navigate(taskUrls[session.currentTask.key]);

packages/clerk-js/src/core/sessionTasks.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,21 @@ interface NavigateToTaskOptions {
1212
options?: ClerkOptions;
1313
}
1414

15+
export function buildTaskURL(task: SessionTask, opts: Pick<Parameters<typeof buildURL>[0], 'base'>) {
16+
return buildURL(
17+
{
18+
base: opts.base,
19+
hashPath: `/tasks/${INTERNAL_SESSION_TASK_ROUTE_BY_KEY[task.key]}`,
20+
},
21+
{ stringify: true },
22+
);
23+
}
24+
1525
/**
1626
* @internal
1727
*/
1828
export function navigateToTask(session: PendingSessionResource, { options, navigate, baseUrl }: NavigateToTaskOptions) {
1929
const currentTaskKey = session.currentTask.key;
2030

21-
return navigate(
22-
options?.taskUrls?.[currentTaskKey] ??
23-
buildURL(
24-
{
25-
base: baseUrl,
26-
hashPath: `/tasks/${INTERNAL_SESSION_TASK_ROUTE_BY_KEY[currentTaskKey]}`,
27-
},
28-
{ stringify: true },
29-
),
30-
);
31+
return navigate(options?.taskUrls?.[currentTaskKey] ?? buildTaskURL(session.currentTask, { base: baseUrl }));
3132
}

packages/clerk-js/src/ui/common/withRedirect.tsx

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,57 @@ export const withRedirectToAfterSignUp = <P extends AvailableComponentProps>(Com
8989

9090
return HOC;
9191
};
92+
93+
export const withRedirectToSignInTask = <P extends AvailableComponentProps>(Component: ComponentType<P>) => {
94+
const displayName = Component.displayName || Component.name || 'Component';
95+
Component.displayName = displayName;
96+
97+
const HOC = (props: P) => {
98+
const signInCtx = useSignInContext();
99+
100+
return withRedirect(
101+
Component,
102+
clerk => !!clerk.session?.currentTask,
103+
({ clerk }) => {
104+
const currentTask = clerk.session?.currentTask;
105+
if (!currentTask || !signInCtx?.taskUrl) {
106+
return '';
107+
}
108+
109+
return signInCtx?.taskUrl;
110+
},
111+
undefined,
112+
)(props);
113+
};
114+
115+
HOC.displayName = `withRedirectToAfterSignIn(${displayName})`;
116+
117+
return HOC;
118+
};
119+
120+
export const withRedirectToSignUpTask = <P extends AvailableComponentProps>(Component: ComponentType<P>) => {
121+
const displayName = Component.displayName || Component.name || 'Component';
122+
Component.displayName = displayName;
123+
124+
const HOC = (props: P) => {
125+
const signUpCtx = useSignUpContext();
126+
127+
return withRedirect(
128+
Component,
129+
clerk => !!clerk.session?.currentTask,
130+
({ clerk }) => {
131+
const currentTask = clerk.session?.currentTask;
132+
if (!currentTask || !signUpCtx?.taskUrl) {
133+
return '';
134+
}
135+
136+
return signUpCtx?.taskUrl;
137+
},
138+
undefined,
139+
)(props);
140+
};
141+
142+
HOC.displayName = `withRedirectToAfterSignIn(${displayName})`;
143+
144+
return HOC;
145+
};

packages/clerk-js/src/ui/components/SessionTasks/index.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ const SessionTasksStart = () => {
2424
useEffect(() => {
2525
// Simulates additional latency to avoid a abrupt UI transition when navigating to the next task
2626
const timeoutId = setTimeout(() => {
27-
// TODO - call setActive?
27+
const currentTaskKey = clerk.session?.currentTask?.key;
28+
if (!currentTaskKey) return;
29+
30+
void navigate(`./${INTERNAL_SESSION_TASK_ROUTE_BY_KEY[currentTaskKey]}`);
2831
}, 500);
2932
return () => clearTimeout(timeoutId);
3033
}, [navigate, clerk, redirectUrlComplete]);

packages/clerk-js/src/ui/components/SignIn/SignInAccountSwitcher.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { Header } from '@/ui/elements/Header';
55
import { PreviewButton } from '@/ui/elements/PreviewButton';
66
import { UserPreview } from '@/ui/elements/UserPreview';
77

8-
import { withRedirectToAfterSignIn } from '../../common';
8+
import { withRedirectToAfterSignIn, withRedirectToSignInTask } from '../../common';
99
import { useEnvironment, useSignInContext, useSignOutContext } from '../../contexts';
1010
import { Col, descriptors, Flow, localizationKeys } from '../../customizables';
1111
import { Add, SwitchArrowRight } from '../../icons';
@@ -125,4 +125,6 @@ const SignInAccountSwitcherInternal = () => {
125125
</Flow.Part>
126126
);
127127
};
128-
export const SignInAccountSwitcher = withRedirectToAfterSignIn(withCardStateProvider(SignInAccountSwitcherInternal));
128+
export const SignInAccountSwitcher = withRedirectToSignInTask(
129+
withRedirectToAfterSignIn(withCardStateProvider(SignInAccountSwitcherInternal)),
130+
);

packages/clerk-js/src/ui/components/SignIn/SignInFactorOne.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { useCardState, withCardStateProvider } from '@/ui/elements/contexts';
66
import { ErrorCard } from '@/ui/elements/ErrorCard';
77
import { LoadingCard } from '@/ui/elements/LoadingCard';
88

9-
import { withRedirectToAfterSignIn } from '../../common';
9+
import { withRedirectToAfterSignIn, withRedirectToSignInTask } from '../../common';
1010
import { useCoreSignIn, useEnvironment } from '../../contexts';
1111
import { useAlternativeStrategies } from '../../hooks/useAlternativeStrategies';
1212
import { localizationKeys } from '../../localization';
@@ -251,4 +251,6 @@ function SignInFactorOneInternal(): JSX.Element {
251251
}
252252
}
253253

254-
export const SignInFactorOne = withRedirectToAfterSignIn(withCardStateProvider(SignInFactorOneInternal));
254+
export const SignInFactorOne = withRedirectToSignInTask(
255+
withRedirectToAfterSignIn(withCardStateProvider(SignInFactorOneInternal)),
256+
);

packages/clerk-js/src/ui/components/SignIn/SignInFactorTwo.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import React from 'react';
44
import { withCardStateProvider } from '@/ui/elements/contexts';
55
import { LoadingCard } from '@/ui/elements/LoadingCard';
66

7-
import { withRedirectToAfterSignIn } from '../../common';
7+
import { withRedirectToAfterSignIn, withRedirectToSignInTask } from '../../common';
88
import { useCoreSignIn } from '../../contexts';
99
import { SignInFactorTwoAlternativeMethods } from './SignInFactorTwoAlternativeMethods';
1010
import { SignInFactorTwoBackupCodeCard } from './SignInFactorTwoBackupCodeCard';
@@ -82,4 +82,6 @@ function SignInFactorTwoInternal(): JSX.Element {
8282
}
8383
}
8484

85-
export const SignInFactorTwo = withRedirectToAfterSignIn(withCardStateProvider(SignInFactorTwoInternal));
85+
export const SignInFactorTwo = withRedirectToSignInTask(
86+
withRedirectToAfterSignIn(withCardStateProvider(SignInFactorTwoInternal)),
87+
);
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
import { SSOCallback, withRedirectToAfterSignIn } from '../../common';
1+
import { SSOCallback, withRedirectToAfterSignIn, withRedirectToSignInTask } from '../../common';
22

3-
export const SignInSSOCallback = withRedirectToAfterSignIn(SSOCallback);
3+
export const SignInSSOCallback = withRedirectToSignInTask(withRedirectToAfterSignIn(SSOCallback));

packages/clerk-js/src/ui/components/SignIn/SignInStart.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
getIdentifierControlDisplayValues,
3131
groupIdentifiers,
3232
withRedirectToAfterSignIn,
33+
withRedirectToSignInTask,
3334
} from '../../common';
3435
import { useCoreSignIn, useEnvironment, useSignInContext } from '../../contexts';
3536
import { Col, descriptors, Flow, localizationKeys } from '../../customizables';
@@ -678,4 +679,6 @@ const InstantPasswordRow = ({ field }: { field?: FormControlState<'password'> })
678679
);
679680
};
680681

681-
export const SignInStart = withRedirectToAfterSignIn(withCardStateProvider(SignInStartInternal));
682+
export const SignInStart = withRedirectToSignInTask(
683+
withRedirectToAfterSignIn(withCardStateProvider(SignInStartInternal)),
684+
);
Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1-
import { SSOCallback, withRedirectToAfterSignUp } from '../../common';
1+
import {
2+
SSOCallback,
3+
withRedirectToAfterSignUp,
4+
withRedirectToSignUpTask,
5+
withRedirectToSignUpTask,
6+
} from '../../common';
27

3-
export const SignUpSSOCallback = withRedirectToAfterSignUp(SSOCallback);
8+
export const SignUpSSOCallback = withRedirectToSignUpTask(withRedirectToAfterSignUp(SSOCallback));

0 commit comments

Comments
 (0)