@adminforth/two-factors-auth 3.1.3 → 3.1.5
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 +24 -5
- package/dist/custom/TwoFAModal.vue +24 -5
- package/dist/index.js +25 -14
- package/index.ts +29 -14
- 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 283,
|
|
20
|
-
total size is 282,
|
|
19
|
+
sent 283,900 bytes received 229 bytes 568,258.00 bytes/sec
|
|
20
|
+
total size is 282,994 speedup is 1.00
|
package/custom/TwoFAModal.vue
CHANGED
|
@@ -102,29 +102,47 @@
|
|
|
102
102
|
|
|
103
103
|
const { alert } = useAdminforth();
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
const isAwaiting2FAResult = ref(false);
|
|
106
|
+
let allowAddNewSessions = true;
|
|
107
|
+
const ALLOW_NEW_SESSIONS_PERIOD = 1000;
|
|
106
108
|
const sessionsIdsToResolve = ref<string[]>([]);
|
|
109
|
+
|
|
110
|
+
watch(isAwaiting2FAResult, (awaiting) => {
|
|
111
|
+
if (awaiting) {
|
|
112
|
+
allowAddNewSessions = true;
|
|
113
|
+
setTimeout(() => {
|
|
114
|
+
if (isAwaiting2FAResult.value) {
|
|
115
|
+
allowAddNewSessions = false;
|
|
116
|
+
}
|
|
117
|
+
}, ALLOW_NEW_SESSIONS_PERIOD);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
|
|
107
121
|
watch( props, () => {
|
|
108
122
|
if (props.adminUser) {
|
|
109
123
|
websocket.unsubscribeByPrefix(`/user2fa/`);
|
|
110
124
|
websocket.subscribe(`/user2fa/${props.adminUser.pk}`, async (data: {sessionId: string}) => {
|
|
125
|
+
if (!allowAddNewSessions) {
|
|
126
|
+
alert({message: 'Some process or user tries to add new actions to confirm. Action was blocked', variant: 'warning'});
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
111
129
|
sessionsIdsToResolve.value.push(data.sessionId);
|
|
112
130
|
let confirmationResult;
|
|
113
|
-
if (isAwaiting2FAResult) {
|
|
131
|
+
if (isAwaiting2FAResult.value) {
|
|
114
132
|
return;
|
|
115
133
|
}
|
|
116
134
|
try {
|
|
117
|
-
isAwaiting2FAResult = true;
|
|
135
|
+
isAwaiting2FAResult.value = true;
|
|
118
136
|
confirmationResult = await window.adminforthTwoFaModal.get2FaConfirmationResult();
|
|
119
137
|
} catch (error) {
|
|
120
138
|
console.error('Error during 2FA confirmation:', error);
|
|
121
139
|
}
|
|
122
|
-
isAwaiting2FAResult = false;
|
|
140
|
+
isAwaiting2FAResult.value = false;
|
|
123
141
|
try {
|
|
124
142
|
const response = await callAdminForthApi({
|
|
125
143
|
method: "POST",
|
|
126
144
|
path: "/plugin/passkeys/resolveVerifyAuto",
|
|
127
|
-
body: { confirmationResult,
|
|
145
|
+
body: { confirmationResult, sessionsIds: sessionsIdsToResolve.value }
|
|
128
146
|
});
|
|
129
147
|
if (!response.ok && response.error === 'No session ID or confirmation result'){
|
|
130
148
|
alert({message: 'Verification session finished or cancelled.', variant: 'warning'});
|
|
@@ -137,6 +155,7 @@
|
|
|
137
155
|
} catch (error) {
|
|
138
156
|
console.error('Error resolving automatic 2FA verification:', error);
|
|
139
157
|
}
|
|
158
|
+
allowAddNewSessions = true;
|
|
140
159
|
});
|
|
141
160
|
websocket.subscribe(`/user2fa/${props.adminUser.pk}-resolve`, async (data: {sessionId: string}) => {
|
|
142
161
|
if (sessionsIdsToResolve.value.includes(data.sessionId) && rejectFn && modelShow.value) {
|
|
@@ -102,29 +102,47 @@
|
|
|
102
102
|
|
|
103
103
|
const { alert } = useAdminforth();
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
const isAwaiting2FAResult = ref(false);
|
|
106
|
+
let allowAddNewSessions = true;
|
|
107
|
+
const ALLOW_NEW_SESSIONS_PERIOD = 1000;
|
|
106
108
|
const sessionsIdsToResolve = ref<string[]>([]);
|
|
109
|
+
|
|
110
|
+
watch(isAwaiting2FAResult, (awaiting) => {
|
|
111
|
+
if (awaiting) {
|
|
112
|
+
allowAddNewSessions = true;
|
|
113
|
+
setTimeout(() => {
|
|
114
|
+
if (isAwaiting2FAResult.value) {
|
|
115
|
+
allowAddNewSessions = false;
|
|
116
|
+
}
|
|
117
|
+
}, ALLOW_NEW_SESSIONS_PERIOD);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
|
|
107
121
|
watch( props, () => {
|
|
108
122
|
if (props.adminUser) {
|
|
109
123
|
websocket.unsubscribeByPrefix(`/user2fa/`);
|
|
110
124
|
websocket.subscribe(`/user2fa/${props.adminUser.pk}`, async (data: {sessionId: string}) => {
|
|
125
|
+
if (!allowAddNewSessions) {
|
|
126
|
+
alert({message: 'Some process or user tries to add new actions to confirm. Action was blocked', variant: 'warning'});
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
111
129
|
sessionsIdsToResolve.value.push(data.sessionId);
|
|
112
130
|
let confirmationResult;
|
|
113
|
-
if (isAwaiting2FAResult) {
|
|
131
|
+
if (isAwaiting2FAResult.value) {
|
|
114
132
|
return;
|
|
115
133
|
}
|
|
116
134
|
try {
|
|
117
|
-
isAwaiting2FAResult = true;
|
|
135
|
+
isAwaiting2FAResult.value = true;
|
|
118
136
|
confirmationResult = await window.adminforthTwoFaModal.get2FaConfirmationResult();
|
|
119
137
|
} catch (error) {
|
|
120
138
|
console.error('Error during 2FA confirmation:', error);
|
|
121
139
|
}
|
|
122
|
-
isAwaiting2FAResult = false;
|
|
140
|
+
isAwaiting2FAResult.value = false;
|
|
123
141
|
try {
|
|
124
142
|
const response = await callAdminForthApi({
|
|
125
143
|
method: "POST",
|
|
126
144
|
path: "/plugin/passkeys/resolveVerifyAuto",
|
|
127
|
-
body: { confirmationResult,
|
|
145
|
+
body: { confirmationResult, sessionsIds: sessionsIdsToResolve.value }
|
|
128
146
|
});
|
|
129
147
|
if (!response.ok && response.error === 'No session ID or confirmation result'){
|
|
130
148
|
alert({message: 'Verification session finished or cancelled.', variant: 'warning'});
|
|
@@ -137,6 +155,7 @@
|
|
|
137
155
|
} catch (error) {
|
|
138
156
|
console.error('Error resolving automatic 2FA verification:', error);
|
|
139
157
|
}
|
|
158
|
+
allowAddNewSessions = true;
|
|
140
159
|
});
|
|
141
160
|
websocket.subscribe(`/user2fa/${props.adminUser.pk}-resolve`, async (data: {sessionId: string}) => {
|
|
142
161
|
if (sessionsIdsToResolve.value.includes(data.sessionId) && rejectFn && modelShow.value) {
|
package/dist/index.js
CHANGED
|
@@ -149,9 +149,10 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
|
|
|
149
149
|
verifyAuto(adminUser) {
|
|
150
150
|
return __awaiter(this, void 0, void 0, function* () {
|
|
151
151
|
const sessionId = crypto.randomUUID();
|
|
152
|
-
this.adminforth.
|
|
153
|
-
|
|
154
|
-
this.
|
|
152
|
+
const jwt = this.adminforth.auth.issueJWT({ sessionId, adminUserPk: adminUser.pk }, 'auto2FA', '5m');
|
|
153
|
+
this.adminforth.websocket.publish(`/user2fa/${adminUser.pk}`, { sessionId: jwt });
|
|
154
|
+
const result = yield this.waitForResponse(jwt);
|
|
155
|
+
this.adminforth.websocket.publish(`/user2fa/${adminUser.pk}-resolve`, { sessionId: jwt });
|
|
155
156
|
return result;
|
|
156
157
|
});
|
|
157
158
|
}
|
|
@@ -1019,15 +1020,26 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
|
|
|
1019
1020
|
path: `/plugin/passkeys/resolveVerifyAuto`,
|
|
1020
1021
|
noAuth: false,
|
|
1021
1022
|
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response, cookies, headers }) {
|
|
1022
|
-
const sessionId = body === null || body === void 0 ? void 0 : body.sessionId;
|
|
1023
1023
|
const sessionsIds = body === null || body === void 0 ? void 0 : body.sessionsIds;
|
|
1024
1024
|
const confirmationResult = body === null || body === void 0 ? void 0 : body.confirmationResult;
|
|
1025
|
-
const idsToResolve = sessionsIds
|
|
1026
|
-
|
|
1025
|
+
const idsToResolve = sessionsIds;
|
|
1026
|
+
const resolveAllIdsAsFailed = (message) => {
|
|
1027
1027
|
for (const id of idsToResolve) {
|
|
1028
|
-
this.resolveResponse(id, { ok: false, error:
|
|
1028
|
+
this.resolveResponse(id, { ok: false, error: message });
|
|
1029
|
+
}
|
|
1030
|
+
return { ok: false, error: message };
|
|
1031
|
+
};
|
|
1032
|
+
if (!(sessionsIds) || !confirmationResult) {
|
|
1033
|
+
return (resolveAllIdsAsFailed('Confirmation window was closed or did not return required data'));
|
|
1034
|
+
}
|
|
1035
|
+
for (const id of idsToResolve) {
|
|
1036
|
+
const validationResult = yield this.adminforth.auth.verify(id, 'auto2FA', false);
|
|
1037
|
+
if (!validationResult) {
|
|
1038
|
+
return (resolveAllIdsAsFailed('Invalid session ID or confirmation result'));
|
|
1039
|
+
}
|
|
1040
|
+
if (validationResult.adminUserPk !== adminUser.pk) {
|
|
1041
|
+
return (resolveAllIdsAsFailed('Session does not belong to the authenticated user'));
|
|
1029
1042
|
}
|
|
1030
|
-
return { ok: false, error: 'No session ID or confirmation result' };
|
|
1031
1043
|
}
|
|
1032
1044
|
const verificationResult = yield this.verify(confirmationResult, {
|
|
1033
1045
|
adminUser: adminUser,
|
|
@@ -1039,15 +1051,14 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
|
|
|
1039
1051
|
}
|
|
1040
1052
|
});
|
|
1041
1053
|
if (!verificationResult || !('ok' in verificationResult)) {
|
|
1054
|
+
return (resolveAllIdsAsFailed('Verification failed'));
|
|
1055
|
+
}
|
|
1056
|
+
if ('ok' in verificationResult && verificationResult.ok) {
|
|
1042
1057
|
for (const id of idsToResolve) {
|
|
1043
|
-
this.resolveResponse(id, { ok:
|
|
1058
|
+
this.resolveResponse(id, { ok: true, passkeyConfirmed: verificationResult });
|
|
1044
1059
|
}
|
|
1045
|
-
return { ok:
|
|
1046
|
-
}
|
|
1047
|
-
for (const id of idsToResolve) {
|
|
1048
|
-
this.resolveResponse(id, { ok: true, passkeyConfirmed: verificationResult });
|
|
1060
|
+
return { ok: true };
|
|
1049
1061
|
}
|
|
1050
|
-
return { ok: true };
|
|
1051
1062
|
})
|
|
1052
1063
|
});
|
|
1053
1064
|
}
|
package/index.ts
CHANGED
|
@@ -159,9 +159,10 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
|
|
|
159
159
|
|
|
160
160
|
public async verifyAuto(adminUser: AdminUser) {
|
|
161
161
|
const sessionId = crypto.randomUUID();
|
|
162
|
-
this.adminforth.
|
|
163
|
-
|
|
164
|
-
this.
|
|
162
|
+
const jwt = this.adminforth.auth.issueJWT({sessionId, adminUserPk: adminUser.pk}, 'auto2FA', '5m');
|
|
163
|
+
this.adminforth.websocket.publish(`/user2fa/${adminUser.pk}`, { sessionId: jwt });
|
|
164
|
+
const result = await this.waitForResponse(jwt);
|
|
165
|
+
this.adminforth.websocket.publish(`/user2fa/${adminUser.pk}-resolve`, { sessionId: jwt });
|
|
165
166
|
return result;
|
|
166
167
|
}
|
|
167
168
|
|
|
@@ -1080,16 +1081,31 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
|
|
|
1080
1081
|
path: `/plugin/passkeys/resolveVerifyAuto`,
|
|
1081
1082
|
noAuth: false,
|
|
1082
1083
|
handler: async ({ body, adminUser, response, cookies, headers }) => {
|
|
1083
|
-
const sessionId = body?.sessionId;
|
|
1084
1084
|
const sessionsIds = body?.sessionsIds;
|
|
1085
1085
|
const confirmationResult = body?.confirmationResult;
|
|
1086
|
-
const idsToResolve = sessionsIds
|
|
1087
|
-
|
|
1086
|
+
const idsToResolve = sessionsIds;
|
|
1087
|
+
|
|
1088
|
+
const resolveAllIdsAsFailed = (message) => {
|
|
1088
1089
|
for (const id of idsToResolve) {
|
|
1089
|
-
this.resolveResponse(id, { ok: false, error:
|
|
1090
|
+
this.resolveResponse(id, { ok: false, error: message });
|
|
1091
|
+
}
|
|
1092
|
+
return { ok: false, error: message };
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
if (!(sessionsIds) || !confirmationResult) {
|
|
1096
|
+
return(resolveAllIdsAsFailed('Confirmation window was closed or did not return required data'));
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
for (const id of idsToResolve) {
|
|
1100
|
+
const validationResult = await this.adminforth.auth.verify(id, 'auto2FA', false);
|
|
1101
|
+
if (!validationResult) {
|
|
1102
|
+
return(resolveAllIdsAsFailed('Invalid session ID or confirmation result'));
|
|
1103
|
+
}
|
|
1104
|
+
if (validationResult.adminUserPk !== adminUser.pk) {
|
|
1105
|
+
return(resolveAllIdsAsFailed('Session does not belong to the authenticated user'));
|
|
1090
1106
|
}
|
|
1091
|
-
return { ok: false, error: 'No session ID or confirmation result' };
|
|
1092
1107
|
}
|
|
1108
|
+
|
|
1093
1109
|
const verificationResult = await this.verify(confirmationResult, {
|
|
1094
1110
|
adminUser: adminUser,
|
|
1095
1111
|
userPk: adminUser.pk,
|
|
@@ -1100,15 +1116,14 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
|
|
|
1100
1116
|
} as HttpExtra
|
|
1101
1117
|
});
|
|
1102
1118
|
if ( !verificationResult || !('ok' in verificationResult) ) {
|
|
1119
|
+
return(resolveAllIdsAsFailed('Verification failed'));
|
|
1120
|
+
}
|
|
1121
|
+
if ('ok' in verificationResult && verificationResult.ok){
|
|
1103
1122
|
for (const id of idsToResolve) {
|
|
1104
|
-
this.resolveResponse(id, { ok:
|
|
1123
|
+
this.resolveResponse(id, { ok: true, passkeyConfirmed: verificationResult });
|
|
1105
1124
|
}
|
|
1106
|
-
return { ok:
|
|
1125
|
+
return { ok: true };
|
|
1107
1126
|
}
|
|
1108
|
-
for (const id of idsToResolve) {
|
|
1109
|
-
this.resolveResponse(id, { ok: true, passkeyConfirmed: verificationResult });
|
|
1110
|
-
}
|
|
1111
|
-
return { ok: true };
|
|
1112
1127
|
}
|
|
1113
1128
|
});
|
|
1114
1129
|
}
|