Skip to content

Commit 4704dfd

Browse files
authored
fix(ui): Skip strategy selection screen if it's the only available on setup mfa session task (#7760)
1 parent 677a9b5 commit 4704dfd

3 files changed

Lines changed: 51 additions & 10 deletions

File tree

.changeset/pretty-queens-relate.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@clerk/ui': patch
3+
---
4+
5+
Skip the strategy selection screen if only one MFA strategy is available for the setup MFA session task

packages/ui/src/components/SessionTasks/tasks/TaskSetupMfa/__tests__/TaskSetupMfa.test.tsx

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ describe('TaskSetupMFA', () => {
3333
identifier: 'test@clerk.com',
3434
tasks: [{ key: 'setup-mfa' }],
3535
});
36+
f.withAuthenticatorApp({ enabled: true });
37+
f.withPhoneNumber({ second_factors: ['phone_code'], used_for_second_factor: true });
3638
});
3739

3840
const { queryByText, queryByRole } = render(<TaskSetupMFA />, { wrapper });
@@ -60,7 +62,7 @@ describe('TaskSetupMFA', () => {
6062
expect(getByRole('button', { name: /sms code/i })).toBeInTheDocument();
6163
});
6264

63-
it('should render SMS code item on the first screen if only SMS code is enabled', async () => {
65+
it('should skip selection screen and go directly to SMS code flow when only SMS code is enabled', async () => {
6466
const { wrapper } = await createFixtures(f => {
6567
f.withUser({
6668
email_addresses: ['test@clerk.com'],
@@ -70,14 +72,14 @@ describe('TaskSetupMFA', () => {
7072
f.withPhoneNumber({ second_factors: ['phone_code'], used_for_second_factor: true });
7173
});
7274

73-
const { getByRole, queryByRole } = render(<TaskSetupMFA />, { wrapper });
75+
const { findByText, queryByText } = render(<TaskSetupMFA />, { wrapper });
7476

75-
expect(queryByRole('button', { name: /authenticator application/i })).not.toBeInTheDocument();
76-
expect(getByRole('button', { name: /sms code/i })).toBeInTheDocument();
77+
await findByText(/add phone number/i);
78+
expect(queryByText(/set up two-step verification/i)).not.toBeInTheDocument();
7779
});
7880

79-
it('should render TOTP item on the first screen if only TOTP is enabled', async () => {
80-
const { wrapper } = await createFixtures(f => {
81+
it('should skip selection screen and go directly to TOTP flow when only TOTP is enabled', async () => {
82+
const { wrapper, fixtures } = await createFixtures(f => {
8183
f.withUser({
8284
email_addresses: ['test@clerk.com'],
8385
identifier: 'test@clerk.com',
@@ -86,10 +88,15 @@ describe('TaskSetupMFA', () => {
8688
f.withAuthenticatorApp({ enabled: true });
8789
});
8890

89-
const { getByRole, queryByRole } = render(<TaskSetupMFA />, { wrapper });
91+
fixtures.clerk.user?.createTOTP.mockResolvedValue({
92+
uri: 'otpauth://totp/Test:test@clerk.com?secret=TESTSECRET&issuer=Test',
93+
secret: 'TESTSECRET',
94+
} as TOTPResource);
95+
96+
const { findByText, queryByText } = render(<TaskSetupMFA />, { wrapper });
9097

91-
expect(getByRole('button', { name: /authenticator application/i })).toBeInTheDocument();
92-
expect(queryByRole('button', { name: /sms code/i })).not.toBeInTheDocument();
98+
await findByText(/add authenticator application/i);
99+
expect(queryByText(/set up two-step verification/i)).not.toBeInTheDocument();
93100
});
94101
});
95102
describe('authenticator application', () => {
@@ -101,6 +108,7 @@ describe('TaskSetupMFA', () => {
101108
tasks: [{ key: 'setup-mfa' }],
102109
});
103110
f.withAuthenticatorApp({ enabled: true });
111+
f.withPhoneNumber({ second_factors: ['phone_code'], used_for_second_factor: true });
104112
});
105113

106114
fixtures.clerk.user?.createTOTP.mockResolvedValue({
@@ -127,6 +135,7 @@ describe('TaskSetupMFA', () => {
127135
tasks: [{ key: 'setup-mfa' }],
128136
});
129137
f.withAuthenticatorApp({ enabled: true });
138+
f.withPhoneNumber({ second_factors: ['phone_code'], used_for_second_factor: true });
130139
});
131140

132141
fixtures.clerk.user?.createTOTP.mockResolvedValue({
@@ -159,6 +168,7 @@ describe('TaskSetupMFA', () => {
159168
tasks: [{ key: 'setup-mfa' }],
160169
});
161170
f.withAuthenticatorApp({ enabled: true });
171+
f.withPhoneNumber({ second_factors: ['phone_code'], used_for_second_factor: true });
162172
});
163173

164174
fixtures.clerk.user?.createTOTP.mockResolvedValue({
@@ -190,6 +200,7 @@ describe('TaskSetupMFA', () => {
190200
tasks: [{ key: 'setup-mfa' }],
191201
});
192202
f.withAuthenticatorApp({ enabled: true });
203+
f.withPhoneNumber({ second_factors: ['phone_code'], used_for_second_factor: true });
193204
f.withBackupCode();
194205
});
195206

@@ -234,6 +245,7 @@ describe('TaskSetupMFA', () => {
234245
tasks: [{ key: 'setup-mfa' }],
235246
});
236247
f.withAuthenticatorApp({ enabled: true });
248+
f.withPhoneNumber({ second_factors: ['phone_code'], used_for_second_factor: true });
237249
});
238250

239251
fixtures.clerk.user?.createTOTP.mockResolvedValue({
@@ -275,6 +287,7 @@ describe('TaskSetupMFA', () => {
275287
tasks: [{ key: 'setup-mfa' }],
276288
});
277289
f.withAuthenticatorApp({ enabled: true });
290+
f.withPhoneNumber({ second_factors: ['phone_code'], used_for_second_factor: true });
278291
});
279292

280293
fixtures.clerk.user?.createTOTP.mockResolvedValue({
@@ -351,6 +364,7 @@ describe('TaskSetupMFA', () => {
351364
tasks: [{ key: 'setup-mfa' }],
352365
});
353366
f.withAuthenticatorApp({ enabled: true });
367+
f.withPhoneNumber({ second_factors: ['phone_code'], used_for_second_factor: true });
354368
});
355369

356370
fixtures.clerk.user?.createTOTP.mockRejectedValueOnce(
@@ -384,6 +398,7 @@ describe('TaskSetupMFA', () => {
384398
tasks: [{ key: 'setup-mfa' }],
385399
});
386400
f.withAuthenticatorApp({ enabled: true });
401+
f.withPhoneNumber({ second_factors: ['phone_code'], used_for_second_factor: true });
387402
});
388403

389404
fixtures.clerk.user?.createTOTP.mockResolvedValue({
@@ -438,6 +453,7 @@ describe('TaskSetupMFA', () => {
438453
phone_numbers: [{ phone_number: '+306911111111', id: 'phone_1' }],
439454
tasks: [{ key: 'setup-mfa' }],
440455
});
456+
f.withAuthenticatorApp({ enabled: true });
441457
f.withPhoneNumber({ second_factors: ['phone_code'], used_for_second_factor: true });
442458
});
443459

@@ -460,6 +476,7 @@ describe('TaskSetupMFA', () => {
460476
identifier: 'test@clerk.com',
461477
tasks: [{ key: 'setup-mfa' }],
462478
});
479+
f.withAuthenticatorApp({ enabled: true });
463480
f.withPhoneNumber({ second_factors: ['phone_code'], used_for_second_factor: true });
464481
});
465482

@@ -481,6 +498,7 @@ describe('TaskSetupMFA', () => {
481498
phone_numbers: [{ phone_number: '+306911111111', id: 'phone_1' }],
482499
tasks: [{ key: 'setup-mfa' }],
483500
});
501+
f.withAuthenticatorApp({ enabled: true });
484502
f.withPhoneNumber({ second_factors: ['phone_code'], used_for_second_factor: true });
485503
});
486504

@@ -514,6 +532,7 @@ describe('TaskSetupMFA', () => {
514532
],
515533
tasks: [{ key: 'setup-mfa' }],
516534
});
535+
f.withAuthenticatorApp({ enabled: true });
517536
f.withPhoneNumber({ second_factors: ['phone_code'], used_for_second_factor: true });
518537
f.withBackupCode();
519538
});
@@ -556,6 +575,7 @@ describe('TaskSetupMFA', () => {
556575
],
557576
tasks: [{ key: 'setup-mfa' }],
558577
});
578+
f.withAuthenticatorApp({ enabled: true });
559579
f.withPhoneNumber({ second_factors: ['phone_code'], used_for_second_factor: true });
560580
});
561581

