@spinajs/rbac-http-user 2.0.502 → 2.0.505

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.
Files changed (53) hide show
  1. package/lib/cjs/2fa/Default2FaToken.d.ts +8 -0
  2. package/lib/cjs/2fa/Default2FaToken.d.ts.map +1 -1
  3. package/lib/cjs/2fa/Default2FaToken.js +25 -3
  4. package/lib/cjs/2fa/Default2FaToken.js.map +1 -1
  5. package/lib/cjs/actions/2fa.d.ts +22 -3
  6. package/lib/cjs/actions/2fa.d.ts.map +1 -1
  7. package/lib/cjs/actions/2fa.js +44 -3
  8. package/lib/cjs/actions/2fa.js.map +1 -1
  9. package/lib/cjs/config/rbac-http.d.ts.map +1 -1
  10. package/lib/cjs/config/rbac-http.js +6 -0
  11. package/lib/cjs/config/rbac-http.js.map +1 -1
  12. package/lib/cjs/controllers/LoginController.d.ts.map +1 -1
  13. package/lib/cjs/controllers/LoginController.js +10 -1
  14. package/lib/cjs/controllers/LoginController.js.map +1 -1
  15. package/lib/cjs/controllers/TwoFactorAuthController.d.ts +13 -3
  16. package/lib/cjs/controllers/TwoFactorAuthController.d.ts.map +1 -1
  17. package/lib/cjs/controllers/TwoFactorAuthController.js +32 -6
  18. package/lib/cjs/controllers/TwoFactorAuthController.js.map +1 -1
  19. package/lib/cjs/controllers/TwoFactorAuthUserController.d.ts +71 -4
  20. package/lib/cjs/controllers/TwoFactorAuthUserController.d.ts.map +1 -1
  21. package/lib/cjs/controllers/TwoFactorAuthUserController.js +136 -16
  22. package/lib/cjs/controllers/TwoFactorAuthUserController.js.map +1 -1
  23. package/lib/cjs/policies/2FaPolicy.d.ts.map +1 -1
  24. package/lib/cjs/policies/2FaPolicy.js +27 -6
  25. package/lib/cjs/policies/2FaPolicy.js.map +1 -1
  26. package/lib/mjs/2fa/Default2FaToken.d.ts +8 -0
  27. package/lib/mjs/2fa/Default2FaToken.d.ts.map +1 -1
  28. package/lib/mjs/2fa/Default2FaToken.js +25 -3
  29. package/lib/mjs/2fa/Default2FaToken.js.map +1 -1
  30. package/lib/mjs/actions/2fa.d.ts +22 -3
  31. package/lib/mjs/actions/2fa.d.ts.map +1 -1
  32. package/lib/mjs/actions/2fa.js +41 -3
  33. package/lib/mjs/actions/2fa.js.map +1 -1
  34. package/lib/mjs/config/rbac-http.d.ts.map +1 -1
  35. package/lib/mjs/config/rbac-http.js +6 -0
  36. package/lib/mjs/config/rbac-http.js.map +1 -1
  37. package/lib/mjs/controllers/LoginController.d.ts.map +1 -1
  38. package/lib/mjs/controllers/LoginController.js +10 -1
  39. package/lib/mjs/controllers/LoginController.js.map +1 -1
  40. package/lib/mjs/controllers/TwoFactorAuthController.d.ts +13 -3
  41. package/lib/mjs/controllers/TwoFactorAuthController.d.ts.map +1 -1
  42. package/lib/mjs/controllers/TwoFactorAuthController.js +35 -9
  43. package/lib/mjs/controllers/TwoFactorAuthController.js.map +1 -1
  44. package/lib/mjs/controllers/TwoFactorAuthUserController.d.ts +71 -4
  45. package/lib/mjs/controllers/TwoFactorAuthUserController.d.ts.map +1 -1
  46. package/lib/mjs/controllers/TwoFactorAuthUserController.js +140 -20
  47. package/lib/mjs/controllers/TwoFactorAuthUserController.js.map +1 -1
  48. package/lib/mjs/policies/2FaPolicy.d.ts.map +1 -1
  49. package/lib/mjs/policies/2FaPolicy.js +26 -5
  50. package/lib/mjs/policies/2FaPolicy.js.map +1 -1
  51. package/lib/tsconfig.cjs.tsbuildinfo +1 -1
  52. package/lib/tsconfig.mjs.tsbuildinfo +1 -1
  53. package/package.json +15 -15
@@ -19,11 +19,12 @@ const di_1 = require("@spinajs/di");
19
19
  const configuration_1 = require("@spinajs/configuration");
20
20
  const rbac_http_1 = require("@spinajs/rbac-http");
21
21
  const exceptions_1 = require("@spinajs/exceptions");
22
- const _2FaPolicy_js_1 = require("../policies/2FaPolicy.js");
23
22
  const confirm_password_dto_js_1 = require("../dto/confirm-password-dto.js");
23
+ const token_dto_js_1 = require("../dto/token-dto.js");
24
24
  const SessionCookies_js_1 = require("../services/SessionCookies.js");
25
25
  const _2fa_js_1 = require("../actions/2fa.js");
26
26
  const Default2FaToken_js_1 = require("../2fa/Default2FaToken.js");
27
+ const _2FaPolicy_js_1 = require("../policies/2FaPolicy.js");
27
28
  /**
28
29
  * Self-service two-factor authentication.
29
30
  *
@@ -38,6 +39,13 @@ const Default2FaToken_js_1 = require("../2fa/Default2FaToken.js");
38
39
  * not be enough to attach an attacker-controlled authenticator or to strip the
39
40
  * second factor off the account.
40
41
  *
42
+ * The system-wide switch (`rbac.twoFactorAuth.enabled`) is enforced by
43
+ * `TwoFactorAuthEnabled`, passed to `@Permission` on each mutating route so it
44
+ * shares a policy group with the permission check and is therefore required
45
+ * rather than merely offered as an alternative. It is deliberately NOT a class
46
+ * policy: `status` stays readable while the switch is off, which is how the
47
+ * frontend learns to hide its 2FA controls.
48
+ *
41
49
  * @tags Two-Factor Settings
42
50
  */
