Skip to content

Commit ad6de28

Browse files
committed
fix(clerk-js): redirect signed-in users forward from factor-two
When a signed-in user lands on factor-two without a pending 2FA (e.g. page reload after successful verification in a multi-session app), redirect to afterSignInUrl instead of back to sign-in start.
1 parent 58f4a39 commit ad6de28

2 files changed

Lines changed: 16 additions & 8 deletions

File tree

.changeset/fix-factor-two-infinite-spinner.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
'@clerk/clerk-js': patch
33
---
44

5-
Fix infinite loading spinner when navigating to factor-two sign-in route without an active 2FA session
5+
Fix infinite loading spinner when navigating to factor-two sign-in route without an active 2FA session. When the user is already signed in (e.g. multi-session app page reload after successful verification), redirects forward to afterSignInUrl instead of back to sign-in start.

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

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

88
import { withRedirectToAfterSignIn, withRedirectToSignInTask } from '../../common';
9-
import { useCoreSignIn } from '../../contexts';
9+
import { useCoreSignIn, useSignInContext } from '../../contexts';
1010
import { useRouter } from '../../router';
1111
import { SignInFactorTwoAlternativeMethods } from './SignInFactorTwoAlternativeMethods';
1212
import { SignInFactorTwoBackupCodeCard } from './SignInFactorTwoBackupCodeCard';
@@ -28,9 +28,10 @@ const factorKey = (factor: SignInFactor | null | undefined) => {
2828
};
2929

3030
function SignInFactorTwoInternal(): JSX.Element {
31-
const { __internal_setActiveInProgress } = useClerk();
31+
const clerk = useClerk();
3232
const signIn = useCoreSignIn();
3333
const router = useRouter();
34+
const { afterSignInUrl } = useSignInContext();
3435
const availableFactors = signIn.supportedSecondFactors;
3536

3637
const lastPreparedFactorKeyRef = React.useRef('');
@@ -50,17 +51,24 @@ function SignInFactorTwoInternal(): JSX.Element {
5051
};
5152

5253
React.useEffect(() => {
53-
if (__internal_setActiveInProgress) {
54+
if (clerk.__internal_setActiveInProgress) {
5455
return;
5556
}
5657

57-
// If the sign-in was reset or doesn't exist, redirect back to the start.
58+
// If the sign-in doesn't need second factor verification, redirect away.
5859
// Don't redirect for 'complete' status - setActive will handle navigation.
5960
if (signIn.status === null || signIn.status === 'needs_identifier' || signIn.status === 'needs_first_factor') {
60-
void router.navigate('../');
61+
// If the user is already signed in (e.g. multi-session app, page reload after
62+
// successful verification), redirect forward to afterSignInUrl instead of
63+
// back to sign-in start.
64+
if (clerk.isSignedIn) {
65+
void router.navigate(afterSignInUrl);
66+
} else {
67+
void router.navigate('../');
68+
}
6169
}
62-
// eslint-disable-next-line react-hooks/exhaustive-deps -- Match SignInFactorOne pattern: only run on mount and when setActiveInProgress changes
63-
}, [__internal_setActiveInProgress]);
70+
// eslint-disable-next-line react-hooks/exhaustive-deps -- Only run on mount and when setActiveInProgress changes
71+
}, [clerk.__internal_setActiveInProgress]);
6472

6573
if (!currentFactor) {
6674
return <LoadingCard />;

0 commit comments

Comments
 (0)