@adminforth/two-factors-auth 3.1.1 → 3.1.3
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/build.log +2 -2
- package/custom/TwoFAModal.vue +14 -6
- package/dist/custom/TwoFAModal.vue +14 -6
- package/dist/index.js +22 -8
- package/index.ts +22 -8
- package/package.json +1 -1
package/build.log
CHANGED
|
@@ -16,5 +16,5 @@ custom/pnpm-lock.yaml
|
|
|
16
16
|
custom/tsconfig.json
|
|
17
17
|
custom/utils.js
|
|
18
18
|
|
|
19
|
-
sent
|
|
20
|
-
total size is
|
|
19
|
+
sent 283,319 bytes received 229 bytes 567,096.00 bytes/sec
|
|
20
|
+
total size is 282,425 speedup is 1.00
|
package/custom/TwoFAModal.vue
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
<div v-if="modalMode === 'totp'" class="af-two-factor-modal-totp flex flex-col items-center relative bg-white dark:bg-gray-700 rounded-lg shadow p-6 w-full max-w-md">
|
|
5
5
|
<div id="mfaCode-label" class="mb-4 text-gray-700 dark:text-gray-100 text-center">
|
|
6
6
|
<p> {{ customDialogTitle }} </p>
|
|
7
|
+
<p class="text-red-500 font-semibold text-xl" v-if="sessionsIdsToResolve.length > 1"> You are confirming {{ sessionsIdsToResolve.length }} actions</p>
|
|
7
8
|
<p>{{ $t('Please enter your authenticator code') }}</p>
|
|
8
9
|
</div>
|
|
9
10
|
|
|
@@ -51,6 +52,7 @@
|
|
|
51
52
|
<p class="text-4xl font-semibold mb-4 text:gray-900 dark:text-gray-200 ">{{$t('Passkey')}}</p>
|
|
52
53
|
<div class="mb-2 max-w-[300px] text:gray-900 dark:text-gray-200">
|
|
53
54
|
<p class="mb-2">{{customDialogTitle}} </p>
|
|
55
|
+
<p class="text-red-500 font-semibold text-xl text-center mb-12" v-if="sessionsIdsToResolve.length > 1"> You are confirming {{ sessionsIdsToResolve.length }} actions</p>
|
|
54
56
|
<p>{{$t('Authenticate yourself using the button below')}}</p>
|
|
55
57
|
</div>
|
|
56
58
|
<Button @click="usePasskeyButtonClick" :disabled="isFetchingPasskey" :loader="isFetchingPasskey" class="w-full mx-16">
|
|
@@ -100,23 +102,29 @@
|
|
|
100
102
|
|
|
101
103
|
const { alert } = useAdminforth();
|
|
102
104
|
|
|
103
|
-
let
|
|
105
|
+
let isAwaiting2FAResult = false;
|
|
106
|
+
const sessionsIdsToResolve = ref<string[]>([]);
|
|
104
107
|
watch( props, () => {
|
|
105
108
|
if (props.adminUser) {
|
|
106
109
|
websocket.unsubscribeByPrefix(`/user2fa/`);
|
|
107
110
|
websocket.subscribe(`/user2fa/${props.adminUser.pk}`, async (data: {sessionId: string}) => {
|
|
108
|
-
|
|
111
|
+
sessionsIdsToResolve.value.push(data.sessionId);
|
|
109
112
|
let confirmationResult;
|
|
113
|
+
if (isAwaiting2FAResult) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
110
116
|
try {
|
|
117
|
+
isAwaiting2FAResult = true;
|
|
111
118
|
confirmationResult = await window.adminforthTwoFaModal.get2FaConfirmationResult();
|
|
112
119
|
} catch (error) {
|
|
113
120
|
console.error('Error during 2FA confirmation:', error);
|
|
114
121
|
}
|
|
122
|
+
isAwaiting2FAResult = false;
|
|
115
123
|
try {
|
|
116
124
|
const response = await callAdminForthApi({
|
|
117
125
|
method: "POST",
|
|
118
126
|
path: "/plugin/passkeys/resolveVerifyAuto",
|
|
119
|
-
body: { confirmationResult, sessionId: data.sessionId }
|
|
127
|
+
body: { confirmationResult, sessionId: data.sessionId, sessionsIds: sessionsIdsToResolve.value }
|
|
120
128
|
});
|
|
121
129
|
if (!response.ok && response.error === 'No session ID or confirmation result'){
|
|
122
130
|
alert({message: 'Verification session finished or cancelled.', variant: 'warning'});
|
|
@@ -125,15 +133,15 @@
|
|
|
125
133
|
} else if (response.ok) {
|
|
126
134
|
alert({message: 'Verification successful', variant: 'success'});
|
|
127
135
|
}
|
|
136
|
+
sessionsIdsToResolve.value = [];
|
|
128
137
|
} catch (error) {
|
|
129
138
|
console.error('Error resolving automatic 2FA verification:', error);
|
|
130
139
|
}
|
|
131
|
-
currentSessionId = null;
|
|
132
140
|
});
|
|
133
141
|
websocket.subscribe(`/user2fa/${props.adminUser.pk}-resolve`, async (data: {sessionId: string}) => {
|
|
134
|
-
if (
|
|
142
|
+
if (sessionsIdsToResolve.value.includes(data.sessionId) && rejectFn && modelShow.value) {
|
|
135
143
|
onCancel();
|
|
136
|
-
|
|
144
|
+
sessionsIdsToResolve.value = sessionsIdsToResolve.value.filter(id => id !== data.sessionId);
|
|
137
145
|
}
|
|
138
146
|
});
|
|
139
147
|
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
<div v-if="modalMode === 'totp'" class="af-two-factor-modal-totp flex flex-col items-center relative bg-white dark:bg-gray-700 rounded-lg shadow p-6 w-full max-w-md">
|
|
5
5
|
<div id="mfaCode-label" class="mb-4 text-gray-700 dark:text-gray-100 text-center">
|
|
6
6
|
<p> {{ customDialogTitle }} </p>
|
|
7
|
+
<p class="text-red-500 font-semibold text-xl" v-if="sessionsIdsToResolve.length > 1"> You are confirming {{ sessionsIdsToResolve.length }} actions</p>
|
|
7
8
|
<p>{{ $t('Please enter your authenticator code') }}</p>
|
|
8
9
|
</div>
|
|
9
10
|
|
|
@@ -51,6 +52,7 @@
|
|
|
51
52
|
<p class="text-4xl font-semibold mb-4 text:gray-900 dark:text-gray-200 ">{{$t('Passkey')}}</p>
|
|
52
53
|
<div class="mb-2 max-w-[300px] text:gray-900 dark:text-gray-200">
|
|
53
54
|
<p class="mb-2">{{customDialogTitle}} </p>
|
|
55
|
+
<p class="text-red-500 font-semibold text-xl text-center mb-12" v-if="sessionsIdsToResolve.length > 1"> You are confirming {{ sessionsIdsToResolve.length }} actions</p>
|
|
54
56
|
<p>{{$t('Authenticate yourself using the button below')}}</p>
|
|
55
57
|
</div>
|
|
56
58
|
<Button @click="usePasskeyButtonClick" :disabled="isFetchingPasskey" :loader="isFetchingPasskey" class="w-full mx-16">
|
|
@@ -100,23 +102,29 @@
|
|
|
100
102
|
|
|
101
103
|
const { alert } = useAdminforth();
|
|
102
104
|
|
|
103
|
-
let
|
|
105
|
+
let isAwaiting2FAResult = false;
|
|
106
|
+
const sessionsIdsToResolve = ref<string[]>([]);
|
|
104
107
|
watch( props, () => {
|
|
105
108
|
if (props.adminUser) {
|
|
106
109
|
websocket.unsubscribeByPrefix(`/user2fa/`);
|
|
107
110
|
websocket.subscribe(`/user2fa/${props.adminUser.pk}`, async (data: {sessionId: string}) => {
|
|
108
|
-
|
|
111
|
+
sessionsIdsToResolve.value.push(data.sessionId);
|
|
109
112
|
let confirmationResult;
|
|
113
|
+
if (isAwaiting2FAResult) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
110
116
|
try {
|
|
117
|
+
isAwaiting2FAResult = true;
|
|
111
118
|
confirmationResult = await window.adminforthTwoFaModal.get2FaConfirmationResult();
|
|
112
119
|
} catch (error) {
|
|
113
120
|
console.error('Error during 2FA confirmation:', error);
|
|
114
121
|
}
|
|
122
|
+
isAwaiting2FAResult = false;
|
|
115
123
|
try {
|
|
116
124
|
const response = await callAdminForthApi({
|
|
117
125
|
method: "POST",
|
|
118
126
|
path: "/plugin/passkeys/resolveVerifyAuto",
|
|
119
|
-
body: { confirmationResult, sessionId: data.sessionId }
|
|
127
|
+
body: { confirmationResult, sessionId: data.sessionId, sessionsIds: sessionsIdsToResolve.value }
|
|
120
128
|
});
|
|
121
129
|
if (!response.ok && response.error === 'No session ID or confirmation result'){
|
|
122
130
|
alert({message: 'Verification session finished or cancelled.', variant: 'warning'});
|
|
@@ -125,15 +133,15 @@
|
|
|
125
133
|
} else if (response.ok) {
|
|
126
134
|
alert({message: 'Verification successful', variant: 'success'});
|
|
127
135
|
}
|
|
136
|
+
sessionsIdsToResolve.value = [];
|
|
128
137
|
} catch (error) {
|
|
129
138
|
console.error('Error resolving automatic 2FA verification:', error);
|
|
130
139
|
}
|
|
131
|
-
currentSessionId = null;
|
|
132
140
|
});
|
|
133
141
|
websocket.subscribe(`/user2fa/${props.adminUser.pk}-resolve`, async (data: {sessionId: string}) => {
|
|
134
|
-
if (
|
|
142
|
+
if (sessionsIdsToResolve.value.includes(data.sessionId) && rejectFn && modelShow.value) {
|
|
135
143
|
onCancel();
|
|
136
|
-
|
|
144
|
+
sessionsIdsToResolve.value = sessionsIdsToResolve.value.filter(id => id !== data.sessionId);
|
|
137
145
|
}
|
|
138
146
|
});
|
|
139
147
|
}
|
package/dist/index.js
CHANGED
|
@@ -717,7 +717,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
|
|
|
717
717
|
method: 'POST',
|
|
718
718
|
path: `/plugin/passkeys/registerPasskeyRequest`,
|
|
719
719
|
noAuth: false,
|
|
720
|
-
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response, cookies }) {
|
|
720
|
+
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response, cookies, headers }) {
|
|
721
721
|
var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
722
722
|
const mode = body === null || body === void 0 ? void 0 : body.mode;
|
|
723
723
|
const confirmationResult = body === null || body === void 0 ? void 0 : body.confirmationResult;
|
|
@@ -725,7 +725,10 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
|
|
|
725
725
|
adminUser: adminUser,
|
|
726
726
|
userPk: adminUser.pk,
|
|
727
727
|
cookies: cookies,
|
|
728
|
-
response: response
|
|
728
|
+
response: response,
|
|
729
|
+
extra: {
|
|
730
|
+
headers,
|
|
731
|
+
}
|
|
729
732
|
});
|
|
730
733
|
if (!verificationResult || !('ok' in verificationResult)) {
|
|
731
734
|
return { ok: false, error: 'Verification failed' };
|
|
@@ -1015,24 +1018,35 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
|
|
|
1015
1018
|
method: 'POST',
|
|
1016
1019
|
path: `/plugin/passkeys/resolveVerifyAuto`,
|
|
1017
1020
|
noAuth: false,
|
|
1018
|
-
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response, cookies }) {
|
|
1021
|
+
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response, cookies, headers }) {
|
|
1019
1022
|
const sessionId = body === null || body === void 0 ? void 0 : body.sessionId;
|
|
1023
|
+
const sessionsIds = body === null || body === void 0 ? void 0 : body.sessionsIds;
|
|
1020
1024
|
const confirmationResult = body === null || body === void 0 ? void 0 : body.confirmationResult;
|
|
1021
|
-
|
|
1022
|
-
|
|
1025
|
+
const idsToResolve = sessionsIds && Array.isArray(sessionsIds) ? sessionsIds : [sessionId];
|
|
1026
|
+
if (!(sessionId || sessionsIds) || !confirmationResult) {
|
|
1027
|
+
for (const id of idsToResolve) {
|
|
1028
|
+
this.resolveResponse(id, { ok: false, error: 'No session ID or confirmation result' });
|
|
1029
|
+
}
|
|
1023
1030
|
return { ok: false, error: 'No session ID or confirmation result' };
|
|
1024
1031
|
}
|
|
1025
1032
|
const verificationResult = yield this.verify(confirmationResult, {
|
|
1026
1033
|
adminUser: adminUser,
|
|
1027
1034
|
userPk: adminUser.pk,
|
|
1028
1035
|
cookies: cookies,
|
|
1029
|
-
response: response
|
|
1036
|
+
response: response,
|
|
1037
|
+
extra: {
|
|
1038
|
+
headers: headers,
|
|
1039
|
+
}
|
|
1030
1040
|
});
|
|
1031
1041
|
if (!verificationResult || !('ok' in verificationResult)) {
|
|
1032
|
-
|
|
1042
|
+
for (const id of idsToResolve) {
|
|
1043
|
+
this.resolveResponse(id, { ok: false, error: 'Verification failed' });
|
|
1044
|
+
}
|
|
1033
1045
|
return { ok: false, error: 'Verification failed' };
|
|
1034
1046
|
}
|
|
1035
|
-
|
|
1047
|
+
for (const id of idsToResolve) {
|
|
1048
|
+
this.resolveResponse(id, { ok: true, passkeyConfirmed: verificationResult });
|
|
1049
|
+
}
|
|
1036
1050
|
return { ok: true };
|
|
1037
1051
|
})
|
|
1038
1052
|
});
|
package/index.ts
CHANGED
|
@@ -777,7 +777,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
|
|
|
777
777
|
method: 'POST',
|
|
778
778
|
path: `/plugin/passkeys/registerPasskeyRequest`,
|
|
779
779
|
noAuth: false,
|
|
780
|
-
handler: async ({ body, adminUser, response, cookies }) => {
|
|
780
|
+
handler: async ({ body, adminUser, response, cookies, headers }) => {
|
|
781
781
|
const mode = body?.mode;
|
|
782
782
|
|
|
783
783
|
const confirmationResult = body?.confirmationResult;
|
|
@@ -785,7 +785,10 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
|
|
|
785
785
|
adminUser: adminUser,
|
|
786
786
|
userPk: adminUser.pk,
|
|
787
787
|
cookies: cookies,
|
|
788
|
-
response: response
|
|
788
|
+
response: response,
|
|
789
|
+
extra: {
|
|
790
|
+
headers,
|
|
791
|
+
} as HttpExtra
|
|
789
792
|
});
|
|
790
793
|
if ( !verificationResult || !('ok' in verificationResult) ) {
|
|
791
794
|
return { ok: false, error: 'Verification failed' };
|
|
@@ -1076,24 +1079,35 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
|
|
|
1076
1079
|
method: 'POST',
|
|
1077
1080
|
path: `/plugin/passkeys/resolveVerifyAuto`,
|
|
1078
1081
|
noAuth: false,
|
|
1079
|
-
handler: async ({ body, adminUser, response, cookies }) => {
|
|
1082
|
+
handler: async ({ body, adminUser, response, cookies, headers }) => {
|
|
1080
1083
|
const sessionId = body?.sessionId;
|
|
1084
|
+
const sessionsIds = body?.sessionsIds;
|
|
1081
1085
|
const confirmationResult = body?.confirmationResult;
|
|
1082
|
-
|
|
1083
|
-
|
|
1086
|
+
const idsToResolve = sessionsIds && Array.isArray(sessionsIds) ? sessionsIds : [sessionId];
|
|
1087
|
+
if (!(sessionId || sessionsIds) || !confirmationResult) {
|
|
1088
|
+
for (const id of idsToResolve) {
|
|
1089
|
+
this.resolveResponse(id, { ok: false, error: 'No session ID or confirmation result' });
|
|
1090
|
+
}
|
|
1084
1091
|
return { ok: false, error: 'No session ID or confirmation result' };
|
|
1085
1092
|
}
|
|
1086
1093
|
const verificationResult = await this.verify(confirmationResult, {
|
|
1087
1094
|
adminUser: adminUser,
|
|
1088
1095
|
userPk: adminUser.pk,
|
|
1089
1096
|
cookies: cookies,
|
|
1090
|
-
response: response
|
|
1097
|
+
response: response,
|
|
1098
|
+
extra: {
|
|
1099
|
+
headers: headers,
|
|
1100
|
+
} as HttpExtra
|
|
1091
1101
|
});
|
|
1092
1102
|
if ( !verificationResult || !('ok' in verificationResult) ) {
|
|
1093
|
-
|
|
1103
|
+
for (const id of idsToResolve) {
|
|
1104
|
+
this.resolveResponse(id, { ok: false, error: 'Verification failed' });
|
|
1105
|
+
}
|
|
1094
1106
|
return { ok: false, error: 'Verification failed' };
|
|
1095
1107
|
}
|
|
1096
|
-
|
|
1108
|
+
for (const id of idsToResolve) {
|
|
1109
|
+
this.resolveResponse(id, { ok: true, passkeyConfirmed: verificationResult });
|
|
1110
|
+
}
|
|
1097
1111
|
return { ok: true };
|
|
1098
1112
|
}
|
|
1099
1113
|
});
|