@adminforth/two-factors-auth 2.9.9 → 2.9.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +46 -1
- package/index.ts +48 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -20,6 +20,31 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
|
|
|
20
20
|
instanceUniqueRepresentation(pluginOptions) {
|
|
21
21
|
return `single`;
|
|
22
22
|
}
|
|
23
|
+
checkIfSkipSetupAllowSkipVerify(adminUser) {
|
|
24
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
25
|
+
if (this.options.usersFilterToAllowSkipSetup) {
|
|
26
|
+
const res = yield this.options.usersFilterToAllowSkipSetup(adminUser); // recieve result of usersFilterToAllowSkipSetup
|
|
27
|
+
if (res === false) { // if false, user is not allowed to skip anyway, so doesn't matter if they have 2FA set up or not
|
|
28
|
+
return { skipAllowed: false };
|
|
29
|
+
}
|
|
30
|
+
//recieve user's record
|
|
31
|
+
const usersResource = this.adminforth.config.resources.find(r => r.resourceId === this.adminforth.config.auth.usersResourceId);
|
|
32
|
+
const usersPrimaryKeyColumn = usersResource.columns.find((col) => col.primaryKey);
|
|
33
|
+
const userPkFieldName = usersPrimaryKeyColumn.name;
|
|
34
|
+
const userRecord = yield this.adminforth.resource(this.adminforth.config.auth.usersResourceId).get([Filters.EQ(userPkFieldName, adminUser.pk)]);
|
|
35
|
+
//check if user has 2FA set up
|
|
36
|
+
const users2FASecret = userRecord[this.options.twoFaSecretFieldName];
|
|
37
|
+
//check if user has any passkeys registered
|
|
38
|
+
const passkeys = yield this.adminforth.resource(this.options.passkeys.credentialResourceID).list([Filters.EQ(this.options.passkeys.credentialUserIdFieldName, adminUser.dbUser[userPkFieldName])]);
|
|
39
|
+
// If user has either 2FA secret or any passkeys, they cannot skip
|
|
40
|
+
if (users2FASecret || (passkeys && passkeys.length > 0)) {
|
|
41
|
+
return { skipAllowed: false };
|
|
42
|
+
}
|
|
43
|
+
return { skipAllowed: res };
|
|
44
|
+
}
|
|
45
|
+
return { skipAllowed: false };
|
|
46
|
+
});
|
|
47
|
+
}
|
|
23
48
|
verify(confirmationResult, opts) {
|
|
24
49
|
return __awaiter(this, void 0, void 0, function* () {
|
|
25
50
|
var _a, _b, _c, _d;
|
|
@@ -31,6 +56,12 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
|
|
|
31
56
|
return { ok: true };
|
|
32
57
|
}
|
|
33
58
|
}
|
|
59
|
+
if (this.options.usersFilterToAllowSkipSetup) {
|
|
60
|
+
const res = yield this.checkIfSkipSetupAllowSkipVerify(opts.adminUser);
|
|
61
|
+
if (res.skipAllowed === true) {
|
|
62
|
+
return { ok: true };
|
|
63
|
+
}
|
|
64
|
+
}
|
|
34
65
|
if (confirmationResult.mode === "totp") {
|
|
35
66
|
const code = confirmationResult.result;
|
|
36
67
|
const authRes = this.adminforth.config.resources
|
|
@@ -132,7 +163,15 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
|
|
|
132
163
|
}
|
|
133
164
|
credMeta.counter = authenticationInfo.newCounter;
|
|
134
165
|
credMeta.last_used_at = new Date().toISOString();
|
|
135
|
-
|
|
166
|
+
const credResource = this.adminforth.config.resources.find(r => r.resourceId === this.options.passkeys.credentialResourceID);
|
|
167
|
+
const credResourcePKColumn = credResource === null || credResource === void 0 ? void 0 : credResource.columns.find(c => c.primaryKey);
|
|
168
|
+
if (!credResource || !credResourcePKColumn) {
|
|
169
|
+
throw new Error('Credential resource or its primary key is not configured correctly');
|
|
170
|
+
}
|
|
171
|
+
const credResourcePKName = credResourcePKColumn.name;
|
|
172
|
+
yield this.adminforth
|
|
173
|
+
.resource(this.options.passkeys.credentialResourceID)
|
|
174
|
+
.update(cred[credResourcePKName], { [this.options.passkeys.credentialMetaFieldName]: JSON.stringify(credMeta) });
|
|
136
175
|
return { ok: true, passkeyConfirmed: true };
|
|
137
176
|
}
|
|
138
177
|
catch (e) {
|
|
@@ -503,6 +542,12 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
|
|
|
503
542
|
return { skipAllowed: true };
|
|
504
543
|
}
|
|
505
544
|
}
|
|
545
|
+
if (this.options.usersFilterToAllowSkipSetup) {
|
|
546
|
+
const res = yield this.checkIfSkipSetupAllowSkipVerify(adminUser);
|
|
547
|
+
if (res.skipAllowed === true) {
|
|
548
|
+
return { skipAllowed: true };
|
|
549
|
+
}
|
|
550
|
+
}
|
|
506
551
|
return { skipAllowed: false };
|
|
507
552
|
}),
|
|
508
553
|
});
|
package/index.ts
CHANGED
|
@@ -27,6 +27,33 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
|
|
|
27
27
|
return `single`;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
public async checkIfSkipSetupAllowSkipVerify(adminUser: AdminUser): Promise<{ skipAllowed: boolean }> {
|
|
31
|
+
if (this.options.usersFilterToAllowSkipSetup) {
|
|
32
|
+
const res = await this.options.usersFilterToAllowSkipSetup(adminUser); // recieve result of usersFilterToAllowSkipSetup
|
|
33
|
+
if (res === false) { // if false, user is not allowed to skip anyway, so doesn't matter if they have 2FA set up or not
|
|
34
|
+
return { skipAllowed: false };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
//recieve user's record
|
|
38
|
+
const usersResource = this.adminforth.config.resources.find(r => r.resourceId === this.adminforth.config.auth.usersResourceId);
|
|
39
|
+
const usersPrimaryKeyColumn = usersResource.columns.find((col) => col.primaryKey);
|
|
40
|
+
const userPkFieldName = usersPrimaryKeyColumn.name;
|
|
41
|
+
const userRecord = await this.adminforth.resource(this.adminforth.config.auth.usersResourceId).get([Filters.EQ(userPkFieldName, adminUser.pk)])
|
|
42
|
+
|
|
43
|
+
//check if user has 2FA set up
|
|
44
|
+
const users2FASecret = userRecord[this.options.twoFaSecretFieldName];
|
|
45
|
+
//check if user has any passkeys registered
|
|
46
|
+
const passkeys = await this.adminforth.resource(this.options.passkeys.credentialResourceID).list( [Filters.EQ(this.options.passkeys.credentialUserIdFieldName, adminUser.dbUser[userPkFieldName])] );
|
|
47
|
+
|
|
48
|
+
// If user has either 2FA secret or any passkeys, they cannot skip
|
|
49
|
+
if (users2FASecret || (passkeys && passkeys.length > 0)) {
|
|
50
|
+
return { skipAllowed: false };
|
|
51
|
+
}
|
|
52
|
+
return { skipAllowed: res };
|
|
53
|
+
}
|
|
54
|
+
return { skipAllowed: false };
|
|
55
|
+
}
|
|
56
|
+
|
|
30
57
|
public async verify(
|
|
31
58
|
confirmationResult: Record<string, any>,
|
|
32
59
|
opts?: { adminUser?: AdminUser; userPk?: string; cookies?: any }
|
|
@@ -38,6 +65,12 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
|
|
|
38
65
|
return { ok: true };
|
|
39
66
|
}
|
|
40
67
|
}
|
|
68
|
+
if (this.options.usersFilterToAllowSkipSetup) {
|
|
69
|
+
const res = await this.checkIfSkipSetupAllowSkipVerify(opts.adminUser);
|
|
70
|
+
if ( res.skipAllowed === true ) {
|
|
71
|
+
return { ok: true };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
41
74
|
if (confirmationResult.mode === "totp") {
|
|
42
75
|
const code = confirmationResult.result;
|
|
43
76
|
const authRes = this.adminforth.config.resources
|
|
@@ -142,7 +175,15 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
|
|
|
142
175
|
}
|
|
143
176
|
credMeta.counter = authenticationInfo.newCounter;
|
|
144
177
|
credMeta.last_used_at = new Date().toISOString();
|
|
145
|
-
|
|
178
|
+
const credResource = this.adminforth.config.resources.find(r => r.resourceId === this.options.passkeys.credentialResourceID);
|
|
179
|
+
const credResourcePKColumn = credResource?.columns.find(c => c.primaryKey);
|
|
180
|
+
if (!credResource || !credResourcePKColumn) {
|
|
181
|
+
throw new Error('Credential resource or its primary key is not configured correctly');
|
|
182
|
+
}
|
|
183
|
+
const credResourcePKName = credResourcePKColumn.name;
|
|
184
|
+
await this.adminforth
|
|
185
|
+
.resource(this.options.passkeys.credentialResourceID)
|
|
186
|
+
.update(cred[credResourcePKName], { [this.options.passkeys.credentialMetaFieldName]: JSON.stringify(credMeta) });
|
|
146
187
|
return { ok: true, passkeyConfirmed: true };
|
|
147
188
|
} catch (e) {
|
|
148
189
|
return { ok: false, error: 'Error authenticating passkey: ' + e };
|
|
@@ -553,6 +594,12 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
|
|
|
553
594
|
return { skipAllowed: true };
|
|
554
595
|
}
|
|
555
596
|
}
|
|
597
|
+
if ( this.options.usersFilterToAllowSkipSetup ) {
|
|
598
|
+
const res = await this.checkIfSkipSetupAllowSkipVerify(adminUser);
|
|
599
|
+
if ( res.skipAllowed === true ) {
|
|
600
|
+
return { skipAllowed: true };
|
|
601
|
+
}
|
|
602
|
+
}
|
|
556
603
|
return { skipAllowed: false };
|
|
557
604
|
},
|
|
558
605
|
});
|