43
51
  let TwoFactorAuthUserController = class TwoFactorAuthUserController extends http_1.BaseController {
@@ -50,12 +58,19 @@ let TwoFactorAuthUserController = class TwoFactorAuthUserController extends http
50
58
  * @response 403 Forbidden — insufficient permissions
51
59
  */
52
60
  async status(user) {
53
- return new http_1.Ok({ Enabled: Boolean(user.Metadata[Default2FaToken_js_1.TWO_FA_METATADATA_KEYS.ENABLED]) });
61
+ const enabled = Boolean(user.Metadata[Default2FaToken_js_1.TWO_FA_METATADATA_KEYS.ENABLED]);
62
+ return new http_1.Ok({
63
+ Enabled: enabled,
64
+ Pending: !enabled && Boolean(user.Metadata[Default2FaToken_js_1.TWO_FA_METATADATA_KEYS.TOKEN]),
65
+ SystemEnabled: this.TwoFactorConfig?.enabled !== false,
66
+ });
54
67
  }
55
68
  /**
56
69
  * Enable own two-factor authentication
57
70
  * Generates a TOTP secret for the authenticated user and returns the OTP provisioning
58
71
  * URI to scan with an authenticator app. Requires the account password to be re-entered.
72
+ * 2FA stays off until the new code is confirmed with `POST /user/2fa/confirm` — a caller
73
+ * that stops after this call leaves the account unprotected, believing it is enrolled.
59
74
  * @security cookieAuth
60
75
  * @returns {IEnable2faResponse} OTP provisioning URI to scan with an authenticator app
61
76
  * @response 400 Two-factor authentication is already enabled for this user
@@ -64,20 +79,58 @@ let TwoFactorAuthUserController = class TwoFactorAuthUserController extends http
64
79
  */
65
80
  async enable(user, confirmation, session) {
66
81
  if (user.Metadata[Default2FaToken_js_1.TWO_FA_METATADATA_KEYS.ENABLED]) {
67
- throw new exceptions_1.InvalidOperation(`User ${user.Uuid} already has 2fa enabled`);
82
+ throw new exceptions_1.BadRequest(`User ${user.Uuid} already has 2fa enabled`);
68
83
  }
69
84
  const confirmed = await this.confirmPassword(user, confirmation.Password);
70
85
  if (confirmed !== true) {
71
86
  return confirmed;
72
87
  }
73
- // NOTE: enrolment takes effect immediately the secret is stored and
74
- // `2fa:enabled` is set before the user has proven they scanned it. That is
75
- // the same contract the login-time setup route follows, and it is what the
76
- // login check reads. A user who never scans the returned URI locks
77
- // themselves out and needs an administrator 2FA reset to recover.
88
+ // The secret is stored but 2fa stays OFF until `POST /user/2fa/confirm`
89
+ // accepts a code generated from it. A user who never scans is left pending,
90
+ // which the login check treats exactly like having no device no lockout,
91
+ // and the next attempt simply issues a new secret.
78
92
  const result = await this.enrol(user);
79
93
  return new http_1.Ok({ otp: result }, await this.rotate(session));
80
94
  }
95
+ /**
96
+ * Confirm own two-factor enrolment
97
+ * Verifies a code generated from the secret handed out by `POST /user/2fa/enable`
98
+ * or `POST /user/2fa/reset`, and only then switches 2FA on.
99
+ * @security cookieAuth
100
+ * @response 200 Two-factor authentication is now active
101
+ * @response 400 There is no pending enrolment to confirm
102
+ * @response 401 Unauthorized — valid session required
103
+ * @response 403 Invalid or expired TOTP code
104
+ */
105
+ async confirm(user, token, session) {
106
+ // `activate()` never clears the stored token, so an already-enabled
107
+ // account still has one and would otherwise be able to call this route
108
+ // again with a currently-valid code. Only the pending state — a token
109
+ // without 2fa being enabled yet — is an enrolment left to confirm.
110
+ if (user.Metadata[Default2FaToken_js_1.TWO_FA_METATADATA_KEYS.ENABLED] || !user.Metadata[Default2FaToken_js_1.TWO_FA_METATADATA_KEYS.TOKEN]) {
111
+ throw new exceptions_1.BadRequest(`User ${user.Uuid} has no pending 2fa enrolment`);
112
+ }
113
+ try {
114
+ await this.confirmEnrolment(user, token.Token);
115
+ }
116
+ catch (err) {
117
+ // `confirmUser2Fa` throws `Unauthorized` for a rejected code — the only
118
+ // case this route should report as "wrong code". Anything else (a
119
+ // database outage during activation, for instance) must surface as a
120
+ // 500, not be misreported to the user as a bad code.
121
+ if (!(err instanceof http_1.Unauthorized)) {
122
+ throw err;
123
+ }
124
+ this._log.warn(`2fa confirmation rejected for ${user.Uuid}`, { error: err });
125
+ return new http_1.ForbiddenResponse({
126
+ error: { code: 'E_2FA_FAILED', message: '2fa check failed' },
127
+ });
128
+ }
129
+ // No password here on purpose: the password was confirmed by the enable or
130
+ // reset call that issued this secret, and the code is itself the proof this
131
+ // route exists to demand.
132
+ return new http_1.Ok(null, await this.rotate(session));
133
+ }
81
134
  /**
82
135
  * Disable own two-factor authentication
83
136
  * Removes the TOTP secret and disables 2FA for the authenticated user.
@@ -90,7 +143,7 @@ let TwoFactorAuthUserController = class TwoFactorAuthUserController extends http
90
143
  */
91
144
  async disable(user, confirmation, session) {
92
145
  if (!user.Metadata[Default2FaToken_js_1.TWO_FA_METATADATA_KEYS.ENABLED]) {
93
- throw new exceptions_1.InvalidOperation(`User ${user.Uuid} already has 2fa disabled`);
146
+ throw new exceptions_1.BadRequest(`User ${user.Uuid} already has 2fa disabled`);
94
147
  }
95
148
  const confirmed = await this.confirmPassword(user, confirmation.Password);
96
149
  if (confirmed !== true) {
@@ -99,6 +152,45 @@ let TwoFactorAuthUserController = class TwoFactorAuthUserController extends http
99
152
  await this.unenrol(user);
100
153
  return new http_1.Ok(null, await this.rotate(session));
101
154
  }
155
+ /**
156
+ * Reset own two-factor authentication
157
+ * Removes the current TOTP device and issues a new secret in a single request,
158
+ * returning the provisioning URI to scan. 2FA stays off until the new code is
159
+ * confirmed with `POST /user/2fa/confirm`. Requires the account password.
160
+ *
161
+ * Folding disable-then-enable into one request removes the client-side gap
162
+ * where abandoning the flow between the two calls could strand the account
163
+ * without a second factor. It does not remove the server-side one: if
164
+ * `enrol` fails after `unenrol` already removed the old device, the account
165
+ * is left with no device at all — there is nothing to roll back to, since
166
+ * the old secret is already gone. That leaves the account in the ordinary
167
+ * `none` state, which every route here already handles: `GET /user/2fa`
168
+ * reports it and `POST /user/2fa/enable` starts a fresh enrolment.
169
+ *
170
+ * A caller who abandons before confirming is left password-only — the same
171
+ * gap as `enable`. The only built-in recovery is `rbac.twoFactorAuth.forceUser`
172
+ * pushing the account back through enrolment at next login, and this package's
173
+ * own default for that flag is `false` (see `src/config/rbac-http.ts`), so a
174
+ * consumer that has not set it will see the downgrade become silent and
175
+ * permanent rather than recovered.
176
+ * @security cookieAuth
177
+ * @returns {IEnable2faResponse} OTP provisioning URI to scan with an authenticator app
178
+ * @response 400 There is no two-factor device to reset
179
+ * @response 401 Unauthorized — valid session required, or password invalid
180
+ * @response 403 Forbidden — insufficient permissions
181
+ */
182
+ async reset(user, confirmation, session) {
183
+ if (!user.Metadata[Default2FaToken_js_1.TWO_FA_METATADATA_KEYS.ENABLED] && !user.Metadata[Default2FaToken_js_1.TWO_FA_METATADATA_KEYS.TOKEN]) {
184
+ throw new exceptions_1.BadRequest(`User ${user.Uuid} has no 2fa to reset`);
185
+ }
186
+ const confirmed = await this.confirmPassword(user, confirmation.Password);
187
+ if (confirmed !== true) {
188
+ return confirmed;
189
+ }
190
+ await this.unenrol(user);
191
+ const result = await this.enrol(user);
192
+ return new http_1.Ok({ otp: result }, await this.rotate(session));
193
+ }
102
194
  /**
103
195
  * Rotates the session id after the account's authentication requirements
104
196
  * changed, and returns the response options carrying the new cookie.
@@ -120,11 +212,16 @@ let TwoFactorAuthUserController = class TwoFactorAuthUserController extends http
120
212
  };
121
213
  }
122
214
  /**
123
- * Generate and store the TOTP secret, returning the provisioning URI. Wraps
124
- * the module-level action so tests can stub it without a TOTP/DB setup.
215
+ * Store the TOTP secret and return the provisioning URI, leaving 2fa off until
216
+ * confirmed. Wraps the module-level action so tests can stub it without a
217
+ * TOTP/DB setup.
125
218
  */
126
219
  enrol(user) {
127
- return (0, _2fa_js_1.enableUser2Fa)(user);
220
+ return (0, _2fa_js_1.beginUser2FaEnrolment)(user);
221
+ }
222
+ /** Verify a code against the pending secret and switch 2fa on. */
223
+ confirmEnrolment(user, token) {
224
+ return (0, _2fa_js_1.confirmUser2Fa)(user, token);
128
225
  }
129
226
  /** Clear the TOTP secret. Wrapped for the same reason as {@link enrol}. */
130
227
  unenrol(user) {
@@ -158,6 +255,10 @@ __decorate([
158
255
  (0, di_1.Autoinject)(SessionCookies_js_1.SessionCookieFactory),
159
256
  __metadata("design:type", SessionCookies_js_1.SessionCookieFactory)
160
257
  ], TwoFactorAuthUserController.prototype, "SessionCookies", void 0);
258
+ __decorate([
259
+ (0, configuration_1.Config)('rbac.twoFactorAuth'),
260
+ __metadata("design:type", Object)
261
+ ], TwoFactorAuthUserController.prototype, "TwoFactorConfig", void 0);
161
262
  __decorate([
162
263
  (0, http_1.Get)('2fa'),
163
264
  (0, rbac_http_1.Permission)(['readOwn']),
@@ -168,7 +269,7 @@ __decorate([
168
269
  ], TwoFactorAuthUserController.prototype, "status", null);
169
270
  __decorate([
170
271
  (0, http_1.Post)('2fa/enable'),
171
- (0, rbac_http_1.Permission)(['updateOwn']),
272
+ (0, rbac_http_1.Permission)(['updateOwn'], _2FaPolicy_js_1.TwoFactorAuthEnabled),
172
273
  __param(0, (0, rbac_http_1.User)()),
173
274
  __param(1, (0, http_1.Body)()),
174
275
  __param(2, (0, rbac_http_1.Session)()),
@@ -176,9 +277,19 @@ __decorate([
176
277
  __metadata("design:paramtypes", [rbac_1.User, confirm_password_dto_js_1.ConfirmPasswordDto, Object]),
177
278
  __metadata("design:returntype", Promise)
178
279
  ], TwoFactorAuthUserController.prototype, "enable", null);
280
+ __decorate([
281
+ (0, http_1.Post)('2fa/confirm'),
282
+ (0, rbac_http_1.Permission)(['updateOwn'], _2FaPolicy_js_1.TwoFactorAuthEnabled),
283
+ __param(0, (0, rbac_http_1.User)()),
284
+ __param(1, (0, http_1.Body)()),
285
+ __param(2, (0, rbac_http_1.Session)()),
286
+ __metadata("design:type", Function),
287
+ __metadata("design:paramtypes", [rbac_1.User, token_dto_js_1.TokenDto, Object]),
288
+ __metadata("design:returntype", Promise)
289
+ ], TwoFactorAuthUserController.prototype, "confirm", null);
179
290
  __decorate([
180
291
  (0, http_1.Post)('2fa/disable'),
181
- (0, rbac_http_1.Permission)(['updateOwn']),
292
+ (0, rbac_http_1.Permission)(['updateOwn'], _2FaPolicy_js_1.TwoFactorAuthEnabled),
182
293
  __param(0, (0, rbac_http_1.User)()),
183
294
  __param(1, (0, http_1.Body)()),
184
295
  __param(2, (0, rbac_http_1.Session)()),
@@ -186,10 +297,19 @@ __decorate([
186
297
  __metadata("design:paramtypes", [rbac_1.User, confirm_password_dto_js_1.ConfirmPasswordDto, Object]),
187
298
  __metadata("design:returntype", Promise)
188
299
  ], TwoFactorAuthUserController.prototype, "disable", null);
300
+ __decorate([
301
+ (0, http_1.Post)('2fa/reset'),
302
+ (0, rbac_http_1.Permission)(['updateOwn'], _2FaPolicy_js_1.TwoFactorAuthEnabled),
303
+ __param(0, (0, rbac_http_1.User)()),
304
+ __param(1, (0, http_1.Body)()),
305
+ __param(2, (0, rbac_http_1.Session)()),
306
+ __metadata("design:type", Function),
307
+ __metadata("design:paramtypes", [rbac_1.User, confirm_password_dto_js_1.ConfirmPasswordDto, Object]),
308
+ __metadata("design:returntype", Promise)
309
+ ], TwoFactorAuthUserController.prototype, "reset", null);
189
310
  exports.TwoFactorAuthUserController = TwoFactorAuthUserController = __decorate([
190
311
  (0, http_1.BasePath)('user'),
191
312
  (0, rbac_http_1.Resource)('user'),
192
- (0, http_1.Policy)(rbac_http_1.AuthorizedPolicy),
193
- (0, http_1.Policy)(_2FaPolicy_js_1.TwoFactorAuthEnabled)
313
+ (0, http_1.Policy)(rbac_http_1.AuthorizedPolicy)
194
314
  ], TwoFactorAuthUserController);
195
315
  //# sourceMappingURL=TwoFactorAuthUserController.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TwoFactorAuthUserController.js","sourceRoot":"","sources":["../../../src/controllers/TwoFactorAuthUserController.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,wCAAoG;AACpG,wCAAwG;AAExG,oCAAyC;AACzC,0DAA2D;AAC3D,kDAAkI;AAClI,oDAAuD;AACvD,4DAAgE;AAChE,4EAAoE;AACpE,qEAAqE;AACrE,+CAAkE;AAClE,kEAAmE;AAOnE;;;;;;;;;;;;;;;GAeG;AAKI,IAAM,2BAA2B,GAAjC,MAAM,2BAA4B,SAAQ,qBAAc;IAU7D;;;;;;;OAOG;IAGU,AAAN,KAAK,CAAC,MAAM,CAAS,IAAe;QACzC,OAAO,IAAI,SAAE,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,2CAAsB,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IACrF,CAAC;IAED;;;;;;;;;OASG;IAGU,AAAN,KAAK,CAAC,MAAM,CAAS,IAAe,EAAU,YAAgC,EAAqB,OAAiB;QACzH,IAAI,IAAI,CAAC,QAAQ,CAAC,2CAAsB,CAAC,OAAO,CAAC,EAAE,CAAC;YAClD,MAAM,IAAI,6BAAgB,CAAC,QAAQ,IAAI,CAAC,IAAI,0BAA0B,CAAC,CAAC;QAC1E,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;QAC1E,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACvB,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,sEAAsE;QACtE,2EAA2E;QAC3E,2EAA2E;QAC3E,mEAAmE;QACnE,kEAAkE;QAClE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEtC,OAAO,IAAI,SAAE,CAAC,EAAE,GAAG,EAAE,MAAgB,EAAE,EAAE,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IACvE,CAAC;IAED;;;;;;;;;OASG;IAGU,AAAN,KAAK,CAAC,OAAO,CAAS,IAAe,EAAU,YAAgC,EAAqB,OAAiB;QAC1H,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,2CAAsB,CAAC,OAAO,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,6BAAgB,CAAC,QAAQ,IAAI,CAAC,IAAI,2BAA2B,CAAC,CAAC;QAC3E,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;QAC1E,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACvB,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACzB,OAAO,IAAI,SAAE,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IAClD,CAAC;IAED;;;;;;;;;OASG;IACO,KAAK,CAAC,MAAM,CAAC,OAAiB;QACtC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;QACrE,CAAC;QAED,MAAM,WAAW,GAAG,MAAM,IAAA,wBAAiB,EAAC,IAAI,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;QAE3E,OAAO;YACL,QAAQ,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YAClD,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;SACxD,CAAC;IACJ,CAAC;IAED;;;OAGG;IACO,KAAK,CAAC,IAAe;QAC7B,OAAO,IAAA,uBAAa,EAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,2EAA2E;IACjE,OAAO,CAAC,IAAe;QAC/B,OAAO,IAAA,wBAAc,EAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED;;;OAGG;IACO,KAAK,CAAC,eAAe,CAAC,IAAe,EAAE,QAAgB;QAC/D,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAE1E,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,2BAA2B,IAAI,CAAC,IAAI,gCAAgC,CAAC,CAAC;YAErF,OAAO,IAAI,mBAAY,CAAC;gBACtB,KAAK,EAAE,EAAE,IAAI,EAAE,oBAAoB,EAAE,OAAO,EAAE,kBAAkB,EAAE;aACnE,CAAC,CAAC;QACL,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAA;;AArIW;IADT,IAAA,iCAAiB,EAAC,eAAe,CAAC;8BACP,uBAAgB;qEAAC;AAGnC;IADT,IAAA,iCAAiB,EAAC,cAAc,CAAC;8BACP,sBAAe;oEAAC;AAGjC;IADT,IAAA,eAAU,EAAC,wCAAoB,CAAC;8BACP,wCAAoB;mEAAC;AAYlC;IAFZ,IAAA,UAAG,EAAC,KAAK,CAAC;IACV,IAAA,sBAAU,EAAC,CAAC,SAAS,CAAC,CAAC;IACH,WAAA,IAAA,gBAAI,GAAE,CAAA;;qCAAO,WAAS;;yDAE1C;AAcY;IAFZ,IAAA,WAAI,EAAC,YAAY,CAAC;IAClB,IAAA,sBAAU,EAAC,CAAC,WAAW,CAAC,CAAC;IACL,WAAA,IAAA,gBAAI,GAAE,CAAA;IAAmB,WAAA,IAAA,WAAI,GAAE,CAAA;IAAoC,WAAA,IAAA,mBAAe,GAAE,CAAA;;qCAAvE,WAAS,EAAwB,4CAAkB;;yDAkBpF;AAcY;IAFZ,IAAA,WAAI,EAAC,aAAa,CAAC;IACnB,IAAA,sBAAU,EAAC,CAAC,WAAW,CAAC,CAAC;IACJ,WAAA,IAAA,gBAAI,GAAE,CAAA;IAAmB,WAAA,IAAA,WAAI,GAAE,CAAA;IAAoC,WAAA,IAAA,mBAAe,GAAE,CAAA;;qCAAvE,WAAS,EAAwB,4CAAkB;;0DAYrF;sCAhFU,2BAA2B;IAJvC,IAAA,eAAQ,EAAC,MAAM,CAAC;IAChB,IAAA,oBAAQ,EAAC,MAAM,CAAC;IAChB,IAAA,aAAM,EAAC,4BAAgB,CAAC;IACxB,IAAA,aAAM,EAAC,oCAAoB,CAAC;GAChB,2BAA2B,CAuIvC"}
1
+ {"version":3,"file":"TwoFactorAuthUserController.js","sourceRoot":"","sources":["../../../src/controllers/TwoFactorAuthUserController.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"2FaPolicy.d.ts","sourceRoot":"","sources":["../../../src/policies/2FaPolicy.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAGzD;;;;;;GAMG;AACH,qBAAa,oBAAqB,SAAQ,UAAU;IAElD,SAAS,CAAC,eAAe,EAAE,mBAAmB,CAAC;IAExC,SAAS,IAAI,OAAO,CAE1B;IAEM,OAAO,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAM5C;CACF;AAED;;;;;;;;;GASG;AACH,qBAAa,kBAAmB,SAAQ,oBAAoB;IAC7C,OAAO,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAejD;CACF"}
1
+ {"version":3,"file":"2FaPolicy.d.ts","sourceRoot":"","sources":["../../../src/policies/2FaPolicy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAGzD;;;;;;GAMG;AACH,qBAAa,oBAAqB,SAAQ,UAAU;IAElD,SAAS,CAAC,eAAe,EAAE,mBAAmB,CAAC;IAExC,SAAS,IAAI,OAAO,CAE1B;IAEY,OAAO,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BlD;CACF;AAED;;;;;;;;;GASG;AACH,qBAAa,kBAAmB,SAAQ,oBAAoB;IAC7C,OAAO,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAejD;CACF"}
@@ -10,10 +10,9 @@ var __metadata = (this && this.__metadata) || function (k, v) {
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.TwoFacRouteEnabled = exports.TwoFactorAuthEnabled = void 0;
13
- const exceptions_1 = require("@spinajs/exceptions");
14
13
  const configuration_1 = require("@spinajs/configuration");
15
14
  const http_1 = require("@spinajs/http");
16
- const exceptions_2 = require("@spinajs/exceptions");
15
+ const exceptions_1 = require("@spinajs/exceptions");
17
16
  /**
18
17
  * Guards routes that only make sense when 2FA is switched on system-wide.
19
18
  *
@@ -25,11 +24,33 @@ class TwoFactorAuthEnabled extends http_1.BasePolicy {
25
24
  isEnabled() {
26
25
  return true;
27
26
  }
28
- execute(_req) {
27
+ async execute(_req) {
29
28
  if (this.TwoFactorConfig.enabled === false) {
30
- throw new exceptions_1.InvalidOperation('2 factor auth is not enabled');
29
+ // Deliberately Forbidden and not InvalidOperation: the latter has no
30
+ // @HandleException mapping in @spinajs/http and reaches the client as a
31
+ // 500, which a caller cannot distinguish from a fault.
32
+ //
33
+ // `Forbidden`'s constructor only accepts a message string (see
34
+ // `Exception` in @spinajs/exceptions), so the structured payload that
35
+ // the HTTP error handler serializes into the response body is attached
36
+ // as an extra `error` property after construction.
37
+ //
38
+ // This method must stay `async`: `createPolicyGate` (see
39
+ // packages/http/src/route-builder.ts) builds its wait list with
40
+ // `enabledPolicies.map(p => p.execute(...).then(...))`. A synchronous
41
+ // `throw` here would escape that `.map()` call entirely instead of
42
+ // becoming a rejected promise in the array, so `Promise.allSettled`
43
+ // would never even run — the whole policy gate blows up for every
44
+ // caller, authorized or not, instead of just this policy losing the
45
+ // race. Marking the method `async` turns the throw into a promise
46
+ // rejection, which is what the gate is built to handle.
47
+ throw Object.assign(new exceptions_1.Forbidden('2 factor auth is not enabled'), {
48
+ error: {
49
+ code: 'E_2FA_SYSTEM_DISABLED',
50
+ message: '2 factor auth is not enabled',
51
+ },
52
+ });
31
53
  }
32
- return Promise.resolve();
33
54
  }
34
55
  }
35
56
  exports.TwoFactorAuthEnabled = TwoFactorAuthEnabled;
@@ -57,7 +78,7 @@ class TwoFacRouteEnabled extends TwoFactorAuthEnabled {
57
78
  * Check only if user passed login page and waiting for TwoFactorAuth
58
79
  */
59
80
  if (!req.storage.Session?.Data.get('TwoFactorAuth')) {
60
- throw new exceptions_2.Forbidden('user does not have 2fa enabled');
81
+ throw new exceptions_1.Forbidden('user does not have 2fa enabled');
61
82
  }
62
83
  return Promise.resolve();
63
84
  }
@@ -1 +1 @@
1
- {"version":3,"file":"2FaPolicy.js","sourceRoot":"","sources":["../../../src/policies/2FaPolicy.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,oDAAuD;AACvD,0DAAgD;AAChD,wCAAgE;AAEhE,oDAAgD;AAEhD;;;;;;GAMG;AACH,0BAAkC,SAAQ,iBAAU;IAI3C,SAAS;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,OAAO,CAAC,IAAc;QAC3B,IAAI,IAAI,CAAC,eAAe,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;YAC3C,MAAM,IAAI,6BAAgB,CAAC,8BAA8B,CAAC,CAAC;QAC7D,CAAC;QAED,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;CACF;;AAbW;IADT,IAAA,sBAAM,EAAC,oBAAoB,CAAC;;6DACkB;AAejD;;;;;;;;;GASG;AACH,wBAAgC,SAAQ,oBAAoB;IACnD,KAAK,CAAC,OAAO,CAAC,GAAa;QAChC,MAAM,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAEzB,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YACzC,MAAM,IAAI,6BAAgB,CAAC,oBAAoB,CAAC,CAAC;QACnD,CAAC;QAED;;WAEG;QACH,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC;YACpD,MAAM,IAAI,sBAAS,CAAC,gCAAgC,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;CACF"}
1
+ {"version":3,"file":"2FaPolicy.js","sourceRoot":"","sources":["../../../src/policies/2FaPolicy.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,0DAAgD;AAChD,wCAAgE;AAEhE,oDAAkE;AAElE;;;;;;GAMG;AACH,0BAAkC,SAAQ,iBAAU;IAI3C,SAAS;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,IAAc;QACjC,IAAI,IAAI,CAAC,eAAe,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;YAC3C,qEAAqE;YACrE,wEAAwE;YACxE,uDAAuD;YACvD,EAAE;YACF,+DAA+D;YAC/D,sEAAsE;YACtE,uEAAuE;YACvE,mDAAmD;YACnD,EAAE;YACF,yDAAyD;YACzD,gEAAgE;YAChE,sEAAsE;YACtE,mEAAmE;YACnE,oEAAoE;YACpE,kEAAkE;YAClE,oEAAoE;YACpE,kEAAkE;YAClE,wDAAwD;YACxD,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,sBAAS,CAAC,8BAA8B,CAAC,EAAE;gBACjE,KAAK,EAAE;oBACL,IAAI,EAAE,uBAAuB;oBAC7B,OAAO,EAAE,8BAA8B;iBACxC;aACF,CAAC,CAAC;QACL,CAAC;IACH,CAAC;CACF;;AAlCW;IADT,IAAA,sBAAM,EAAC,oBAAoB,CAAC;;6DACkB;AAoCjD;;;;;;;;;GASG;AACH,wBAAgC,SAAQ,oBAAoB;IACnD,KAAK,CAAC,OAAO,CAAC,GAAa;QAChC,MAAM,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAEzB,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YACzC,MAAM,IAAI,6BAAgB,CAAC,oBAAoB,CAAC,CAAC;QACnD,CAAC;QAED;;WAEG;QACH,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC;YACpD,MAAM,IAAI,sBAAS,CAAC,gCAAgC,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;CACF"}
@@ -14,6 +14,14 @@ export declare class Default2FaToken extends TwoFactorAuthProvider {
14
14
  execute(_: User): Promise<void>;
15
15
  verifyToken(token: string, user: User): Promise<boolean>;
16
16
  disable(user: User): Promise<void>;
17
+ beginEnrolment(user: User): Promise<any>;
18
+ activate(user: User): Promise<void>;
19
+ /**
20
+ * Enrol and switch on in one step. This is what the CLI command, the
21
+ * administrator reset and user seeding use — they hand the secret to an
22
+ * operator rather than to the account owner, so there is nobody to confirm
23
+ * possession with.
24
+ */
17
25
  initialize(user: User): Promise<any>;
18
26
  getOtpAuthUrl(user: User): Promise<string | null>;
19
27
  isEnabled(user: User): Promise<boolean>;
@@ -1 +1 @@
1
- {"version":3,"file":"Default2FaToken.d.ts","sourceRoot":"","sources":["../../../src/2fa/Default2FaToken.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,OAAO,EAAE,GAAG,EAAU,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAI3D,oBAAY,sBAAsB;IAC9B,KAAK,cAAc;IACnB,OAAO,gBAAgB;IACvB,GAAG,YAAY;CAClB;AAED,qBACa,eAAgB,SAAQ,qBAAqB;IAEtD,SAAS,CAAC,MAAM,EAAE,GAAG,CAAC;IAGtB,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC;IAEnB,cAEC;IAED,OAAO,CAAC,OAAO;IAYR,OAAO,CAAC,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAIrC;IAEY,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAcpE;IAEY,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAY9C;IAEY,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAyBhD;IAEY,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAU7D;IAEY,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAGnD;IAEY,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAGvD;CACJ"}
1
+ {"version":3,"file":"Default2FaToken.d.ts","sourceRoot":"","sources":["../../../src/2fa/Default2FaToken.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,OAAO,EAAE,GAAG,EAAU,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAI3D,oBAAY,sBAAsB;IAC9B,KAAK,cAAc;IACnB,OAAO,gBAAgB;IACvB,GAAG,YAAY;CAClB;AAED,qBACa,eAAgB,SAAQ,qBAAqB;IAEtD,SAAS,CAAC,MAAM,EAAE,GAAG,CAAC;IAGtB,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC;IAEnB,cAEC;IAED,OAAO,CAAC,OAAO;IAYR,OAAO,CAAC,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAIrC;IAEY,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAcpE;IAEY,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAY9C;IAEY,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAwBpD;IAEY,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAc/C;IAED;;;;;OAKG;IACU,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAKhD;IAEY,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAU7D;IAEY,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAGnD;IAEY,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAGvD;CACJ"}
@@ -60,17 +60,16 @@ let Default2FaToken = class Default2FaToken extends TwoFactorAuthProvider {
60
60
  },
61
61
  });
62
62
  }
63
- async initialize(user) {
63
+ async beginEnrolment(user) {
64
64
  if (user.Metadata[TWO_FA_METATADATA_KEYS.ENABLED]) {
65
65
  throw new InvalidOperation(`user ${user.Uuid} alread have enabled 2f, disable it first.`);
66
66
  }
67
67
  const secret = new OTPAuth.Secret({ size: this.Config.secretSize });
68
68
  const totp = this._getOTP(user, secret.base32);
69
69
  user.Metadata[TWO_FA_METATADATA_KEYS.TOKEN] = secret.base32;
70
- user.Metadata[TWO_FA_METATADATA_KEYS.ENABLED] = true;
71
70
  user.Metadata[TWO_FA_METATADATA_KEYS.OTP] = totp.toString();
72
71
  await user.Metadata.update();
73
- this.Log.trace(`2fa token initialized for user ${user.Uuid}`, {
72
+ this.Log.trace(`2fa enrolment started for user ${user.Uuid}`, {
74
73
  user: {
75
74
  Uuid: user.Uuid
76
75
  },
@@ -80,6 +79,29 @@ let Default2FaToken = class Default2FaToken extends TwoFactorAuthProvider {
80
79
  */
81
80
  return totp.toString();
82
81
  }
82
+ async activate(user) {
83
+ if (!user.Metadata[TWO_FA_METATADATA_KEYS.TOKEN]) {
84
+ throw new InvalidOperation(`user ${user.Uuid} has no 2fa secret to activate`);
85
+ }
86
+ user.Metadata[TWO_FA_METATADATA_KEYS.ENABLED] = true;
87
+ await user.Metadata.update();
88
+ this.Log.trace(`2fa activated for user ${user.Uuid}`, {
89
+ user: {
90
+ Uuid: user.Uuid
91
+ },
92
+ });
93
+ }
94
+ /**
95
+ * Enrol and switch on in one step. This is what the CLI command, the
96
+ * administrator reset and user seeding use — they hand the secret to an
97
+ * operator rather than to the account owner, so there is nobody to confirm
98
+ * possession with.
99
+ */
100
+ async initialize(user) {
101
+ const otp = await this.beginEnrolment(user);
102
+ await this.activate(user);
103
+ return otp;
104
+ }
83
105
  async getOtpAuthUrl(user) {
84
106
  const token = user.Metadata[TWO_FA_METATADATA_KEYS.TOKEN];
85
107
  if (!token) {
@@ -1 +1 @@
1
- {"version":3,"file":"Default2FaToken.js","sourceRoot":"","sources":["../../../src/2fa/Default2FaToken.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Default2FaToken.js","sourceRoot":"","sources":["../../../src/2fa/Default2FaToken.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,30 @@
1
1
  import { User } from '@spinajs/rbac';
2
2
  /**
3
- * NOTE for all three actions below: the event must be emitted for the USER, not
4
- * for whatever the provider call returned ( `initialize()` returns the otpauth
3
+ * NOTE for enableUser2Fa: the event must be emitted for the USER, not for
4
+ * whatever the provider call returned ( `initialize()` returns the otpauth
5
5
  * url ). `_user_ev` reads `Uuid` off its argument, so it is bound to `u`
6
- * explicitly and the provider result is passed through untouched.
6
+ * explicitly via `_tap`, which fires the event as a side effect while passing
7
+ * the provider result through untouched as the chain's result.
7
8
  */
8
9
  export declare function enableUser2Fa(identifier: number | string | User): Promise<unknown>;
10
+ /**
11
+ * Hand the user a secret without switching 2fa on. No event is emitted: an
12
+ * enrolment nobody confirmed is not a fact about the account, and consumers
13
+ * listening for User2FaEnabled would otherwise fire on an abandoned attempt.
14
+ */
15
+ export declare function beginUser2FaEnrolment(identifier: number | string | User): Promise<unknown>;
16
+ /**
17
+ * Switch 2fa on for an account whose code was already verified by the caller.
18
+ * The login-window flow needs this split: `auth2Fa` has already checked the
19
+ * code and emitted User2FaPassed by the time the session is authorized.
20
+ */
21
+ export declare function activateUser2Fa(identifier: number | string | User): Promise<unknown>;
22
+ /**
23
+ * Complete an enrolment started by `beginUser2FaEnrolment`: verify the code
24
+ * against the stored secret, then switch 2fa on. Throws Unauthorized when the
25
+ * code does not match, leaving the enrolment pending so the user can retry.
26
+ */
27
+ export declare function confirmUser2Fa(identifier: number | string | User, token: string): Promise<unknown>;
9
28
  export declare function disableUser2Fa(identifier: number | string | User): Promise<unknown>;
10
29
  export declare function resetUser2Fa(identifier: number | string | User): Promise<unknown>;
11
30
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"2fa.d.ts","sourceRoot":"","sources":["../../../src/actions/2fa.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAyD,MAAM,eAAe,CAAC;AAa5F;;;;;GAKG;AAEH,wBAAsB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,oBAYrE;AAED,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,oBAWtE;AAED,wBAAsB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,oBAiBpE;AAED;;;;;;;GAOG;AACH,wBAAsB,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,oBA8B9E"}
1
+ {"version":3,"file":"2fa.d.ts","sourceRoot":"","sources":["../../../src/actions/2fa.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAyD,MAAM,eAAe,CAAC;AAa5F;;;;;;GAMG;AAEH,wBAAsB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,oBAYrE;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,oBAU7E;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,oBAWvE;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,oBAqBrF;AAED,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,oBAWtE;AAED,wBAAsB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,oBAiBpE;AAED;;;;;;;GAOG;AACH,wBAAsB,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,oBA8B9E"}
@@ -9,10 +9,11 @@ import { TwoFactorAuthProvider, } from '@spinajs/rbac-http';
9
9
  import { User2FaReset } from '../events/User2FaReset.js';
10
10
  import { User2FaDisabled } from '../events/User2FaDisabled.js';
11
11
  /**
12
- * NOTE for all three actions below: the event must be emitted for the USER, not
13
- * for whatever the provider call returned ( `initialize()` returns the otpauth
12
+ * NOTE for enableUser2Fa: the event must be emitted for the USER, not for
13
+ * whatever the provider call returned ( `initialize()` returns the otpauth
14
14
  * url ). `_user_ev` reads `Uuid` off its argument, so it is bound to `u`
15
- * explicitly and the provider result is passed through untouched.
15
+ * explicitly via `_tap`, which fires the event as a side effect while passing
16
+ * the provider result through untouched as the chain's result.
16
17
  */
17
18
  export async function enableUser2Fa(identifier) {
18
19
  return _chain(_user_unsafe(identifier), (u) => {
@@ -21,6 +22,43 @@ export async function enableUser2Fa(identifier) {
21
22
  _tap(async () => _user_ev(User2FaEnabled)(u)));
22
23
  });
23
24
  }
25
+ /**
26
+ * Hand the user a secret without switching 2fa on. No event is emitted: an
27
+ * enrolment nobody confirmed is not a fact about the account, and consumers
28
+ * listening for User2FaEnabled would otherwise fire on an abandoned attempt.
29
+ */
30
+ export async function beginUser2FaEnrolment(identifier) {
31
+ return _chain(_user_unsafe(identifier), (u) => {
32
+ return _chain(_service('rbac.twoFactorAuth', TwoFactorAuthProvider), async (twoFa) => twoFa.beginEnrolment(u));
33
+ });
34
+ }
35
+ /**
36
+ * Switch 2fa on for an account whose code was already verified by the caller.
37
+ * The login-window flow needs this split: `auth2Fa` has already checked the
38
+ * code and emitted User2FaPassed by the time the session is authorized.
39
+ */
40
+ export async function activateUser2Fa(identifier) {
41
+ return _chain(_user_unsafe(identifier), (u) => {
42
+ return _chain(_service('rbac.twoFactorAuth', TwoFactorAuthProvider), async (twoFa) => twoFa.activate(u), () => _user_ev(User2FaEnabled)(u));
43
+ });
44
+ }
45
+ /**
46
+ * Complete an enrolment started by `beginUser2FaEnrolment`: verify the code
47
+ * against the stored secret, then switch 2fa on. Throws Unauthorized when the
48
+ * code does not match, leaving the enrolment pending so the user can retry.
49
+ */
50
+ export async function confirmUser2Fa(identifier, token) {
51
+ token = _check_arg(_trim(), _non_empty())(token, 'token');
52
+ return _chain(_user_unsafe(identifier), (u) => {
53
+ return _chain(_service('rbac.twoFactorAuth', TwoFactorAuthProvider), _either((twoFa) => twoFa.verifyToken(token, u),
54
+ // Delegates to `activateUser2Fa`, which re-resolves the provider
55
+ // itself. It is shared with the login-window flow, where the
56
+ // code is already verified by the time activation is needed.
57
+ () => activateUser2Fa(u), () => {
58
+ throw new Unauthorized('2fa confirmation failed');
59
+ }));
60
+ });
61
+ }
24
62
  export async function disableUser2Fa(identifier) {
25
63
  return _chain(_user_unsafe(identifier), (u) => {
26
64
  return _chain(_service('rbac.twoFactorAuth', TwoFactorAuthProvider), async (twoFa) => twoFa.disable(u), () => _user_ev(User2FaDisabled)(u));
@@ -1 +1 @@
1
- {"version":3,"file":"2fa.js","sourceRoot":"","sources":["../../../src/actions/2fa.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"2fa.js","sourceRoot":"","sources":["../../../src/actions/2fa.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"rbac-http.d.ts","sourceRoot":"","sources":["../../../src/config/rbac-http.ts"],"names":[],"mappings":"AAQA,QAAA,MAAM,QAAQ;IACZ,MAAM;QACJ,IAAI;YACF,WAAW;YACX,GAAG;;;IAGP,KAAK;QACH,OAAO;YACL,eAAe;gBAAI,UAAU;;YAC7B,cAAc;gBAAI,UAAU;;YAC5B,aAAa;gBAAI,UAAU;;YAC3B,YAAY;gBAAI,UAAU;;;;IAG9B,IAAI;QACF,OAAO;YACL;;eAEG;YACH,MAAM;YAEN;;eAEG;YACH,SAAS;YACT,MAAM;YACN,MAAM;YACN,MAAM;;QAER,aAAa;YACX,OAAO;YACP,SAAS;YACT,OAAO;;QAMT,QAAQ;YAIN;;eAEG;YACH,kBAAkB;;;IAGtB,IAAI;CAKL,CAAC;eAEa,QAAQ"}
1
+ {"version":3,"file":"rbac-http.d.ts","sourceRoot":"","sources":["../../../src/config/rbac-http.ts"],"names":[],"mappings":"AAQA,QAAA,MAAM,QAAQ;IACZ,MAAM;QACJ,IAAI;YACF,WAAW;YACX,GAAG;;;IAGP,KAAK;QACH,OAAO;YACL,eAAe;gBAAI,UAAU;;YAC7B,cAAc;gBAAI,UAAU;;YAC5B,aAAa;gBAAI,UAAU;;YAC3B,YAAY;gBAAI,UAAU;;;;IAG9B,IAAI;QACF,OAAO;YACL;;eAEG;YACH,MAAM;YAEN;;eAEG;YACH,SAAS;YACT,MAAM;YACN,MAAM;YACN,MAAM;;QAER,aAAa;YACX,OAAO;YAQP,SAAS;YACT,OAAO;;QAMT,QAAQ;YAIN;;eAEG;YACH,kBAAkB;;;IAGtB,IAAI;CAKL,CAAC;eAEa,QAAQ"}
@@ -34,6 +34,12 @@ const rbacHttp = {
34
34
  },
35
35
  twoFactorAuth: {
36
36
  enabled: true,
37
+ // `POST /user/2fa/reset` relies on this flag to recover an account that
38
+ // was left password-only after a reset was abandoned before the new
39
+ // secret was confirmed (see the docblock on `reset` in
40
+ // TwoFactorAuthUserController) — with it `false`, as it defaults here,
41
+ // that downgrade is silent and permanent for any consumer of this
42
+ // package that does not override it.
37
43
  forceUser: false,
38
44
  service: 'Default2FaToken',
39
45
  },
@@ -1 +1 @@
1
- {"version":3,"file":"rbac-http.js","sourceRoot":"","sources":["../../../src/config/rbac-http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEhD,SAAS,GAAG,CAAC,IAAY;IACvB,MAAM,UAAU,GAAG,OAAO,MAAM,KAAK,WAAW,CAAC;IACjD,OAAO,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,UAAU,EAAE,gBAAgB,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;AAC3K,CAAC;AAGD,MAAM,QAAQ,GAAG;IACf,MAAM,EAAE;QACN,IAAI,EAAE;YACJ,WAAW,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YACjC,GAAG,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;SAClB;KACF;IACD,KAAK,EAAE;QACL,OAAO,EAAE;YACP,eAAe,EAAE,EAAE,UAAU,EAAE,uBAAuB,EAAE;YACxD,cAAc,EAAE,EAAE,UAAU,EAAE,uBAAuB,EAAE;YACvD,aAAa,EAAE,EAAE,UAAU,EAAE,uBAAuB,EAAE;YACtD,YAAY,EAAE,EAAE,UAAU,EAAE,uBAAuB,EAAE;SACtD;KACF;IACD,IAAI,EAAE;QACJ,OAAO,EAAE;YACP;;eAEG;YACH,MAAM,EAAE,SAAS;YAEjB;;eAEG;YACH,SAAS,EAAE,MAAM;YACjB,MAAM,EAAE,CAAC;YACT,MAAM,EAAE,EAAE;YACV,MAAM,EAAE,CAAC;SACV;QACD,aAAa,EAAE;YACb,OAAO,EAAE,IAAI;YACb,SAAS,EAAE,KAAK;YAChB,OAAO,EAAE,iBAAiB;SAC3B;QACD,sEAAsE;QACtE,0EAA0E;QAC1E,sEAAsE;QACtE,yCAAyC;QACzC,QAAQ,EAAE;YACR,qFAAqF;YACrF,4EAA4E;YAE5E;;eAEG;YACH,kBAAkB,EAAE,CAAC;SACtB;KACF;IACD,IAAI,EAAE;IACJ,iBAAiB;IACjB,+CAA+C;IAC/C,KAAK;KACN;CACF,CAAC;AAEF,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"rbac-http.js","sourceRoot":"","sources":["../../../src/config/rbac-http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEhD,SAAS,GAAG,CAAC,IAAY;IACvB,MAAM,UAAU,GAAG,OAAO,MAAM,KAAK,WAAW,CAAC;IACjD,OAAO,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,UAAU,EAAE,gBAAgB,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;AAC3K,CAAC;AAGD,MAAM,QAAQ,GAAG;IACf,MAAM,EAAE;QACN,IAAI,EAAE;YACJ,WAAW,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YACjC,GAAG,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;SAClB;KACF;IACD,KAAK,EAAE;QACL,OAAO,EAAE;YACP,eAAe,EAAE,EAAE,UAAU,EAAE,uBAAuB,EAAE;YACxD,cAAc,EAAE,EAAE,UAAU,EAAE,uBAAuB,EAAE;YACvD,aAAa,EAAE,EAAE,UAAU,EAAE,uBAAuB,EAAE;YACtD,YAAY,EAAE,EAAE,UAAU,EAAE,uBAAuB,EAAE;SACtD;KACF;IACD,IAAI,EAAE;QACJ,OAAO,EAAE;YACP;;eAEG;YACH,MAAM,EAAE,SAAS;YAEjB;;eAEG;YACH,SAAS,EAAE,MAAM;YACjB,MAAM,EAAE,CAAC;YACT,MAAM,EAAE,EAAE;YACV,MAAM,EAAE,CAAC;SACV;QACD,aAAa,EAAE;YACb,OAAO,EAAE,IAAI;YAEb,wEAAwE;YACxE,oEAAoE;YACpE,uDAAuD;YACvD,uEAAuE;YACvE,kEAAkE;YAClE,qCAAqC;YACrC,SAAS,EAAE,KAAK;YAChB,OAAO,EAAE,iBAAiB;SAC3B;QACD,sEAAsE;QACtE,0EAA0E;QAC1E,sEAAsE;QACtE,yCAAyC;QACzC,QAAQ,EAAE;YACR,qFAAqF;YACrF,4EAA4E;YAE5E;;eAEG;YACH,kBAAkB,EAAE,CAAC;SACtB;KACF;IACD,IAAI,EAAE;IACJ,iBAAiB;IACjB,+CAA+C;IAC/C,KAAK;KACN;CACF,CAAC;AAEF,eAAe,QAAQ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"LoginController.d.ts","sourceRoot":"","sources":["../../../src/controllers/LoginController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAwB,EAAE,EAAO,YAAY,EAAU,MAAM,eAAe,CAAC;AACpG,OAAO,EAAE,YAAY,EAAE,eAAe,EAAsB,aAAa,EAA0C,MAAM,eAAe,CAAC;AAGzI,OAAO,EAA6B,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAElF,OAAO,EAA0F,cAAc,EAAE,eAAe,EAAuB,MAAM,oBAAoB,CAAC;AAClL,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAKrE;;;;;GAKG;AACH,qBACa,eAAgB,SAAQ,cAAc;IAEjD,SAAS,CAAC,aAAa,EAAE,aAAa,CAAC;IAGvC,SAAS,CAAC,YAAY,EAAE,YAAY,CAAC;IAGrC,SAAS,CAAC,eAAe,EAAE,eAAe,CAAC;IAK3C,SAAS,CAAC,oBAAoB,EAAE,OAAO,CAAC;IAMxC,SAAS,CAAC,sBAAsB,EAAE,OAAO,CAAC;IAG1C,SAAS,CAAC,cAAc,EAAE,oBAAoB,CAAC;IAG/C,SAAS,CAAC,EAAE,EAAE,aAAa,CAAC;IAE5B;;;;;;;;;OASG;IAGU,KAAK,CAAiB,MAAM,EAAE,IAAI,EAAe,IAAI,EAAE,MAAM,EAAU,WAAW,EAAE,YAAY,GAAG,OAAO,CAAC,EAAE,CAAC,cAAc,CAAC,GAAG,YAAY,CAAC,CA4GzJ;IAED;;;;;;;;;;;;OAYG;IAGU,MAAM,CAAc,IAAI,EAAE,MAAM,EAAqB,OAAO,EAAE,QAAQ,EAAkB,IAAI,EAAE,IAAI,oBA8B9G;IAED;;;;;;;;;OASG;IAGU,MAAM,CAAiB,IAAI,EAAE,IAAI,EAAiB,UAAU,EAAE,MAAM,EAAqB,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAmBrJ;CACF"}
1
+ {"version":3,"file":"LoginController.d.ts","sourceRoot":"","sources":["../../../src/controllers/LoginController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAwB,EAAE,EAAO,YAAY,EAAU,MAAM,eAAe,CAAC;AACpG,OAAO,EAAE,YAAY,EAAE,eAAe,EAAsB,aAAa,EAA0C,MAAM,eAAe,CAAC;AAGzI,OAAO,EAA6B,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAElF,OAAO,EAA0F,cAAc,EAAE,eAAe,EAAuB,MAAM,oBAAoB,CAAC;AAClL,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAKrE;;;;;GAKG;AACH,qBACa,eAAgB,SAAQ,cAAc;IAEjD,SAAS,CAAC,aAAa,EAAE,aAAa,CAAC;IAGvC,SAAS,CAAC,YAAY,EAAE,YAAY,CAAC;IAGrC,SAAS,CAAC,eAAe,EAAE,eAAe,CAAC;IAK3C,SAAS,CAAC,oBAAoB,EAAE,OAAO,CAAC;IAMxC,SAAS,CAAC,sBAAsB,EAAE,OAAO,CAAC;IAG1C,SAAS,CAAC,cAAc,EAAE,oBAAoB,CAAC;IAG/C,SAAS,CAAC,EAAE,EAAE,aAAa,CAAC;IAE5B;;;;;;;;;OASG;IAGU,KAAK,CAAiB,MAAM,EAAE,IAAI,EAAe,IAAI,EAAE,MAAM,EAAU,WAAW,EAAE,YAAY,GAAG,OAAO,CAAC,EAAE,CAAC,cAAc,CAAC,GAAG,YAAY,CAAC,CAqHzJ;IAED;;;;;;;;;;;;OAYG;IAGU,MAAM,CAAc,IAAI,EAAE,MAAM,EAAqB,OAAO,EAAE,QAAQ,EAAkB,IAAI,EAAE,IAAI,oBA8B9G;IAED;;;;;;;;;OASG;IAGU,MAAM,CAAiB,IAAI,EAAE,IAAI,EAAiB,UAAU,EAAE,MAAM,EAAqB,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAmBrJ;CACF"}
@@ -63,7 +63,16 @@ let LoginController = class LoginController extends BaseController {
63
63
  session.Data.set('Logged', true);
64
64
  session.UserId = user.Id;
65
65
  const twoFaEnabledForUser = Boolean(user.Metadata[TWO_FA_METATADATA_KEYS.ENABLED]);
66
- if (this.TwoFactorAuthForceUser && !twoFaEnabledForUser) {
66
+ // `forceUser` alone used to be enough to park the user in
67
+ // TwoFactorInitRequired. But every mutating `/user/2fa*` and
68
+ // `/auth/2fa/setup` route is now gated by `TwoFactorAuthEnabled` and
69
+ // answers 403 when `rbac.twoFactorAuth.enabled` is off — so a user forced into
70
+ // this branch while the system switch is off would have no route back
71
+ // out: setup2fa can no longer both enrol AND activate them. The
72
+ // system-wide switch has to gate this branch too, or every user without
73
+ // 2FA is locked out of the product the moment forceUser is on and the
74
+ // switch is off.
75
+ if (this.TwoFactorAuthEnabled && this.TwoFactorAuthForceUser && !twoFaEnabledForUser) {
67
76
  this._log.trace('User logged in, 2fa init required', {
68
77
  Uuid: user.Uuid
69
78
  });