@adminforth/two-factors-auth 1.0.0

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.
@@ -0,0 +1,301 @@
1
+ {
2
+ "name": "custom",
3
+ "version": "1.0.0",
4
+ "lockfileVersion": 3,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "custom",
9
+ "version": "1.0.0",
10
+ "license": "ISC",
11
+ "dependencies": {
12
+ "@loltech/vue3-2fa-code-input": "^1.1.0",
13
+ "vue3-otp-input": "^0.5.21"
14
+ }
15
+ },
16
+ "node_modules/@babel/helper-string-parser": {
17
+ "version": "7.25.9",
18
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
19
+ "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
20
+ "license": "MIT",
21
+ "engines": {
22
+ "node": ">=6.9.0"
23
+ }
24
+ },
25
+ "node_modules/@babel/helper-validator-identifier": {
26
+ "version": "7.25.9",
27
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
28
+ "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
29
+ "license": "MIT",
30
+ "engines": {
31
+ "node": ">=6.9.0"
32
+ }
33
+ },
34
+ "node_modules/@babel/parser": {
35
+ "version": "7.25.9",
36
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.9.tgz",
37
+ "integrity": "sha512-aI3jjAAO1fh7vY/pBGsn1i9LDbRP43+asrRlkPuTXW5yHXtd1NgTEMudbBoDDxrf1daEEfPJqR+JBMakzrR4Dg==",
38
+ "license": "MIT",
39
+ "dependencies": {
40
+ "@babel/types": "^7.25.9"
41
+ },
42
+ "bin": {
43
+ "parser": "bin/babel-parser.js"
44
+ },
45
+ "engines": {
46
+ "node": ">=6.0.0"
47
+ }
48
+ },
49
+ "node_modules/@babel/types": {
50
+ "version": "7.25.9",
51
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.9.tgz",
52
+ "integrity": "sha512-OwS2CM5KocvQ/k7dFJa8i5bNGJP0hXWfVCfDkqRFP1IreH1JDC7wG6eCYCi0+McbfT8OR/kNqsI0UU0xP9H6PQ==",
53
+ "license": "MIT",
54
+ "dependencies": {
55
+ "@babel/helper-string-parser": "^7.25.9",
56
+ "@babel/helper-validator-identifier": "^7.25.9"
57
+ },
58
+ "engines": {
59
+ "node": ">=6.9.0"
60
+ }
61
+ },
62
+ "node_modules/@jridgewell/sourcemap-codec": {
63
+ "version": "1.5.0",
64
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
65
+ "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
66
+ "license": "MIT"
67
+ },
68
+ "node_modules/@loltech/vue3-2fa-code-input": {
69
+ "version": "1.1.0",
70
+ "resolved": "https://registry.npmjs.org/@loltech/vue3-2fa-code-input/-/vue3-2fa-code-input-1.1.0.tgz",
71
+ "integrity": "sha512-styyoQjsARSeVf6E5qMvYIVkLRrwYtfL8xDl5W+g9wKF8qlr2XGU2gi9maEg0X4Us41kJryXBzfRMUcv5tKIBA=="
72
+ },
73
+ "node_modules/@vue/compiler-core": {
74
+ "version": "3.5.12",
75
+ "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.12.tgz",
76
+ "integrity": "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw==",
77
+ "license": "MIT",
78
+ "dependencies": {
79
+ "@babel/parser": "^7.25.3",
80
+ "@vue/shared": "3.5.12",
81
+ "entities": "^4.5.0",
82
+ "estree-walker": "^2.0.2",
83
+ "source-map-js": "^1.2.0"
84
+ }
85
+ },
86
+ "node_modules/@vue/compiler-dom": {
87
+ "version": "3.5.12",
88
+ "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.12.tgz",
89
+ "integrity": "sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg==",
90
+ "license": "MIT",
91
+ "dependencies": {
92
+ "@vue/compiler-core": "3.5.12",
93
+ "@vue/shared": "3.5.12"
94
+ }
95
+ },
96
+ "node_modules/@vue/compiler-sfc": {
97
+ "version": "3.5.12",
98
+ "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.12.tgz",
99
+ "integrity": "sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw==",
100
+ "license": "MIT",
101
+ "dependencies": {
102
+ "@babel/parser": "^7.25.3",
103
+ "@vue/compiler-core": "3.5.12",
104
+ "@vue/compiler-dom": "3.5.12",
105
+ "@vue/compiler-ssr": "3.5.12",
106
+ "@vue/shared": "3.5.12",
107
+ "estree-walker": "^2.0.2",
108
+ "magic-string": "^0.30.11",
109
+ "postcss": "^8.4.47",
110
+ "source-map-js": "^1.2.0"
111
+ }
112
+ },
113
+ "node_modules/@vue/compiler-ssr": {
114
+ "version": "3.5.12",
115
+ "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.12.tgz",
116
+ "integrity": "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA==",
117
+ "license": "MIT",
118
+ "dependencies": {
119
+ "@vue/compiler-dom": "3.5.12",
120
+ "@vue/shared": "3.5.12"
121
+ }
122
+ },
123
+ "node_modules/@vue/reactivity": {
124
+ "version": "3.5.12",
125
+ "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.12.tgz",
126
+ "integrity": "sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg==",
127
+ "license": "MIT",
128
+ "dependencies": {
129
+ "@vue/shared": "3.5.12"
130
+ }
131
+ },
132
+ "node_modules/@vue/runtime-core": {
133
+ "version": "3.5.12",
134
+ "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.12.tgz",
135
+ "integrity": "sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw==",
136
+ "license": "MIT",
137
+ "dependencies": {
138
+ "@vue/reactivity": "3.5.12",
139
+ "@vue/shared": "3.5.12"
140
+ }
141
+ },
142
+ "node_modules/@vue/runtime-dom": {
143
+ "version": "3.5.12",
144
+ "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.12.tgz",
145
+ "integrity": "sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA==",
146
+ "license": "MIT",
147
+ "dependencies": {
148
+ "@vue/reactivity": "3.5.12",
149
+ "@vue/runtime-core": "3.5.12",
150
+ "@vue/shared": "3.5.12",
151
+ "csstype": "^3.1.3"
152
+ }
153
+ },
154
+ "node_modules/@vue/server-renderer": {
155
+ "version": "3.5.12",
156
+ "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.12.tgz",
157
+ "integrity": "sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg==",
158
+ "license": "MIT",
159
+ "dependencies": {
160
+ "@vue/compiler-ssr": "3.5.12",
161
+ "@vue/shared": "3.5.12"
162
+ },
163
+ "peerDependencies": {
164
+ "vue": "3.5.12"
165
+ }
166
+ },
167
+ "node_modules/@vue/shared": {
168
+ "version": "3.5.12",
169
+ "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.12.tgz",
170
+ "integrity": "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg==",
171
+ "license": "MIT"
172
+ },
173
+ "node_modules/csstype": {
174
+ "version": "3.1.3",
175
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
176
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
177
+ "license": "MIT"
178
+ },
179
+ "node_modules/entities": {
180
+ "version": "4.5.0",
181
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
182
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
183
+ "license": "BSD-2-Clause",
184
+ "engines": {
185
+ "node": ">=0.12"
186
+ },
187
+ "funding": {
188
+ "url": "https://github.com/fb55/entities?sponsor=1"
189
+ }
190
+ },
191
+ "node_modules/estree-walker": {
192
+ "version": "2.0.2",
193
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
194
+ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
195
+ "license": "MIT"
196
+ },
197
+ "node_modules/magic-string": {
198
+ "version": "0.30.12",
199
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz",
200
+ "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==",
201
+ "license": "MIT",
202
+ "dependencies": {
203
+ "@jridgewell/sourcemap-codec": "^1.5.0"
204
+ }
205
+ },
206
+ "node_modules/nanoid": {
207
+ "version": "3.3.7",
208
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
209
+ "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
210
+ "funding": [
211
+ {
212
+ "type": "github",
213
+ "url": "https://github.com/sponsors/ai"
214
+ }
215
+ ],
216
+ "license": "MIT",
217
+ "bin": {
218
+ "nanoid": "bin/nanoid.cjs"
219
+ },
220
+ "engines": {
221
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
222
+ }
223
+ },
224
+ "node_modules/picocolors": {
225
+ "version": "1.1.1",
226
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
227
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
228
+ "license": "ISC"
229
+ },
230
+ "node_modules/postcss": {
231
+ "version": "8.4.47",
232
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz",
233
+ "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
234
+ "funding": [
235
+ {
236
+ "type": "opencollective",
237
+ "url": "https://opencollective.com/postcss/"
238
+ },
239
+ {
240
+ "type": "tidelift",
241
+ "url": "https://tidelift.com/funding/github/npm/postcss"
242
+ },
243
+ {
244
+ "type": "github",
245
+ "url": "https://github.com/sponsors/ai"
246
+ }
247
+ ],
248
+ "license": "MIT",
249
+ "dependencies": {
250
+ "nanoid": "^3.3.7",
251
+ "picocolors": "^1.1.0",
252
+ "source-map-js": "^1.2.1"
253
+ },
254
+ "engines": {
255
+ "node": "^10 || ^12 || >=14"
256
+ }
257
+ },
258
+ "node_modules/source-map-js": {
259
+ "version": "1.2.1",
260
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
261
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
262
+ "license": "BSD-3-Clause",
263
+ "engines": {
264
+ "node": ">=0.10.0"
265
+ }
266
+ },
267
+ "node_modules/vue": {
268
+ "version": "3.5.12",
269
+ "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.12.tgz",
270
+ "integrity": "sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg==",
271
+ "license": "MIT",
272
+ "dependencies": {
273
+ "@vue/compiler-dom": "3.5.12",
274
+ "@vue/compiler-sfc": "3.5.12",
275
+ "@vue/runtime-dom": "3.5.12",
276
+ "@vue/server-renderer": "3.5.12",
277
+ "@vue/shared": "3.5.12"
278
+ },
279
+ "peerDependencies": {
280
+ "typescript": "*"
281
+ },
282
+ "peerDependenciesMeta": {
283
+ "typescript": {
284
+ "optional": true
285
+ }
286
+ }
287
+ },
288
+ "node_modules/vue3-otp-input": {
289
+ "version": "0.5.21",
290
+ "resolved": "https://registry.npmjs.org/vue3-otp-input/-/vue3-otp-input-0.5.21.tgz",
291
+ "integrity": "sha512-dRxmGJqXlU+U5dCijNCyY7ird49+pyfeQspSTqvIp2Xs+VByIluNlTOjgHrftzSdeVZggtx+Ojb8uKiRLaob4Q==",
292
+ "license": "MIT",
293
+ "dependencies": {
294
+ "vue": "^3.4.27"
295
+ },
296
+ "peerDependencies": {
297
+ "vue": "^3.0.*"
298
+ }
299
+ }
300
+ }
301
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "custom",
3
+ "version": "1.0.0",
4
+ "main": "index.js",
5
+ "scripts": {
6
+ "test": "echo \"Error: no test specified\" && exit 1"
7
+ },
8
+ "keywords": [],
9
+ "author": "",
10
+ "license": "ISC",
11
+ "description": "",
12
+ "dependencies": {
13
+ "@loltech/vue3-2fa-code-input": "^1.1.0",
14
+ "vue3-otp-input": "^0.5.21"
15
+ }
16
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "baseUrl": ".", // This should point to your project root
4
+ "paths": {
5
+ "@/*": [
6
+ // "node_modules/adminforth/dist/spa/src/*"
7
+ "../../../spa/src/*"
8
+ ],
9
+ "*": [
10
+ // "node_modules/adminforth/dist/spa/node_modules/*"
11
+ "../../../spa/node_modules/*"
12
+ ],
13
+ "@@/*": [
14
+ // "node_modules/adminforth/dist/spa/src/*"
15
+ "."
16
+ ]
17
+ }
18
+ }
19
+ }
package/dist/index.js ADDED
@@ -0,0 +1,174 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { AdminForthPlugin } from "adminforth";
11
+ import twofactor from 'node-2fa';
12
+ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
13
+ constructor(options) {
14
+ super(options, import.meta.url);
15
+ this.options = options;
16
+ }
17
+ instanceUniqueRepresentation(pluginOptions) {
18
+ return `single`;
19
+ }
20
+ modifyResourceConfig(adminforth, resourceConfig) {
21
+ super.modifyResourceConfig(adminforth, resourceConfig);
22
+ this.adminforth = adminforth;
23
+ this.adminForthAuth = adminforth.auth;
24
+ const customPages = this.adminforth.config.customization.customPages;
25
+ customPages.push({
26
+ path: '/confirm2fa',
27
+ component: { file: this.componentPath('TwoFactorsConfirmation.vue'), meta: { customLayout: true } }
28
+ });
29
+ customPages.push({
30
+ path: '/setup2fa',
31
+ component: { file: this.componentPath('TwoFactorsSetup.vue'), meta: { title: 'Setup 2FA', customLayout: true } }
32
+ });
33
+ this.activate(resourceConfig, adminforth);
34
+ }
35
+ activate(resourceConfig, adminforth) {
36
+ if (!this.options.twoFaSecretFieldName) {
37
+ throw new Error('twoFaSecretFieldName is required');
38
+ }
39
+ if (typeof this.options.twoFaSecretFieldName !== 'string') {
40
+ throw new Error('twoFaSecretFieldName must be a string');
41
+ }
42
+ if (this.options.timeStepWindow === undefined
43
+ || typeof this.options.timeStepWindow !== 'number'
44
+ || this.options.timeStepWindow < 0)
45
+ this.options.timeStepWindow = 1;
46
+ this.authResource = resourceConfig;
47
+ if (!this.authResource.columns.some((col) => col.name === this.options.twoFaSecretFieldName)) {
48
+ throw new Error(`Column ${this.options.twoFaSecretFieldName} not found in ${this.authResource.label}`);
49
+ }
50
+ this.adminforth.config.auth.beforeLoginConfirmation.push((_a) => __awaiter(this, [_a], void 0, function* ({ adminUser, response }) {
51
+ const secret = adminUser.dbUser[this.options.twoFaSecretFieldName];
52
+ const userName = adminUser.dbUser[adminforth.config.auth.usernameField];
53
+ const brandName = adminforth.config.customization.brandName;
54
+ const brandNameSlug = adminforth.config.customization.brandNameSlug;
55
+ const authResource = adminforth.config.resources.find((res) => res.resourceId === adminforth.config.auth.usersResourceId);
56
+ const authPk = authResource.columns.find((col) => col.primaryKey).name;
57
+ const userPk = adminUser.dbUser[authPk];
58
+ let newSecret = null;
59
+ const userNeeds2FA = this.options.usersFilterToApply ? this.options.usersFilterToApply(adminUser) : true;
60
+ if (!userNeeds2FA) {
61
+ return { body: { loginAllowed: true }, ok: true };
62
+ }
63
+ const userCanSkipSetup = this.options.usersFilterToAllowSkipSetup ? this.options.usersFilterToAllowSkipSetup(adminUser) : false;
64
+ if (!secret) {
65
+ const tempSecret = twofactor.generateSecret({ name: brandName, account: userName });
66
+ newSecret = tempSecret.secret;
67
+ }
68
+ else {
69
+ const value = this.adminforth.auth.issueJWT({ userName, issuer: brandName, pk: userPk, userCanSkipSetup }, 'tempTotp', '2h');
70
+ response.setHeader('Set-Cookie', `adminforth_${brandNameSlug}_totpTemporaryJWT=${value}; Path=${this.adminforth.config.baseUrl || '/'}; HttpOnly; SameSite=Strict; max-age=3600; `);
71
+ return {
72
+ body: {
73
+ loginAllowed: false,
74
+ redirectTo: '/confirm2fa',
75
+ },
76
+ ok: true
77
+ };
78
+ }
79
+ const totpTemporaryJWT = this.adminforth.auth.issueJWT({ userName, newSecret, issuer: brandName, pk: userPk, userCanSkipSetup }, 'tempTotp', '2h');
80
+ response.setHeader('Set-Cookie', `adminforth_${brandNameSlug}_totpTemporaryJWT=${totpTemporaryJWT}; Path=${this.adminforth.config.baseUrl || '/'}; HttpOnly; SameSite=Strict; Expires=${new Date(Date.now() + '1h').toUTCString()} `);
81
+ return {
82
+ body: {
83
+ loginAllowed: false,
84
+ redirectTo: secret ? '/confirm2fa' : '/setup2fa',
85
+ },
86
+ ok: true
87
+ };
88
+ }));
89
+ }
90
+ setupEndpoints(server) {
91
+ server.endpoint({
92
+ method: 'POST',
93
+ path: `/plugin/twofa/initSetup`,
94
+ noAuth: true,
95
+ handler: (server) => __awaiter(this, void 0, void 0, function* () {
96
+ var _a;
97
+ const toReturn = { totpJWT: null, status: 'ok', };
98
+ const brandNameSlug = this.adminforth.config.customization.brandNameSlug;
99
+ const totpTemporaryJWT = (_a = server.cookies.find((cookie) => cookie.key === `adminforth_${brandNameSlug}_totpTemporaryJWT`)) === null || _a === void 0 ? void 0 : _a.value;
100
+ if (totpTemporaryJWT) {
101
+ toReturn.totpJWT = totpTemporaryJWT;
102
+ }
103
+ return toReturn;
104
+ })
105
+ });
106
+ server.endpoint({
107
+ method: 'POST',
108
+ path: `/plugin/twofa/confirmSetup`,
109
+ noAuth: true,
110
+ handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response, cookies }) {
111
+ var _b;
112
+ const brandNameSlug = this.adminforth.config.customization.brandNameSlug;
113
+ const totpTemporaryJWT = (_b = cookies.find((cookie) => cookie.key === `adminforth_${brandNameSlug}_totpTemporaryJWT`)) === null || _b === void 0 ? void 0 : _b.value;
114
+ const decoded = yield this.adminforth.auth.verify(totpTemporaryJWT, 'tempTotp');
115
+ if (!decoded)
116
+ return { status: 'error', message: 'Invalid token' };
117
+ if (decoded.newSecret) {
118
+ const verified = body.skip && decoded.userCanSkipSetup ? true : twofactor.verifyToken(decoded.newSecret, body.code, this.options.timeStepWindow);
119
+ if (verified) {
120
+ this.connectors = this.adminforth.connectors;
121
+ if (!body.skip) {
122
+ const connector = this.connectors[this.authResource.dataSource];
123
+ yield connector.updateRecord({ resource: this.authResource, recordId: decoded.pk, newValues: { [this.options.twoFaSecretFieldName]: decoded.newSecret } });
124
+ }
125
+ this.adminforth.auth.removeCustomCookie({ response, name: 'totpTemporaryJWT' });
126
+ this.adminforth.auth.setAuthCookie({ response, username: decoded.userName, pk: decoded.pk });
127
+ return { status: 'ok', allowedLogin: true };
128
+ }
129
+ else {
130
+ return { error: 'Wrong or expired OTP code' };
131
+ }
132
+ }
133
+ else {
134
+ // user already has secret, get it
135
+ this.connectors = this.adminforth.connectors;
136
+ const connector = this.connectors[this.authResource.dataSource];
137
+ const user = yield connector.getRecordByPrimaryKey(this.authResource, decoded.pk);
138
+ const verified = twofactor.verifyToken(user[this.options.twoFaSecretFieldName], body.code, this.options.timeStepWindow);
139
+ if (verified) {
140
+ this.adminforth.auth.removeCustomCookie({ response, name: 'totpTemporaryJWT' });
141
+ this.adminforth.auth.setAuthCookie({ response, username: decoded.userName, pk: decoded.pk });
142
+ return { status: 'ok', allowedLogin: true };
143
+ }
144
+ else {
145
+ return { error: 'Wrong or expired OTP code' };
146
+ }
147
+ }
148
+ })
149
+ });
150
+ server.endpoint({
151
+ method: "GET",
152
+ path: "/plugin/twofa/skip-allow",
153
+ noAuth: true,
154
+ handler: (_a) => __awaiter(this, [_a], void 0, function* ({ cookies }) {
155
+ var _b;
156
+ const brandNameSlug = this.adminforth.config.customization.brandNameSlug;
157
+ const totpTemporaryJWT = (_b = cookies.find((cookie) => cookie.key === `adminforth_${brandNameSlug}_totpTemporaryJWT`)) === null || _b === void 0 ? void 0 : _b.value;
158
+ const decoded = yield this.adminforth.auth.verify(totpTemporaryJWT, "tempTotp");
159
+ if (!decoded) {
160
+ return { status: "error", message: "Invalid token" };
161
+ }
162
+ if (!decoded.newSecret) {
163
+ return { status: "ok", skipAllowed: false };
164
+ }
165
+ else {
166
+ return {
167
+ status: "ok",
168
+ skipAllowed: decoded.userCanSkipSetup,
169
+ };
170
+ }
171
+ }),
172
+ });
173
+ }
174
+ }
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};