Skip to content

Commit fb932e5

Browse files
authoredOct 2, 2024··
chore(clerk-js, clerk-react,types): Rename assurance to reverification (#4268)
1 parent 2e369ee commit fb932e5

File tree

10 files changed

+256
-147
lines changed

10 files changed

+256
-147
lines changed
 

‎.changeset/purple-goats-applaud.md

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
"@clerk/clerk-js": minor
3+
"@clerk/shared": minor
4+
"@clerk/clerk-react": minor
5+
"@clerk/types": minor
6+
---
7+
8+
Rename `__experimental_assurance` to `__experimental_reverification`.
9+
10+
- Supported levels are now are `firstFactor`, `secondFactor`, `multiFactor`.
11+
- Support maxAge is now replaced by maxAgeMinutes and afterMinutes depending on usage.
12+
- Introduced `____experimental_SessionVerificationTypes` that abstracts away the level and maxAge
13+
- Allowed values 'veryStrict' | 'strict' | 'moderate' | 'lax'

‎packages/clerk-js/bundlewatch.config.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"files": [
3-
{ "path": "./dist/clerk.browser.js", "maxSize": "65kB" },
3+
{ "path": "./dist/clerk.browser.js", "maxSize": "64.5kB" },
44
{ "path": "./dist/clerk.headless.js", "maxSize": "43kB" },
55
{ "path": "./dist/ui-common*.js", "maxSize": "86KB" },
66
{ "path": "./dist/vendors*.js", "maxSize": "70KB" },

‎packages/clerk-js/src/core/resources/Session.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -122,15 +122,15 @@ export class Session extends BaseResource implements SessionResource {
122122

123123
__experimental_startVerification = async ({
124124
level,
125-
maxAge,
125+
maxAgeMinutes,
126126
}: __experimental_SessionVerifyCreateParams): Promise<__experimental_SessionVerificationResource> => {
127127
const json = (
128128
await BaseResource._fetch({
129129
method: 'POST',
130130
path: `/client/sessions/${this.id}/verify`,
131131
body: {
132132
level,
133-
maxAge,
133+
maxAgeMinutes,
134134
} as any,
135135
})
136136
)?.response as unknown as __experimental_SessionVerificationJSON;

‎packages/clerk-js/src/core/resources/__tests__/Session.test.ts

+101-71
Original file line numberDiff line numberDiff line change
@@ -311,9 +311,9 @@ describe('Session', () => {
311311

312312
const isAuthorized = session.checkAuthorization({
313313
permission: 'org:sys_profile:delete',
314-
__experimental_assurance: {
315-
level: 'L2.secondFactor',
316-
maxAge: 'A1.10min',
314+
__experimental_reverification: {
315+
level: 'multiFactor',
316+
afterMinutes: 10,
317317
},
318318
});
319319

@@ -338,9 +338,9 @@ describe('Session', () => {
338338

339339
const isAuthorized = session.checkAuthorization({
340340
permission: 'org:sys_profile:delete',
341-
__experimental_assurance: {
342-
level: 'L2.secondFactor',
343-
maxAge: 'A1.10min',
341+
__experimental_reverification: {
342+
level: 'multiFactor',
343+
afterMinutes: 10,
344344
},
345345
});
346346

@@ -362,9 +362,9 @@ describe('Session', () => {
362362
} as SessionJSON);
363363

364364
const isAuthorized = session.checkAuthorization({
365-
__experimental_assurance: {
366-
level: 'L2.secondFactor',
367-
maxAge: 'A1.10min',
365+
__experimental_reverification: {
366+
level: 'multiFactor',
367+
afterMinutes: 10,
368368
},
369369
});
370370

@@ -386,9 +386,9 @@ describe('Session', () => {
386386
} as SessionJSON);
387387

388388
const isAuthorized = session.checkAuthorization({
389-
__experimental_assurance: {
390-
level: 'L2.secondFactor',
391-
maxAge: 'A1.10min',
389+
__experimental_reverification: {
390+
level: 'multiFactor',
391+
afterMinutes: 10,
392392
},
393393
});
394394

@@ -410,9 +410,9 @@ describe('Session', () => {
410410
} as SessionJSON);
411411

412412
const isAuthorized = session.checkAuthorization({
413-
__experimental_assurance: {
414-
level: 'L1.firstFactor',
415-
maxAge: 'A1.10min',
413+
__experimental_reverification: {
414+
level: 'multiFactor',
415+
afterMinutes: 10,
416416
},
417417
});
418418

@@ -434,9 +434,9 @@ describe('Session', () => {
434434
} as SessionJSON);
435435

436436
const isAuthorized = session.checkAuthorization({
437-
__experimental_assurance: {
438-
level: 'L1.firstFactor',
439-
maxAge: 'A1.10min',
437+
__experimental_reverification: {
438+
level: 'multiFactor',
439+
afterMinutes: 10,
440440
},
441441
});
442442

@@ -458,9 +458,9 @@ describe('Session', () => {
458458
} as SessionJSON);
459459

460460
const isAuthorized = session.checkAuthorization({
461-
__experimental_assurance: {
462-
level: 'L2.secondFactor',
463-
maxAge: 'A1.10min',
461+
__experimental_reverification: {
462+
level: 'multiFactor',
463+
afterMinutes: 10,
464464
},
465465
});
466466

@@ -482,10 +482,7 @@ describe('Session', () => {
482482
} as SessionJSON);
483483

484484
const isAuthorized = session.checkAuthorization({
485-
__experimental_assurance: {
486-
level: 'L2.secondFactor',
487-
maxAge: 'A1.10min',
488-
},
485+
__experimental_reverification: 'strict',
489486
});
490487

491488
expect(isAuthorized).toBe(false);
@@ -506,10 +503,7 @@ describe('Session', () => {
506503
} as SessionJSON);
507504

508505
const isAuthorized = session.checkAuthorization({
509-
__experimental_assurance: {
510-
level: 'L3.multiFactor',
511-
maxAge: 'A1.10min',
512-
},
506+
__experimental_reverification: 'veryStrict',
513507
});
514508

515509
expect(isAuthorized).toBe(true);
@@ -530,9 +524,9 @@ describe('Session', () => {
530524
} as SessionJSON);
531525

532526
const isAuthorized = session.checkAuthorization({
533-
__experimental_assurance: {
534-
level: 'L3.multiFactor',
535-
maxAge: 'A1.10min',
527+
__experimental_reverification: {
528+
level: 'multiFactor',
529+
afterMinutes: 10,
536530
},
537531
});
538532

@@ -554,9 +548,9 @@ describe('Session', () => {
554548
} as SessionJSON);
555549

556550
const isAuthorized = session.checkAuthorization({
557-
__experimental_assurance: {
558-
level: 'L3.multiFactor',
559-
maxAge: 'A1.10min',
551+
__experimental_reverification: {
552+
level: 'multiFactor',
553+
afterMinutes: 10,
560554
},
561555
});
562556

@@ -578,9 +572,9 @@ describe('Session', () => {
578572
} as SessionJSON);
579573

580574
const isAuthorized = session.checkAuthorization({
581-
__experimental_assurance: {
582-
level: 'L3.multiFactor',
583-
maxAge: 'A1.10min',
575+
__experimental_reverification: {
576+
level: 'multiFactor',
577+
afterMinutes: 10,
584578
},
585579
});
586580

@@ -602,9 +596,9 @@ describe('Session', () => {
602596
} as SessionJSON);
603597

604598
const isAuthorized = session.checkAuthorization({
605-
__experimental_assurance: {
606-
level: 'L3.multiFactor',
607-
maxAge: 'A1.10min',
599+
__experimental_reverification: {
600+
level: 'multiFactor',
601+
afterMinutes: 10,
608602
},
609603
});
610604

@@ -626,9 +620,9 @@ describe('Session', () => {
626620
} as SessionJSON);
627621

628622
const isAuthorized = session.checkAuthorization({
629-
__experimental_assurance: {
630-
level: 'L3.multiFactor',
631-
maxAge: 'A1.10min',
623+
__experimental_reverification: {
624+
level: 'multiFactor',
625+
afterMinutes: 10,
632626
},
633627
});
634628

@@ -650,9 +644,9 @@ describe('Session', () => {
650644
} as SessionJSON);
651645

652646
const isAuthorized = session.checkAuthorization({
653-
__experimental_assurance: {
654-
level: 'L1.firstFactor',
655-
maxAge: 'A1.10min',
647+
__experimental_reverification: {
648+
level: 'firstFactor',
649+
afterMinutes: 10,
656650
},
657651
});
658652

@@ -674,10 +668,7 @@ describe('Session', () => {
674668
} as SessionJSON);
675669

676670
const isAuthorized = session.checkAuthorization({
677-
__experimental_assurance: {
678-
level: 'L2.secondFactor',
679-
maxAge: 'A1.10min',
680-
},
671+
__experimental_reverification: 'strict',
681672
});
682673

683674
expect(isAuthorized).toBe(false);
@@ -686,7 +677,7 @@ describe('Session', () => {
686677
/**
687678
* Test for invalid input
688679
*/
689-
it('incorrect params for __experimental_assurance', async () => {
680+
it('incorrect params for __experimental_reverification', async () => {
690681
const session = new Session({
691682
status: 'active',
692683
id: 'session_1',
@@ -701,17 +692,17 @@ describe('Session', () => {
701692
} as SessionJSON);
702693

703694
const isAuthorized = session.checkAuthorization({
704-
__experimental_assurance: {
695+
__experimental_reverification: {
705696
//@ts-expect-error
706697
level: 'any level',
707-
maxAge: 'A1.10min',
698+
afterMinutes: 10,
708699
},
709700
});
710701

711702
expect(isAuthorized).toBe(false);
712703
});
713704

714-
it('incorrect params for __experimental_assurance', async () => {
705+
it('incorrect params for __experimental_reverification', async () => {
715706
const session = new Session({
716707
status: 'active',
717708
id: 'session_1',
@@ -726,18 +717,39 @@ describe('Session', () => {
726717
} as SessionJSON);
727718

728719
const isAuthorized = session.checkAuthorization({
729-
__experimental_assurance: {
720+
__experimental_reverification: {
730721
//@ts-expect-error
731722
level: 'any level',
732723
//@ts-expect-error
733-
maxAge: 'som-value',
724+
afterMinutes: 'some-value',
734725
},
735726
});
736727

737728
expect(isAuthorized).toBe(false);
738729
});
739730

740-
it('incorrect params for __experimental_assurance', async () => {
731+
it('incorrect params for __experimental_reverification', async () => {
732+
const session = new Session({
733+
status: 'active',
734+
id: 'session_1',
735+
object: 'session',
736+
user: createUser(),
737+
last_active_organization_id: null,
738+
last_active_token: { object: 'token', jwt: mockJwt },
739+
actor: null,
740+
created_at: new Date().getTime(),
741+
updated_at: new Date().getTime(),
742+
factor_verification_age: [0, 0],
743+
} as SessionJSON);
744+
745+
const isAuthorized = session.checkAuthorization({
746+
__experimental_reverification: 'invalid-value',
747+
});
748+
749+
expect(isAuthorized).toBe(false);
750+
});
751+
752+
it('incorrect params for __experimental_reverification', async () => {
741753
const session = new Session({
742754
status: 'active',
743755
id: 'session_1',
@@ -752,10 +764,31 @@ describe('Session', () => {
752764
} as SessionJSON);
753765

754766
const isAuthorized = session.checkAuthorization({
755-
__experimental_assurance: {
756-
level: 'L1.firstFactor',
767+
__experimental_reverification: 123,
768+
});
769+
770+
expect(isAuthorized).toBe(false);
771+
});
772+
773+
it('incorrect params for __experimental_reverification', async () => {
774+
const session = new Session({
775+
status: 'active',
776+
id: 'session_1',
777+
object: 'session',
778+
user: createUser(),
779+
last_active_organization_id: null,
780+
last_active_token: { object: 'token', jwt: mockJwt },
781+
actor: null,
782+
created_at: new Date().getTime(),
783+
updated_at: new Date().getTime(),
784+
factor_verification_age: [0, 0],
785+
} as SessionJSON);
786+
787+
const isAuthorized = session.checkAuthorization({
788+
__experimental_reverification: {
789+
level: 'firstFactor',
757790
//@ts-expect-error
758-
maxAge: 100,
791+
afterMinutes: '10',
759792
},
760793
});
761794

@@ -780,9 +813,9 @@ describe('Session', () => {
780813
} as SessionJSON);
781814

782815
const isAuthorized = session.checkAuthorization({
783-
__experimental_assurance: {
784-
level: 'L3.multiFactor',
785-
maxAge: 'A1.10min',
816+
__experimental_reverification: {
817+
level: 'multiFactor',
818+
afterMinutes: 10,
786819
},
787820
});
788821

@@ -804,9 +837,9 @@ describe('Session', () => {
804837
} as SessionJSON);
805838

806839
const isAuthorized = session.checkAuthorization({
807-
__experimental_assurance: {
808-
level: 'L1.firstFactor',
809-
maxAge: 'A1.10min',
840+
__experimental_reverification: {
841+
level: 'firstFactor',
842+
afterMinutes: 10,
810843
},
811844
});
812845

@@ -828,10 +861,7 @@ describe('Session', () => {
828861
} as SessionJSON);
829862

830863
const isAuthorized = session.checkAuthorization({
831-
__experimental_assurance: {
832-
level: 'L2.secondFactor',
833-
maxAge: 'A1.10min',
834-
},
864+
__experimental_reverification: 'strict',
835865
});
836866

837867
expect(isAuthorized).toBe(true);

‎packages/clerk-js/src/ui/components/UserVerification/useUserVerificationSession.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ const useUserVerificationSession = () => {
1010
const data = useFetch(
1111
session ? session.__experimental_startVerification : undefined,
1212
{
13-
level: level || 'L2.secondFactor',
13+
level: level || 'secondFactor',
1414
// TODO(STEP-UP): Figure out if this needs to be a prop
15-
maxAge: 'A1.10min',
15+
maxAgeMinutes: 10,
1616
},
1717
{
1818
throttleTime: 300,

‎packages/react/src/hooks/__tests__/useAuth.test.ts

+53-26
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ describe('useAuth type tests', () => {
1111
expectTypeOf({} as const).toMatchTypeOf<ParamsOfHas>();
1212
});
1313

14+
it('has({randomKey}) is not allowed', () => {
15+
expectTypeOf({
16+
randomKey: '',
17+
}).not.toMatchTypeOf<ParamsOfHas>();
18+
});
19+
1420
it('has({role: string}) is allowed', () => {
1521
expectTypeOf({ role: 'org:admin' }).toMatchTypeOf<ParamsOfHas>();
1622
});
@@ -22,64 +28,85 @@ describe('useAuth type tests', () => {
2228
it('has with role and assurance is allowed', () => {
2329
expectTypeOf({
2430
role: 'org:admin',
25-
__experimental_assurance: {
26-
level: 'L1.firstFactor',
27-
maxAge: 'A1.10min',
31+
__experimental_reverification: {
32+
level: 'firstFactor',
33+
afterMinutes: 10,
2834
},
2935
} as const).toMatchTypeOf<ParamsOfHas>();
3036
});
3137

32-
it('has with permission and assurance is allowed', () => {
38+
it('has with permission and reverification is allowed', () => {
3339
expectTypeOf({
3440
permission: 'org:edit:posts',
35-
__experimental_assurance: {
36-
level: 'L1.firstFactor',
37-
maxAge: 'A1.10min',
41+
__experimental_reverification: {
42+
level: 'firstFactor',
43+
afterMinutes: 10,
3844
},
3945
} as const).toMatchTypeOf<ParamsOfHas>();
4046
});
4147

42-
it('has({assurance: {level, maxAge}}) is allowed', () => {
48+
it('has({reverification: {level, maxAge}}) is allowed', () => {
4349
expectTypeOf({
44-
__experimental_assurance: {
45-
level: 'L1.firstFactor',
46-
maxAge: 'A1.10min',
50+
__experimental_reverification: {
51+
level: 'firstFactor',
52+
afterMinutes: 10,
4753
},
4854
} as const).toMatchTypeOf<ParamsOfHas>();
4955
});
5056

51-
it('assurance with other strings as maxAge should throw', () => {
57+
it('reverification with other values as maxAge should throw', () => {
5258
expectTypeOf({
53-
__experimental_assurance: {
54-
level: 'L1.firstFactor',
55-
maxAge: 'some-value',
59+
__experimental_reverification: {
60+
level: 'firstFactor',
61+
afterMinutes: '10',
5662
},
5763
} as const).not.toMatchTypeOf<ParamsOfHas>();
5864
});
5965

60-
it('assurance with number as maxAge should throw', () => {
66+
it('veryStrict reverification is allowed', () => {
6167
expectTypeOf({
62-
__experimental_assurance: {
63-
level: 'L1.firstFactor',
64-
maxAge: 1000,
65-
},
68+
__experimental_reverification: 'veryStrict',
69+
} as const).toMatchTypeOf<ParamsOfHas>();
70+
});
71+
72+
it('strict reverification is allowed', () => {
73+
expectTypeOf({
74+
__experimental_reverification: 'strict',
75+
} as const).toMatchTypeOf<ParamsOfHas>();
76+
});
77+
78+
it('moderate reverification is allowed', () => {
79+
expectTypeOf({
80+
__experimental_reverification: 'moderate',
81+
} as const).toMatchTypeOf<ParamsOfHas>();
82+
});
83+
84+
it('lax reverification is allowed', () => {
85+
expectTypeOf({
86+
__experimental_reverification: 'lax',
87+
} as const).toMatchTypeOf<ParamsOfHas>();
88+
});
89+
90+
it('random reverification is not allowed', () => {
91+
expectTypeOf({
92+
__experimental_reverification: 'random',
6693
} as const).not.toMatchTypeOf<ParamsOfHas>();
6794
});
6895

69-
it('assurance with other strings as level should throw', () => {
96+
it('reverification with other strings as level should throw', () => {
7097
expectTypeOf({
71-
__experimental_assurance: {
98+
__experimental_reverification: {
7299
level: 'some-factor',
73-
maxAge: 'A1.10min',
100+
afterMinutes: 10,
74101
},
75102
} as const).not.toMatchTypeOf<ParamsOfHas>();
76103
});
77104

78-
it('assurance with number as level should throw', () => {
105+
it('reverification with number as level should throw', () => {
79106
expectTypeOf({
80-
__experimental_assurance: {
107+
__experimental_reverification: {
81108
level: 2,
82-
maxAge: 'A1.10min',
109+
afterMinutes: 10,
83110
},
84111
} as const).not.toMatchTypeOf<ParamsOfHas>();
85112
});

‎packages/shared/src/authorization.ts

+58-31
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
import type {
2+
__experimental_ReverificationConfig,
23
__experimental_SessionVerificationLevel,
3-
__experimental_SessionVerificationMaxAge,
4+
__experimental_SessionVerificationTypes,
45
CheckAuthorizationWithCustomPermissions,
56
OrganizationCustomPermissionKey,
67
OrganizationCustomRoleKey,
78
} from '@clerk/types';
89

9-
type MaxAgeMap = Record<__experimental_SessionVerificationMaxAge, number>;
10+
type TypesToConfig = Record<
11+
__experimental_SessionVerificationTypes,
12+
Exclude<__experimental_ReverificationConfig, __experimental_SessionVerificationTypes>
13+
>;
1014
type AuthorizationOptions = {
1115
userId: string | null | undefined;
1216
orgId: string | null | undefined;
@@ -22,34 +26,38 @@ type CheckOrgAuthorization = (
2226

2327
type CheckStepUpAuthorization = (
2428
params: {
25-
__experimental_assurance?: {
26-
level: __experimental_SessionVerificationLevel;
27-
maxAge: __experimental_SessionVerificationMaxAge;
28-
};
29+
__experimental_reverification?: __experimental_ReverificationConfig;
2930
},
3031
{ __experimental_factorVerificationAge }: AuthorizationOptions,
3132
) => boolean | null;
3233

33-
const MAX_AGE_TO_MINUTES: MaxAgeMap = {
34-
'A1.10min': 10,
35-
'A2.1hr': 60,
36-
'A3.4hr': 240, //4 * 60
37-
'A4.1day': 1440, //24 * 60,
38-
'A5.1wk': 10080, //7 * 24 * 60,
34+
const TYPES_TO_OBJECTS: TypesToConfig = {
35+
veryStrict: {
36+
afterMinutes: 10,
37+
level: 'multiFactor',
38+
},
39+
strict: {
40+
afterMinutes: 10,
41+
level: 'secondFactor',
42+
},
43+
moderate: {
44+
afterMinutes: 60,
45+
level: 'secondFactor',
46+
},
47+
lax: {
48+
afterMinutes: 1_440,
49+
level: 'secondFactor',
50+
},
3951
};
4052

41-
const ALLOWED_MAX_AGES = new Set<__experimental_SessionVerificationMaxAge>(
42-
Object.keys(MAX_AGE_TO_MINUTES) as __experimental_SessionVerificationMaxAge[],
43-
);
44-
const ALLOWED_LEVELS = new Set<__experimental_SessionVerificationLevel>([
45-
'L1.firstFactor',
46-
'L2.secondFactor',
47-
'L3.multiFactor',
48-
]);
53+
const ALLOWED_LEVELS = new Set<__experimental_SessionVerificationLevel>(['firstFactor', 'secondFactor', 'multiFactor']);
54+
55+
const ALLOWED_TYPES = new Set<__experimental_SessionVerificationTypes>(['veryStrict', 'strict', 'moderate', 'lax']);
4956

5057
// Helper functions
51-
const isValidMaxAge = (maxAge: __experimental_SessionVerificationMaxAge) => ALLOWED_MAX_AGES.has(maxAge);
52-
const isValidLevel = (level: __experimental_SessionVerificationLevel) => ALLOWED_LEVELS.has(level);
58+
const isValidMaxAge = (maxAge: any) => typeof maxAge === 'number' && maxAge > 0;
59+
const isValidLevel = (level: any) => ALLOWED_LEVELS.has(level);
60+
const isValidVerificationType = (type: any) => ALLOWED_TYPES.has(type);
5361

5462
/**
5563
* Checks if a user has the required organization-level authorization.
@@ -74,36 +82,55 @@ const checkOrgAuthorization: CheckOrgAuthorization = (params, options) => {
7482
return null;
7583
};
7684

85+
const validateReverificationConfig = (config: __experimental_ReverificationConfig | undefined) => {
86+
const convertConfigToObject = (config: __experimental_ReverificationConfig) => {
87+
if (typeof config === 'string') {
88+
return TYPES_TO_OBJECTS[config];
89+
}
90+
return config;
91+
};
92+
93+
if (typeof config === 'string' && isValidVerificationType(config)) {
94+
return convertConfigToObject.bind(null, config);
95+
}
96+
97+
if (typeof config === 'object' && isValidLevel(config.level) && isValidMaxAge(config.afterMinutes)) {
98+
return convertConfigToObject.bind(null, config);
99+
}
100+
101+
return false;
102+
};
103+
77104
/**
78105
* Evaluates if the user meets step-up authentication requirements.
79106
* Compares the user's factor verification ages against the specified maxAge.
80107
* Handles different verification levels (first factor, second factor, multi-factor).
81108
* @returns null, if requirements or verification data are missing.
82109
*/
83110
const checkStepUpAuthorization: CheckStepUpAuthorization = (params, { __experimental_factorVerificationAge }) => {
84-
if (!params.__experimental_assurance || !__experimental_factorVerificationAge) {
111+
if (!params.__experimental_reverification || !__experimental_factorVerificationAge) {
85112
return null;
86113
}
87-
const { level, maxAge } = params.__experimental_assurance;
88114

89-
if (!isValidLevel(level) || !isValidMaxAge(maxAge)) {
115+
const isValidReverification = validateReverificationConfig(params.__experimental_reverification);
116+
if (!isValidReverification) {
90117
return null;
91118
}
92119

120+
const { level, afterMinutes } = isValidReverification();
93121
const [factor1Age, factor2Age] = __experimental_factorVerificationAge;
94-
const maxAgeInMinutes = MAX_AGE_TO_MINUTES[maxAge];
95122

96123
// -1 indicates the factor group (1fa,2fa) is not enabled
97124
// -1 for 1fa is not a valid scenario, but we need to make sure we handle it properly
98-
const isValidFactor1 = factor1Age !== -1 ? maxAgeInMinutes > factor1Age : null;
99-
const isValidFactor2 = factor2Age !== -1 ? maxAgeInMinutes > factor2Age : null;
125+
const isValidFactor1 = factor1Age !== -1 ? afterMinutes > factor1Age : null;
126+
const isValidFactor2 = factor2Age !== -1 ? afterMinutes > factor2Age : null;
100127

101128
switch (level) {
102-
case 'L1.firstFactor':
129+
case 'firstFactor':
103130
return isValidFactor1;
104-
case 'L2.secondFactor':
131+
case 'secondFactor':
105132
return factor2Age !== -1 ? isValidFactor2 : isValidFactor1;
106-
case 'L3.multiFactor':
133+
case 'multiFactor':
107134
return factor2Age === -1 ? isValidFactor1 : isValidFactor1 && isValidFactor2;
108135
}
109136
};

‎packages/types/src/clerk.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -861,8 +861,8 @@ export type __experimental_UserVerificationProps = RoutingOptions & {
861861

862862
/**
863863
* Defines the steps of the verification flow.
864-
* When `L3.multiFactor` is used, the user will be prompt for a first factor flow followed by a second factor flow.
865-
* @default `'L2.secondFactor'`
864+
* When `multiFactor` is used, the user will be prompt for a first factor flow followed by a second factor flow.
865+
* @default `'secondFactor'`
866866
*/
867867
level?: __experimental_SessionVerificationLevel;
868868

‎packages/types/src/session.ts

+5-10
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ import type {
1616
} from './organizationMembership';
1717
import type { ClerkResource } from './resource';
1818
import type {
19+
__experimental_ReverificationConfig,
1920
__experimental_SessionVerificationLevel,
20-
__experimental_SessionVerificationMaxAge,
21+
__experimental_SessionVerificationMaxAgeMinutes,
2122
__experimental_SessionVerificationResource,
2223
} from './sessionVerification';
2324
import type { TokenResource } from './token';
@@ -39,10 +40,7 @@ export type CheckAuthorizationParamsWithCustomPermissions = (
3940
}
4041
| { role?: never; permission?: never }
4142
) & {
42-
__experimental_assurance?: {
43-
level: __experimental_SessionVerificationLevel;
44-
maxAge: __experimental_SessionVerificationMaxAge;
45-
};
43+
__experimental_reverification?: __experimental_ReverificationConfig;
4644
};
4745

4846
export type CheckAuthorization = CheckAuthorizationFn<CheckAuthorizationParams>;
@@ -61,10 +59,7 @@ type CheckAuthorizationParams = (
6159
permission?: never;
6260
}
6361
) & {
64-
__experimental_assurance?: {
65-
level: __experimental_SessionVerificationLevel;
66-
maxAge: __experimental_SessionVerificationMaxAge;
67-
};
62+
__experimental_reverification?: __experimental_ReverificationConfig;
6863
};
6964

7065
export interface SessionResource extends ClerkResource {
@@ -160,7 +155,7 @@ export type GetToken = (options?: GetTokenOptions) => Promise<string | null>;
160155

161156
export type __experimental_SessionVerifyCreateParams = {
162157
level: __experimental_SessionVerificationLevel;
163-
maxAge: __experimental_SessionVerificationMaxAge;
158+
maxAgeMinutes: __experimental_SessionVerificationMaxAgeMinutes;
164159
};
165160

166161
export type __experimental_SessionVerifyPrepareFirstFactorParams = EmailCodeConfig | PhoneCodeConfig;

‎packages/types/src/sessionVerification.ts

+19-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,25 @@ export interface __experimental_SessionVerificationResource extends ClerkResourc
1414
}
1515

1616
export type __experimental_SessionVerificationStatus = 'needs_first_factor' | 'needs_second_factor' | 'complete';
17-
export type __experimental_SessionVerificationLevel = 'L1.firstFactor' | 'L2.secondFactor' | 'L3.multiFactor';
18-
export type __experimental_SessionVerificationMaxAge = 'A1.10min' | 'A2.1hr' | 'A3.4hr' | 'A4.1day' | 'A5.1wk';
17+
18+
export type __experimental_SessionVerificationTypes = 'veryStrict' | 'strict' | 'moderate' | 'lax';
19+
20+
export type __experimental_SessionVerificationConfig =
21+
| __experimental_SessionVerificationTypes
22+
| {
23+
level: __experimental_SessionVerificationLevel;
24+
maxAgeMinutes: __experimental_SessionVerificationMaxAgeMinutes;
25+
};
26+
27+
export type __experimental_ReverificationConfig =
28+
| __experimental_SessionVerificationTypes
29+
| {
30+
level: __experimental_SessionVerificationLevel;
31+
afterMinutes: __experimental_SessionVerificationMaxAgeMinutes;
32+
};
33+
34+
export type __experimental_SessionVerificationLevel = 'firstFactor' | 'secondFactor' | 'multiFactor';
35+
export type __experimental_SessionVerificationMaxAgeMinutes = number;
1936

2037
export type __experimental_SessionVerificationFirstFactor = EmailCodeFactor | PhoneCodeFactor | PasswordFactor;
2138
export type __experimental_SessionVerificationSecondFactor = PhoneCodeFactor | TOTPFactor | BackupCodeFactor;

0 commit comments

Comments
 (0)
Please sign in to comment.