@@ -602,6 +622,7 @@ describe('TaskSetupMFA', () => {
602622
],
603623
tasks: [{ key: 'setup-mfa' }],
604624
});
625+
f.withAuthenticatorApp({ enabled: true });
605626
f.withPhoneNumber({ second_factors: ['phone_code'], used_for_second_factor: true });
606627
});
607628

@@ -662,6 +683,7 @@ describe('TaskSetupMFA', () => {
662683
],
663684
tasks: [{ key: 'setup-mfa' }],
664685
});
686+
f.withAuthenticatorApp({ enabled: true });
665687
f.withPhoneNumber({ second_factors: ['phone_code'], used_for_second_factor: true });
666688
});
667689

@@ -705,6 +727,7 @@ describe('TaskSetupMFA', () => {
705727
identifier: 'test@clerk.com',
706728
tasks: [{ key: 'setup-mfa' }],
707729
});
730+
f.withAuthenticatorApp({ enabled: true });
708731
f.withPhoneNumber({ second_factors: ['phone_code'], used_for_second_factor: true });
709732
});
710733

@@ -746,6 +769,7 @@ describe('TaskSetupMFA', () => {
746769
identifier: 'test@clerk.com',
747770
tasks: [{ key: 'setup-mfa' }],
748771
});
772+
f.withAuthenticatorApp({ enabled: true });
749773
f.withPhoneNumber({ second_factors: ['phone_code'], used_for_second_factor: true });
750774
});
751775

@@ -794,6 +818,7 @@ describe('TaskSetupMFA', () => {
794818
],
795819
tasks: [{ key: 'setup-mfa' }],
796820
});
821+
f.withAuthenticatorApp({ enabled: true });
797822
f.withPhoneNumber({ second_factors: ['phone_code'], used_for_second_factor: true });
798823
});
799824

@@ -846,6 +871,7 @@ describe('TaskSetupMFA', () => {
846871
],
847872
tasks: [{ key: 'setup-mfa' }],
848873
});
874+
f.withAuthenticatorApp({ enabled: true });
849875
f.withPhoneNumber({ second_factors: ['phone_code'], used_for_second_factor: true });
850876
});
851877

packages/ui/src/components/SessionTasks/tasks/TaskSetupMfa/index.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ import { SetupMfaStartScreen } from './SetupMfaStartScreen';
1313
import { SmsCodeFlow } from './SmsCodeFlowScreen';
1414
import { TOTPCodeFlow } from './TOTPCodeFlowScreen';
1515

16+
const WIZARD_STEPS = {
17+
start: 0,
18+
phoneCode: 1,
19+
totp: 2,
20+
} as const;
21+
1622
const TaskSetupMFAInternal = () => {
1723
const clerk = useClerk();
1824
const { user } = useUser();
@@ -38,7 +44,11 @@ const TaskSetupMFAInternal = () => {
3844
});
3945
}, [attributes, user]);
4046

41-
const wizard = useWizard({ defaultStep: 0 });
47+
const defaultStep =
48+
secondFactorsAvailableToAdd.indexOf('phone_code') > -1 ? WIZARD_STEPS.phoneCode : WIZARD_STEPS.totp;
49+
const wizard = useWizard({
50+
defaultStep: secondFactorsAvailableToAdd.length > 1 ? WIZARD_STEPS.start : defaultStep,
51+
});
4252
const { redirectUrlComplete } = useTaskSetupMFAContext();
4353
const { navigateOnSetActive, redirectOnActiveSession } = useSessionTasksContext();
4454

0 commit comments

Comments
 (0)