@spinajs/rbac-http-user 2.0.486 → 2.0.487

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 (239) hide show
  1. package/lib/cjs/config/rbac-http.d.ts +0 -15
  2. package/lib/cjs/config/rbac-http.d.ts.map +1 -1
  3. package/lib/cjs/config/rbac-http.js +6 -16
  4. package/lib/cjs/config/rbac-http.js.map +1 -1
  5. package/lib/cjs/controllers/ActiveRoleController.d.ts +2 -1
  6. package/lib/cjs/controllers/ActiveRoleController.d.ts.map +1 -1
  7. package/lib/cjs/controllers/ActiveRoleController.js +7 -17
  8. package/lib/cjs/controllers/ActiveRoleController.js.map +1 -1
  9. package/lib/cjs/controllers/ImpersonationController.d.ts +7 -9
  10. package/lib/cjs/controllers/ImpersonationController.d.ts.map +1 -1
  11. package/lib/cjs/controllers/ImpersonationController.js +31 -56
  12. package/lib/cjs/controllers/ImpersonationController.js.map +1 -1
  13. package/lib/cjs/controllers/LoginController.d.ts +10 -3
  14. package/lib/cjs/controllers/LoginController.d.ts.map +1 -1
  15. package/lib/cjs/controllers/LoginController.js +39 -40
  16. package/lib/cjs/controllers/LoginController.js.map +1 -1
  17. package/lib/cjs/controllers/PasswordResetController.d.ts +54 -0
  18. package/lib/cjs/controllers/PasswordResetController.d.ts.map +1 -0
  19. package/lib/cjs/controllers/PasswordResetController.js +129 -0
  20. package/lib/cjs/controllers/PasswordResetController.js.map +1 -0
  21. package/lib/cjs/controllers/SessionsController.d.ts +65 -0
  22. package/lib/cjs/controllers/SessionsController.d.ts.map +1 -0
  23. package/lib/cjs/controllers/SessionsController.js +143 -0
  24. package/lib/cjs/controllers/SessionsController.js.map +1 -0
  25. package/lib/cjs/controllers/TwoFactorAuthController.d.ts +24 -23
  26. package/lib/cjs/controllers/TwoFactorAuthController.d.ts.map +1 -1
  27. package/lib/cjs/controllers/TwoFactorAuthController.js +39 -72
  28. package/lib/cjs/controllers/TwoFactorAuthController.js.map +1 -1
  29. package/lib/cjs/controllers/TwoFactorAuthUserController.d.ts +98 -0
  30. package/lib/cjs/controllers/TwoFactorAuthUserController.d.ts.map +1 -0
  31. package/lib/cjs/controllers/TwoFactorAuthUserController.js +195 -0
  32. package/lib/cjs/controllers/TwoFactorAuthUserController.js.map +1 -0
  33. package/lib/cjs/controllers/UserController.d.ts +10 -7
  34. package/lib/cjs/controllers/UserController.d.ts.map +1 -1
  35. package/lib/cjs/controllers/UserController.js +56 -58
  36. package/lib/cjs/controllers/UserController.js.map +1 -1
  37. package/lib/cjs/controllers/UserMetadataController.d.ts +6 -12
  38. package/lib/cjs/controllers/UserMetadataController.d.ts.map +1 -1
  39. package/lib/cjs/controllers/UserMetadataController.js +23 -72
  40. package/lib/cjs/controllers/UserMetadataController.js.map +1 -1
  41. package/lib/cjs/dto/confirm-password-dto.d.ts +23 -0
  42. package/lib/cjs/dto/confirm-password-dto.d.ts.map +1 -0
  43. package/lib/cjs/dto/{restore-password-dto.js → confirm-password-dto.js} +16 -12
  44. package/lib/cjs/dto/confirm-password-dto.js.map +1 -0
  45. package/lib/cjs/dto/password-reset-dto.d.ts +58 -0
  46. package/lib/cjs/dto/password-reset-dto.d.ts.map +1 -0
  47. package/lib/cjs/dto/password-reset-dto.js +57 -0
  48. package/lib/cjs/dto/password-reset-dto.js.map +1 -0
  49. package/lib/cjs/handlers/DefaultLogoutHandler.d.ts +4 -1
  50. package/lib/cjs/handlers/DefaultLogoutHandler.d.ts.map +1 -1
  51. package/lib/cjs/handlers/DefaultLogoutHandler.js +20 -13
  52. package/lib/cjs/handlers/DefaultLogoutHandler.js.map +1 -1
  53. package/lib/cjs/handlers/ImpersonationLogoutHandler.d.ts +4 -7
  54. package/lib/cjs/handlers/ImpersonationLogoutHandler.d.ts.map +1 -1
  55. package/lib/cjs/handlers/ImpersonationLogoutHandler.js +30 -31
  56. package/lib/cjs/handlers/ImpersonationLogoutHandler.js.map +1 -1
  57. package/lib/cjs/index.d.ts +20 -0
  58. package/lib/cjs/index.d.ts.map +1 -1
  59. package/lib/cjs/index.js +22 -0
  60. package/lib/cjs/index.js.map +1 -1
  61. package/lib/cjs/logout.d.ts +7 -0
  62. package/lib/cjs/logout.d.ts.map +1 -1
  63. package/lib/cjs/logout.js.map +1 -1
  64. package/lib/cjs/policies/2FaPolicy.d.ts +21 -1
  65. package/lib/cjs/policies/2FaPolicy.d.ts.map +1 -1
  66. package/lib/cjs/policies/2FaPolicy.js +31 -7
  67. package/lib/cjs/policies/2FaPolicy.js.map +1 -1
  68. package/lib/cjs/services/ImpersonationService.d.ts +90 -0
  69. package/lib/cjs/services/ImpersonationService.d.ts.map +1 -0
  70. package/lib/cjs/services/ImpersonationService.js +147 -0
  71. package/lib/cjs/services/ImpersonationService.js.map +1 -0
  72. package/lib/cjs/services/SessionCookies.d.ts +41 -0
  73. package/lib/cjs/services/SessionCookies.d.ts.map +1 -0
  74. package/lib/cjs/services/SessionCookies.js +62 -0
  75. package/lib/cjs/services/SessionCookies.js.map +1 -0
  76. package/lib/cjs/services/UserMetadataService.d.ts +53 -0
  77. package/lib/cjs/services/UserMetadataService.d.ts.map +1 -0
  78. package/lib/cjs/services/UserMetadataService.js +94 -0
  79. package/lib/cjs/services/UserMetadataService.js.map +1 -0
  80. package/lib/cjs/services/grants.d.ts +29 -0
  81. package/lib/cjs/services/grants.d.ts.map +1 -0
  82. package/lib/cjs/services/grants.js +43 -0
  83. package/lib/cjs/services/grants.js.map +1 -0
  84. package/lib/mjs/config/rbac-http.d.ts +0 -15
  85. package/lib/mjs/config/rbac-http.d.ts.map +1 -1
  86. package/lib/mjs/config/rbac-http.js +6 -16
  87. package/lib/mjs/config/rbac-http.js.map +1 -1
  88. package/lib/mjs/controllers/ActiveRoleController.d.ts +2 -1
  89. package/lib/mjs/controllers/ActiveRoleController.d.ts.map +1 -1
  90. package/lib/mjs/controllers/ActiveRoleController.js +8 -18
  91. package/lib/mjs/controllers/ActiveRoleController.js.map +1 -1
  92. package/lib/mjs/controllers/ImpersonationController.d.ts +7 -9
  93. package/lib/mjs/controllers/ImpersonationController.d.ts.map +1 -1
  94. package/lib/mjs/controllers/ImpersonationController.js +32 -57
  95. package/lib/mjs/controllers/ImpersonationController.js.map +1 -1
  96. package/lib/mjs/controllers/LoginController.d.ts +10 -3
  97. package/lib/mjs/controllers/LoginController.d.ts.map +1 -1
  98. package/lib/mjs/controllers/LoginController.js +42 -43
  99. package/lib/mjs/controllers/LoginController.js.map +1 -1
  100. package/lib/mjs/controllers/PasswordResetController.d.ts +54 -0
  101. package/lib/mjs/controllers/PasswordResetController.d.ts.map +1 -0
  102. package/lib/mjs/controllers/PasswordResetController.js +126 -0
  103. package/lib/mjs/controllers/PasswordResetController.js.map +1 -0
  104. package/lib/mjs/controllers/SessionsController.d.ts +65 -0
  105. package/lib/mjs/controllers/SessionsController.d.ts.map +1 -0
  106. package/lib/mjs/controllers/SessionsController.js +140 -0
  107. package/lib/mjs/controllers/SessionsController.js.map +1 -0
  108. package/lib/mjs/controllers/TwoFactorAuthController.d.ts +24 -23
  109. package/lib/mjs/controllers/TwoFactorAuthController.d.ts.map +1 -1
  110. package/lib/mjs/controllers/TwoFactorAuthController.js +43 -76
  111. package/lib/mjs/controllers/TwoFactorAuthController.js.map +1 -1
  112. package/lib/mjs/controllers/TwoFactorAuthUserController.d.ts +98 -0
  113. package/lib/mjs/controllers/TwoFactorAuthUserController.d.ts.map +1 -0
  114. package/lib/mjs/controllers/TwoFactorAuthUserController.js +192 -0
  115. package/lib/mjs/controllers/TwoFactorAuthUserController.js.map +1 -0
  116. package/lib/mjs/controllers/UserController.d.ts +10 -7
  117. package/lib/mjs/controllers/UserController.d.ts.map +1 -1
  118. package/lib/mjs/controllers/UserController.js +59 -28
  119. package/lib/mjs/controllers/UserController.js.map +1 -1
  120. package/lib/mjs/controllers/UserMetadataController.d.ts +6 -12
  121. package/lib/mjs/controllers/UserMetadataController.d.ts.map +1 -1
  122. package/lib/mjs/controllers/UserMetadataController.js +23 -72
  123. package/lib/mjs/controllers/UserMetadataController.js.map +1 -1
  124. package/lib/mjs/dto/confirm-password-dto.d.ts +23 -0
  125. package/lib/mjs/dto/confirm-password-dto.d.ts.map +1 -0
  126. package/lib/mjs/dto/{user-dto.js → confirm-password-dto.js} +15 -10
  127. package/lib/mjs/dto/confirm-password-dto.js.map +1 -0
  128. package/lib/mjs/dto/password-reset-dto.d.ts +58 -0
  129. package/lib/mjs/dto/password-reset-dto.d.ts.map +1 -0
  130. package/lib/mjs/dto/password-reset-dto.js +54 -0
  131. package/lib/mjs/dto/password-reset-dto.js.map +1 -0
  132. package/lib/mjs/handlers/DefaultLogoutHandler.d.ts +4 -1
  133. package/lib/mjs/handlers/DefaultLogoutHandler.d.ts.map +1 -1
  134. package/lib/mjs/handlers/DefaultLogoutHandler.js +23 -16
  135. package/lib/mjs/handlers/DefaultLogoutHandler.js.map +1 -1
  136. package/lib/mjs/handlers/ImpersonationLogoutHandler.d.ts +4 -7
  137. package/lib/mjs/handlers/ImpersonationLogoutHandler.d.ts.map +1 -1
  138. package/lib/mjs/handlers/ImpersonationLogoutHandler.js +31 -32
  139. package/lib/mjs/handlers/ImpersonationLogoutHandler.js.map +1 -1
  140. package/lib/mjs/index.d.ts +20 -0
  141. package/lib/mjs/index.d.ts.map +1 -1
  142. package/lib/mjs/index.js +22 -0
  143. package/lib/mjs/index.js.map +1 -1
  144. package/lib/mjs/logout.d.ts +7 -0
  145. package/lib/mjs/logout.d.ts.map +1 -1
  146. package/lib/mjs/logout.js.map +1 -1
  147. package/lib/mjs/policies/2FaPolicy.d.ts +21 -1
  148. package/lib/mjs/policies/2FaPolicy.d.ts.map +1 -1
  149. package/lib/mjs/policies/2FaPolicy.js +29 -6
  150. package/lib/mjs/policies/2FaPolicy.js.map +1 -1
  151. package/lib/mjs/services/ImpersonationService.d.ts +90 -0
  152. package/lib/mjs/services/ImpersonationService.d.ts.map +1 -0
  153. package/lib/mjs/services/ImpersonationService.js +144 -0
  154. package/lib/mjs/services/ImpersonationService.js.map +1 -0
  155. package/lib/mjs/services/SessionCookies.d.ts +41 -0
  156. package/lib/mjs/services/SessionCookies.d.ts.map +1 -0
  157. package/lib/mjs/services/SessionCookies.js +59 -0
  158. package/lib/mjs/services/SessionCookies.js.map +1 -0
  159. package/lib/mjs/services/UserMetadataService.d.ts +53 -0
  160. package/lib/mjs/services/UserMetadataService.d.ts.map +1 -0
  161. package/lib/mjs/services/UserMetadataService.js +91 -0
  162. package/lib/mjs/services/UserMetadataService.js.map +1 -0
  163. package/lib/mjs/services/grants.d.ts +29 -0
  164. package/lib/mjs/services/grants.d.ts.map +1 -0
  165. package/lib/mjs/services/grants.js +38 -0
  166. package/lib/mjs/services/grants.js.map +1 -0
  167. package/lib/tsconfig.cjs.tsbuildinfo +1 -1
  168. package/lib/tsconfig.mjs.tsbuildinfo +1 -1
  169. package/package.json +17 -11
  170. package/lib/cjs/controllers/AuthController.d.ts +0 -1
  171. package/lib/cjs/controllers/AuthController.d.ts.map +0 -1
  172. package/lib/cjs/controllers/AuthController.js +0 -211
  173. package/lib/cjs/controllers/AuthController.js.map +0 -1
  174. package/lib/cjs/controllers/FederatedLoginController.d.ts +0 -1
  175. package/lib/cjs/controllers/FederatedLoginController.d.ts.map +0 -1
  176. package/lib/cjs/controllers/FederatedLoginController.js +0 -38
  177. package/lib/cjs/controllers/FederatedLoginController.js.map +0 -1
  178. package/lib/cjs/dto/login-dto.d.ts +0 -17
  179. package/lib/cjs/dto/login-dto.d.ts.map +0 -1
  180. package/lib/cjs/dto/login-dto.js +0 -33
  181. package/lib/cjs/dto/login-dto.js.map +0 -1
  182. package/lib/cjs/dto/restore-password-dto.d.ts +0 -24
  183. package/lib/cjs/dto/restore-password-dto.d.ts.map +0 -1
  184. package/lib/cjs/dto/restore-password-dto.js.map +0 -1
  185. package/lib/cjs/dto/user-dto.d.ts +0 -22
  186. package/lib/cjs/dto/user-dto.d.ts.map +0 -1
  187. package/lib/cjs/dto/user-dto.js +0 -33
  188. package/lib/cjs/dto/user-dto.js.map +0 -1
  189. package/lib/cjs/fingerprint/FingerprintJs.d.ts +0 -1
  190. package/lib/cjs/fingerprint/FingerprintJs.d.ts.map +0 -1
  191. package/lib/cjs/fingerprint/FingerprintJs.js +0 -5
  192. package/lib/cjs/fingerprint/FingerprintJs.js.map +0 -1
  193. package/lib/cjs/middlewares/AttributeFilter.d.ts +0 -11
  194. package/lib/cjs/middlewares/AttributeFilter.d.ts.map +0 -1
  195. package/lib/cjs/middlewares/AttributeFilter.js +0 -19
  196. package/lib/cjs/middlewares/AttributeFilter.js.map +0 -1
  197. package/lib/cjs/policies/AllowFederatedLoginPolicy.d.ts +0 -7
  198. package/lib/cjs/policies/AllowFederatedLoginPolicy.d.ts.map +0 -1
  199. package/lib/cjs/policies/AllowFederatedLoginPolicy.js +0 -32
  200. package/lib/cjs/policies/AllowFederatedLoginPolicy.js.map +0 -1
  201. package/lib/cjs/policies/CaptchaPolicy.d.ts +0 -1
  202. package/lib/cjs/policies/CaptchaPolicy.d.ts.map +0 -1
  203. package/lib/cjs/policies/CaptchaPolicy.js +0 -1
  204. package/lib/cjs/policies/CaptchaPolicy.js.map +0 -1
  205. package/lib/mjs/controllers/AuthController.d.ts +0 -2
  206. package/lib/mjs/controllers/AuthController.d.ts.map +0 -1
  207. package/lib/mjs/controllers/AuthController.js +0 -212
  208. package/lib/mjs/controllers/AuthController.js.map +0 -1
  209. package/lib/mjs/controllers/FederatedLoginController.d.ts +0 -2
  210. package/lib/mjs/controllers/FederatedLoginController.d.ts.map +0 -1
  211. package/lib/mjs/controllers/FederatedLoginController.js +0 -39
  212. package/lib/mjs/controllers/FederatedLoginController.js.map +0 -1
  213. package/lib/mjs/dto/login-dto.d.ts +0 -17
  214. package/lib/mjs/dto/login-dto.d.ts.map +0 -1
  215. package/lib/mjs/dto/login-dto.js +0 -30
  216. package/lib/mjs/dto/login-dto.js.map +0 -1
  217. package/lib/mjs/dto/restore-password-dto.d.ts +0 -24
  218. package/lib/mjs/dto/restore-password-dto.d.ts.map +0 -1
  219. package/lib/mjs/dto/restore-password-dto.js +0 -31
  220. package/lib/mjs/dto/restore-password-dto.js.map +0 -1
  221. package/lib/mjs/dto/user-dto.d.ts +0 -22
  222. package/lib/mjs/dto/user-dto.d.ts.map +0 -1
  223. package/lib/mjs/dto/user-dto.js.map +0 -1
  224. package/lib/mjs/fingerprint/FingerprintJs.d.ts +0 -2
  225. package/lib/mjs/fingerprint/FingerprintJs.d.ts.map +0 -1
  226. package/lib/mjs/fingerprint/FingerprintJs.js +0 -6
  227. package/lib/mjs/fingerprint/FingerprintJs.js.map +0 -1
  228. package/lib/mjs/middlewares/AttributeFilter.d.ts +0 -11
  229. package/lib/mjs/middlewares/AttributeFilter.d.ts.map +0 -1
  230. package/lib/mjs/middlewares/AttributeFilter.js +0 -15
  231. package/lib/mjs/middlewares/AttributeFilter.js.map +0 -1
  232. package/lib/mjs/policies/AllowFederatedLoginPolicy.d.ts +0 -7
  233. package/lib/mjs/policies/AllowFederatedLoginPolicy.d.ts.map +0 -1
  234. package/lib/mjs/policies/AllowFederatedLoginPolicy.js +0 -28
  235. package/lib/mjs/policies/AllowFederatedLoginPolicy.js.map +0 -1
  236. package/lib/mjs/policies/CaptchaPolicy.d.ts +0 -2
  237. package/lib/mjs/policies/CaptchaPolicy.d.ts.map +0 -1
  238. package/lib/mjs/policies/CaptchaPolicy.js +0 -2
  239. package/lib/mjs/policies/CaptchaPolicy.js.map +0 -1
@@ -1,41 +1,42 @@
1
1
  import { TokenDto } from './../dto/token-dto.js';
2
2
  import { BaseController, Ok, ForbiddenResponse } from '@spinajs/http';
3
3
  import { ISession, SessionProvider, User as UserModel, AccessControl } from '@spinajs/rbac';
4
- import { QueueService } from '@spinajs/queue';
5
- import { IEnable2faResponse, IUserWithGrants } from "@spinajs/rbac-http";
4
+ import { IEnable2faResponse, IUserWithGrants } from '@spinajs/rbac-http';
5
+ import { SessionCookieFactory } from '../services/SessionCookies.js';
6
6
  /**
7
- * Two-factor authentication (TOTP) management.
8
- * Enables, disables, and verifies TOTP-based two-factor authentication for users.
9
- * All routes are only available when 2FA is enabled in the system configuration.
10
- * The caller must be logged in but does NOT need to be fully authorized (2FA verified),
11
- * allowing these routes to be used during the 2FA verification step itself.
7
+ * Two-factor authentication during login.
8
+ *
9
+ * These routes serve the narrow window between a successful password check and
10
+ * full authorization: the session is `Logged` but not `Authorized` and carries
11
+ * the `TwoFactorAuth` marker. Both class policies must hold, so the window
12
+ * closes the moment verification succeeds.
13
+ *
14
+ * Managing a TOTP device outside that window — enrolling for the first time, or
15
+ * turning 2FA off — lives on {@link TwoFactorAuthUserController} under
16
+ * `/user/2fa`, where the caller is fully authorized. Notably there is no
17
+ * "disable" here on purpose: a session that has not yet proven possession of
18
+ * the second factor must not be able to remove it, which would reduce the whole
19
+ * scheme to the password alone.
20
+ *
12
21
  * @tags Two-Factor Authentication
13
22
  */
14
23
  export declare class TwoFactorAuthController extends BaseController {
15
- protected Queue: QueueService;
16
24
  protected SessionProvider: SessionProvider;
17
- protected SessionCookieConfig: any;
25
+ protected SessionCookies: SessionCookieFactory;
18
26
  protected AC: AccessControl;
19
27
  /**
20
- * Enable two-factor authentication
21
- * Generates a TOTP secret for the authenticated user and returns the OTP provisioning URI
22
- * to be scanned by an authenticator app. Throws if 2FA is already enabled for the user.
28
+ * Set up two-factor authentication during login
29
+ * Generates a TOTP secret for a user who must enrol before continuing — the state
30
+ * signalled by `TwoFactorInitRequired` at login when `rbac.twoFactorAuth.forceUser`
31
+ * is on. Returns the OTP provisioning URI to scan with an authenticator app; the
32
+ * caller then confirms with `POST /auth/2fa/verify`.
23
33
  * @security cookieAuth
24
34
  * @returns {IEnable2faResponse} OTP provisioning URI to scan with an authenticator app
25
35
  * @response 400 Two-factor authentication is already enabled for this user
26
36
  * @response 401 Unauthorized — valid session required
37
+ * @response 403 Session is not awaiting two-factor enrolment
27
38
  */
28
- enable2fa(user: UserModel): Promise<Ok<IEnable2faResponse>>;
29
- /**
30
- * Disable two-factor authentication
31
- * Removes the TOTP secret and disables 2FA for the authenticated user.
32
- * Throws if 2FA is not currently enabled for the user.
33
- * @security cookieAuth
34
- * @response 200 Two-factor authentication disabled successfully
35
- * @response 400 Two-factor authentication is not enabled for this user
36
- * @response 401 Unauthorized — valid session required
37
- */
38
- disable2Fa(user: UserModel): Promise<Ok<any>>;
39
+ setup2fa(user: UserModel): Promise<Ok<IEnable2faResponse>>;
39
40
  /**
40
41
  * Verify TOTP token
41
42
  * Validates the provided TOTP token against the user's 2FA secret. On success, marks the session
@@ -1 +1 @@
1
- {"version":3,"file":"TwoFactorAuthController.d.ts","sourceRoot":"","sources":["../../../src/controllers/TwoFactorAuthController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAY,EAAE,EAAa,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC3F,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,IAAI,IAAI,SAAS,EAAyC,aAAa,EAA0C,MAAM,eAAe,CAAC;AAO3K,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,EAA6B,kBAAkB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAKpG;;;;;;;GAOG;AACH,qBAGa,uBAAwB,SAAQ,cAAc;IAEvD,SAAS,CAAC,KAAK,EAAE,YAAY,CAAC;IAG9B,SAAS,CAAC,eAAe,EAAE,eAAe,CAAC;IAG3C,SAAS,CAAC,mBAAmB,EAAE,GAAG,CAAC;IAGnC,SAAS,CAAC,EAAE,EAAE,aAAa,CAAC;IAE5B;;;;;;;;OAQG;IAEU,SAAS,CAAS,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC;IAYhF;;;;;;;;OAQG;IAEU,UAAU,CAAS,IAAI,EAAE,SAAS;IAS/C;;;;;;;;OAQG;IAEU,WAAW,CAAS,MAAM,EAAE,SAAS,EAAU,KAAK,EAAE,QAAQ,EAAa,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,EAAE,CAAC,eAAe,CAAC,GAAG,iBAAiB,CAAC;IAgE5J;;;;OAIG;IACH,SAAS,CAAC,oBAAoB,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGhF"}
1
+ {"version":3,"file":"TwoFactorAuthController.d.ts","sourceRoot":"","sources":["../../../src/controllers/TwoFactorAuthController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAY,EAAE,EAAQ,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACtF,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,IAAI,IAAI,SAAS,EAAE,aAAa,EAAqB,MAAM,eAAe,CAAC;AAO/G,OAAO,EAA6B,kBAAkB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAIpG,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAGrE;;;;;;;;;;;;;;;;GAgBG;AACH,qBAGa,uBAAwB,SAAQ,cAAc;IAEzD,SAAS,CAAC,eAAe,EAAE,eAAe,CAAC;IAG3C,SAAS,CAAC,cAAc,EAAE,oBAAoB,CAAC;IAG/C,SAAS,CAAC,EAAE,EAAE,aAAa,CAAC;IAE5B;;;;;;;;;;;OAWG;IAEU,QAAQ,CAAS,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC;IAW/E;;;;;;;;OAQG;IAEU,WAAW,CAAS,MAAM,EAAE,SAAS,EAAU,KAAK,EAAE,QAAQ,EAAa,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,EAAE,CAAC,eAAe,CAAC,GAAG,iBAAiB,CAAC;IAyC5J;;;;OAIG;IACH,SAAS,CAAC,oBAAoB,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG9E"}
@@ -21,54 +21,51 @@ const http_2 = require("@spinajs/http");
21
21
  const _2FaPolicy_js_1 = require("../policies/2FaPolicy.js");
22
22
  const configuration_1 = require("@spinajs/configuration");
23
23
  const di_1 = require("@spinajs/di");
24
- const queue_1 = require("@spinajs/queue");
25
24
  const rbac_http_2 = require("@spinajs/rbac-http");
26
- const _2fa_js_1 = require("./../actions/2fa.js");
27
- const _2fa_js_2 = require("../actions/2fa.js");
25
+ const _2fa_js_1 = require("../actions/2fa.js");
28
26
  const exceptions_1 = require("@spinajs/exceptions");
27
+ const Default2FaToken_js_1 = require("../2fa/Default2FaToken.js");
28
+ const SessionCookies_js_1 = require("../services/SessionCookies.js");
29
+ const grants_js_1 = require("../services/grants.js");
29
30
  /**
30
- * Two-factor authentication (TOTP) management.
31
- * Enables, disables, and verifies TOTP-based two-factor authentication for users.
32
- * All routes are only available when 2FA is enabled in the system configuration.
33
- * The caller must be logged in but does NOT need to be fully authorized (2FA verified),
34
- * allowing these routes to be used during the 2FA verification step itself.
31
+ * Two-factor authentication during login.
32
+ *
33
+ * These routes serve the narrow window between a successful password check and
34
+ * full authorization: the session is `Logged` but not `Authorized` and carries
35
+ * the `TwoFactorAuth` marker. Both class policies must hold, so the window
36
+ * closes the moment verification succeeds.
37
+ *
38
+ * Managing a TOTP device outside that window — enrolling for the first time, or
39
+ * turning 2FA off — lives on {@link TwoFactorAuthUserController} under
40
+ * `/user/2fa`, where the caller is fully authorized. Notably there is no
41
+ * "disable" here on purpose: a session that has not yet proven possession of
42
+ * the second factor must not be able to remove it, which would reduce the whole
43
+ * scheme to the password alone.
44
+ *
35
45
  * @tags Two-Factor Authentication
36
46
  */
37
47
  let TwoFactorAuthController = class TwoFactorAuthController extends http_1.BaseController {
38
48
  /**
39
- * Enable two-factor authentication
40
- * Generates a TOTP secret for the authenticated user and returns the OTP provisioning URI
41
- * to be scanned by an authenticator app. Throws if 2FA is already enabled for the user.
49
+ * Set up two-factor authentication during login
50
+ * Generates a TOTP secret for a user who must enrol before continuing — the state
51
+ * signalled by `TwoFactorInitRequired` at login when `rbac.twoFactorAuth.forceUser`
52
+ * is on. Returns the OTP provisioning URI to scan with an authenticator app; the
53
+ * caller then confirms with `POST /auth/2fa/verify`.
42
54
  * @security cookieAuth
43
55
  * @returns {IEnable2faResponse} OTP provisioning URI to scan with an authenticator app
44
56
  * @response 400 Two-factor authentication is already enabled for this user
45
57
  * @response 401 Unauthorized — valid session required
58
+ * @response 403 Session is not awaiting two-factor enrolment
46
59
  */
47
- async enable2fa(user) {
48
- if (user.Metadata['2fa:enabled']) {
60
+ async setup2fa(user) {
61
+ if (user.Metadata[Default2FaToken_js_1.TWO_FA_METATADATA_KEYS.ENABLED]) {
49
62
  throw new exceptions_1.InvalidOperation(`User ${user.Uuid} already has 2fa enabled`);
50
63
  }
51
- const result = await (0, _2fa_js_2.enableUser2Fa)(user);
64
+ const result = await (0, _2fa_js_1.enableUser2Fa)(user);
52
65
  return new http_1.Ok({
53
- otp: result
66
+ otp: result,
54
67
  });
55
68
  }
56
- /**
57
- * Disable two-factor authentication
58
- * Removes the TOTP secret and disables 2FA for the authenticated user.
59
- * Throws if 2FA is not currently enabled for the user.
60
- * @security cookieAuth
61
- * @response 200 Two-factor authentication disabled successfully
62
- * @response 400 Two-factor authentication is not enabled for this user
63
- * @response 401 Unauthorized — valid session required
64
- */
65
- async disable2Fa(user) {
66
- if (!user.Metadata['2fa:enabled']) {
67
- throw new exceptions_1.InvalidOperation(`User ${user.Uuid} already has 2fa disabled`);
68
- }
69
- await (0, _2fa_js_1.disableUser2Fa)(user);
70
- return new http_1.Ok();
71
- }
72
69
  /**
73
70
  * Verify TOTP token
74
71
  * Validates the provided TOTP token against the user's 2FA secret. On success, marks the session
@@ -89,41 +86,22 @@ let TwoFactorAuthController = class TwoFactorAuthController extends http_1.BaseC
89
86
  // id to defend against session fixation and reset the ssid cookie.
90
87
  const regenerated = await (0, rbac_1.regenerateSession)(this.SessionProvider, session);
91
88
  this._log.trace('User logged in, 2fa authorized', {
92
- Uuid: logged.Uuid
89
+ Uuid: logged.Uuid,
93
90
  });
94
91
  // Mirror the login response shape: resolve grants for the session's
95
92
  // active role (falling back to the first role) and include ActiveRole,
96
93
  // instead of flattening every role with no ActiveRole reported.
97
- const activeRole = session.Data.get('ActiveRole') ?? logged.Role?.[0];
98
- const combinedGrants = activeRole ? (0, rbac_1._unwindGrants)(activeRole, this.AC.getGrants()) : {};
99
- return new http_1.Ok({
100
- ...logged.dehydrateWithRelations({
101
- dateTimeFormat: "iso"
102
- }),
103
- Role: logged.Role,
104
- ActiveRole: activeRole,
105
- Grants: combinedGrants,
106
- }, {
107
- Coockies: [
108
- {
109
- Name: 'ssid',
110
- Value: regenerated.SessionId,
111
- Options: {
112
- signed: true,
113
- httpOnly: true,
114
- maxAge: (0, rbac_1.sessionCookieMaxAge)(regenerated),
115
- ...this.SessionCookieConfig,
116
- },
117
- },
118
- ],
94
+ const activeRole = (0, grants_js_1.activeRoleOf)(logged, session);
95
+ return new http_1.Ok((0, grants_js_1.buildUserWithGrants)(logged, activeRole, this.AC), {
96
+ Coockies: [this.SessionCookies.issue(regenerated)],
119
97
  });
120
98
  }
121
99
  catch (err) {
122
100
  if (err instanceof Error) {
123
- this._log.error(err, "2fa verification failed");
101
+ this._log.error(err, '2fa verification failed');
124
102
  }
125
103
  else {
126
- this._log.error("2fa verification failed", { error: err });
104
+ this._log.error('2fa verification failed', { error: err });
127
105
  }
128
106
  return new http_1.ForbiddenResponse({
129
107
  error: {
@@ -143,36 +121,25 @@ let TwoFactorAuthController = class TwoFactorAuthController extends http_1.BaseC
143
121
  }
144
122
  };
145
123
  exports.TwoFactorAuthController = TwoFactorAuthController;
146
- __decorate([
147
- (0, di_1.Autoinject)(queue_1.QueueService),
148
- __metadata("design:type", queue_1.QueueService)
149
- ], TwoFactorAuthController.prototype, "Queue", void 0);
150
124
  __decorate([
151
125
  (0, configuration_1.AutoinjectService)('rbac.session'),
152
126
  __metadata("design:type", rbac_1.SessionProvider)
153
127
  ], TwoFactorAuthController.prototype, "SessionProvider", void 0);
154
128
  __decorate([
155
- (0, configuration_1.Config)('rbac.session.cookie', {}),
156
- __metadata("design:type", Object)
157
- ], TwoFactorAuthController.prototype, "SessionCookieConfig", void 0);
129
+ (0, di_1.Autoinject)(SessionCookies_js_1.SessionCookieFactory),
130
+ __metadata("design:type", SessionCookies_js_1.SessionCookieFactory)
131
+ ], TwoFactorAuthController.prototype, "SessionCookies", void 0);
158
132
  __decorate([
159
133
  (0, di_1.Autoinject)(rbac_1.AccessControl),
160
134
  __metadata("design:type", rbac_1.AccessControl)
161
135
  ], TwoFactorAuthController.prototype, "AC", void 0);
162
136
  __decorate([
163
- (0, http_1.Get)('2fa/enable'),
164
- __param(0, (0, rbac_http_2.User)()),
165
- __metadata("design:type", Function),
166
- __metadata("design:paramtypes", [rbac_1.User]),
167
- __metadata("design:returntype", Promise)
168
- ], TwoFactorAuthController.prototype, "enable2fa", null);
169
- __decorate([
170
- (0, http_1.Get)('2fa/disable'),
137
+ (0, http_1.Post)('2fa/setup'),
171
138
  __param(0, (0, rbac_http_2.User)()),
172
139
  __metadata("design:type", Function),
173
140
  __metadata("design:paramtypes", [rbac_1.User]),
174
141
  __metadata("design:returntype", Promise)
175
- ], TwoFactorAuthController.prototype, "disable2Fa", null);
142
+ ], TwoFactorAuthController.prototype, "setup2fa", null);
176
143
  __decorate([
177
144
  (0, http_1.Post)('2fa/verify'),
178
145
  __param(0, (0, rbac_http_2.User)()),
@@ -1 +1 @@
1
- {"version":3,"file":"TwoFactorAuthController.js","sourceRoot":"","sources":["../../../src/controllers/TwoFactorAuthController.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,wDAAiD;AACjD,wCAA2F;AAC3F,wCAA2K;AAC3K,kDAA6C;AAC7C,wCAA6C;AAE7C,4DAA8D;AAC9D,0DAA6E;AAC7E,oCAAyC;AACzC,0CAA8C;AAE9C,kDAAoG;AACpG,iDAA8D;AAC9D,+CAAkD;AAClD,oDAAuD;AAEvD;;;;;;;GAOG;AAII,IAAM,uBAAuB,GAA7B,MAAM,uBAAwB,SAAQ,qBAAc;IAavD;;;;;;;;OAQG;IAEU,AAAN,KAAK,CAAC,SAAS,CAAS,IAAe;QAE1C,IAAI,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;YAC/B,MAAM,IAAI,6BAAgB,CAAC,QAAQ,IAAI,CAAC,IAAI,0BAA0B,CAAC,CAAC;QAC5E,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,IAAA,uBAAa,EAAC,IAAI,CAAC,CAAC;QACzC,OAAO,IAAI,SAAE,CAAC;YACV,GAAG,EAAE,MAAgB;SACxB,CAAC,CAAC;IACP,CAAC;IAED;;;;;;;;OAQG;IAEU,AAAN,KAAK,CAAC,UAAU,CAAS,IAAe;QAC3C,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,6BAAgB,CAAC,QAAQ,IAAI,CAAC,IAAI,2BAA2B,CAAC,CAAC;QAC7E,CAAC;QAED,MAAM,IAAA,wBAAc,EAAC,IAAI,CAAC,CAAC;QAC3B,OAAO,IAAI,SAAE,EAAE,CAAC;IACpB,CAAC;IAED;;;;;;;;OAQG;IAEU,AAAN,KAAK,CAAC,WAAW,CAAS,MAAiB,EAAU,KAAe,EAAa,OAAiB;QAErG,IAAI,CAAC;YACD,MAAM,IAAI,CAAC,oBAAoB,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;YAErD,mCAAmC;YACnC,4CAA4C;YAC5C,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;YACrC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;YAErC,qEAAqE;YACrE,mEAAmE;YACnE,MAAM,WAAW,GAAG,MAAM,IAAA,wBAAiB,EAAC,IAAI,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;YAE3E,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,gCAAgC,EAAE;gBAC9C,IAAI,EAAE,MAAM,CAAC,IAAI;aACpB,CAAC,CAAC;YAGH,oEAAoE;YACpE,uEAAuE;YACvE,gEAAgE;YAChE,MAAM,UAAU,GAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAwB,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAC9F,MAAM,cAAc,GAAG,UAAU,CAAC,CAAC,CAAC,IAAA,oBAAa,EAAC,UAAU,EAAE,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAExF,OAAO,IAAI,SAAE,CAAC;gBACV,GAAG,MAAM,CAAC,sBAAsB,CAAC;oBAC7B,cAAc,EAAE,KAAK;iBACxB,CAAC;gBACF,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,UAAU,EAAE,UAAU;gBACtB,MAAM,EAAE,cAAc;aACK,EAAE;gBAC7B,QAAQ,EAAE;oBACN;wBACI,IAAI,EAAE,MAAM;wBACZ,KAAK,EAAE,WAAW,CAAC,SAAS;wBAC5B,OAAO,EAAE;4BACL,MAAM,EAAE,IAAI;4BACZ,QAAQ,EAAE,IAAI;4BACd,MAAM,EAAE,IAAA,0BAAmB,EAAC,WAAW,CAAC;4BACxC,GAAG,IAAI,CAAC,mBAAmB;yBAC9B;qBACJ;iBACJ;aACJ,CAAC,CAAC;QACP,CAAC;QACD,OAAO,GAAG,EAAE,CAAC;YAET,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;gBACvB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,yBAAyB,CAAC,CAAC;YACpD,CAAC;iBAAM,CAAC;gBACJ,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,yBAAyB,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;YAC/D,CAAC;YAED,OAAO,IAAI,wBAAiB,CAAC;gBACzB,KAAK,EAAE;oBACH,IAAI,EAAE,cAAc;oBACpB,OAAO,EAAE,kBAAkB;iBAC9B;aACJ,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAED;;;;OAIG;IACO,oBAAoB,CAAC,IAAe,EAAE,KAAa;QACzD,OAAO,IAAA,iBAAO,EAAC,IAAI,EAAE,KAAK,CAAkB,CAAC;IACjD,CAAC;CACJ,CAAA;AAxIY,0DAAuB;AAEtB;IADT,IAAA,eAAU,EAAC,oBAAY,CAAC;8BACR,oBAAY;sDAAC;AAGpB;IADT,IAAA,iCAAiB,EAAC,cAAc,CAAC;8BACP,sBAAe;gEAAC;AAGjC;IADT,IAAA,sBAAM,EAAC,qBAAqB,EAAE,EAAE,CAAC;;oEACC;AAGzB;IADT,IAAA,eAAU,EAAC,oBAAa,CAAC;8BACZ,oBAAa;mDAAC;AAYf;IADZ,IAAA,UAAG,EAAC,YAAY,CAAC;IACM,WAAA,IAAA,gBAAI,GAAE,CAAA;;qCAAO,WAAS;;wDAU7C;AAYY;IADZ,IAAA,UAAG,EAAC,aAAa,CAAC;IACM,WAAA,IAAA,gBAAI,GAAE,CAAA;;qCAAO,WAAS;;yDAO9C;AAYY;IADZ,IAAA,WAAI,EAAC,YAAY,CAAC;IACO,WAAA,IAAA,gBAAI,GAAE,CAAA;IAAqB,WAAA,IAAA,WAAI,GAAE,CAAA;IAAmB,WAAA,IAAA,mBAAO,GAAE,CAAA;;qCAA9C,WAAS,EAAiB,uBAAQ;;0DA8D1E;kCA9HQ,uBAAuB;IAHnC,IAAA,eAAQ,EAAC,MAAM,CAAC;IAChB,IAAA,aAAM,EAAC,kCAAkB,CAAC;IAC1B,IAAA,aAAM,EAAC,+BAAmB,CAAC;GACf,uBAAuB,CAwInC"}
1
+ {"version":3,"file":"TwoFactorAuthController.js","sourceRoot":"","sources":["../../../src/controllers/TwoFactorAuthController.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ import { BaseController, Ok, Unauthorized } from '@spinajs/http';
2
+ import { PasswordProvider, SessionProvider, User as UserModel } from '@spinajs/rbac';
3
+ import type { ISession } from '@spinajs/rbac';
4
+ import { IEnable2faResponse } from '@spinajs/rbac-http';
5
+ import { ConfirmPasswordDto } from '../dto/confirm-password-dto.js';
6
+ import { SessionCookieFactory } from '../services/SessionCookies.js';
7
+ /** Whether the authenticated user currently has a TOTP device enrolled. */
8
+ export interface ITwoFactorStatus {
9
+ Enabled: boolean;
10
+ }
11
+ /**
12
+ * Self-service two-factor authentication.
13
+ *
14
+ * Enrolling and unenrolling a TOTP device for one's own account, from a fully
15
+ * authorized session. These operations were previously only reachable from the
16
+ * login-time 2FA window, whose policies (`TwoFacRouteEnabled` +
17
+ * `NotAuthorizedPolicy`) exclude an authorized session by construction — so a
18
+ * normal logged-in user could neither enrol nor unenrol, and the only ways in
19
+ * were the CLI command or an administrator's 2FA reset.
20
+ *
21
+ * Both mutations re-verify the account password. A stolen session cookie must
22
+ * not be enough to attach an attacker-controlled authenticator or to strip the
23
+ * second factor off the account.
24
+ *
25
+ * @tags Two-Factor Authentication
26
+ */
27
+ export declare class TwoFactorAuthUserController extends BaseController {
28
+ protected PasswordProvider: PasswordProvider;
29
+ protected SessionProvider: SessionProvider;
30
+ protected SessionCookies: SessionCookieFactory;
31
+ /**
32
+ * Get own two-factor status
33
+ * Reports whether the authenticated user currently has a TOTP device enrolled.
34
+ * @security cookieAuth
35
+ * @returns {ITwoFactorStatus} Current enrolment state
36
+ * @response 401 Unauthorized — valid session required
37
+ * @response 403 Forbidden — insufficient permissions
38
+ */
39
+ status(user: UserModel): Promise<Ok<ITwoFactorStatus>>;
40
+ /**
41
+ * Enable own two-factor authentication
42
+ * Generates a TOTP secret for the authenticated user and returns the OTP provisioning
43
+ * URI to scan with an authenticator app. Requires the account password to be re-entered.
44
+ * @security cookieAuth
45
+ * @returns {IEnable2faResponse} OTP provisioning URI to scan with an authenticator app
46
+ * @response 400 Two-factor authentication is already enabled for this user
47
+ * @response 401 Unauthorized — valid session required, or password invalid
48
+ * @response 403 Forbidden — insufficient permissions
49
+ */
50
+ enable(user: UserModel, confirmation: ConfirmPasswordDto, session: ISession): Promise<Ok<IEnable2faResponse> | Unauthorized>;
51
+ /**
52
+ * Disable own two-factor authentication
53
+ * Removes the TOTP secret and disables 2FA for the authenticated user.
54
+ * Requires the account password to be re-entered.
55
+ * @security cookieAuth
56
+ * @response 200 Two-factor authentication disabled successfully
57
+ * @response 400 Two-factor authentication is not enabled for this user
58
+ * @response 401 Unauthorized — valid session required, or password invalid
59
+ * @response 403 Forbidden — insufficient permissions
60
+ */
61
+ disable(user: UserModel, confirmation: ConfirmPasswordDto, session: ISession): Promise<Ok | Unauthorized>;
62
+ /**
63
+ * Rotates the session id after the account's authentication requirements
64
+ * changed, and returns the response options carrying the new cookie.
65
+ *
66
+ * Attaching or removing a second factor changes what the session is worth. A
67
+ * session id that was observed before the change must not keep working after
68
+ * it.
69
+ *
70
+ * @param session - the caller's current session
71
+ */
72
+ protected rotate(session: ISession): Promise<{
73
+ Headers: {
74
+ Name: string;
75
+ Value: string;
76
+ }[];
77
+ Coockies?: undefined;
78
+ } | {
79
+ Coockies: import("../services/SessionCookies.js").ISessionCookie[];
80
+ Headers: {
81
+ Name: string;
82
+ Value: string;
83
+ }[];
84
+ }>;
85
+ /**
86
+ * Generate and store the TOTP secret, returning the provisioning URI. Wraps
87
+ * the module-level action so tests can stub it without a TOTP/DB setup.
88
+ */
89
+ protected enrol(user: UserModel): Promise<unknown>;
90
+ /** Clear the TOTP secret. Wrapped for the same reason as {@link enrol}. */
91
+ protected unenrol(user: UserModel): Promise<unknown>;
92
+ /**
93
+ * Re-verify the account password. Returns `true` on success, or the
94
+ * Unauthorized response to hand back to the caller.
95
+ */
96
+ protected confirmPassword(user: UserModel, password: string): Promise<true | Unauthorized>;
97
+ }
98
+ //# sourceMappingURL=TwoFactorAuthUserController.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TwoFactorAuthUserController.d.ts","sourceRoot":"","sources":["../../../src/controllers/TwoFactorAuthUserController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAuB,EAAE,EAAgB,YAAY,EAAE,MAAM,eAAe,CAAC;AACpG,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,IAAI,IAAI,SAAS,EAAqB,MAAM,eAAe,CAAC;AACxG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG9C,OAAO,EAAoB,kBAAkB,EAA0D,MAAM,oBAAoB,CAAC;AAGlI,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAIrE,2EAA2E;AAC3E,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAIa,2BAA4B,SAAQ,cAAc;IAE7D,SAAS,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAG7C,SAAS,CAAC,eAAe,EAAE,eAAe,CAAC;IAG3C,SAAS,CAAC,cAAc,EAAE,oBAAoB,CAAC;IAE/C;;;;;;;OAOG;IAGU,MAAM,CAAS,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC;IAI3E;;;;;;;;;OASG;IAGU,MAAM,CAAS,IAAI,EAAE,SAAS,EAAU,YAAY,EAAE,kBAAkB,EAAqB,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,EAAE,CAAC,kBAAkB,CAAC,GAAG,YAAY,CAAC;IAoB5K;;;;;;;;;OASG;IAGU,OAAO,CAAS,IAAI,EAAE,SAAS,EAAU,YAAY,EAAE,kBAAkB,EAAqB,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,EAAE,GAAG,YAAY,CAAC;IAczJ;;;;;;;;;OASG;cACa,MAAM,CAAC,OAAO,EAAE,QAAQ;;;;;;;;;;;;;IAaxC;;;OAGG;IACH,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;IAIlD,2EAA2E;IAC3E,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;IAIpD;;;OAGG;cACa,eAAe,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,YAAY,CAAC;CAajG"}
@@ -0,0 +1,195 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.TwoFactorAuthUserController = void 0;
16
+ const http_1 = require("@spinajs/http");
17
+ const rbac_1 = require("@spinajs/rbac");
18
+ const di_1 = require("@spinajs/di");
19
+ const configuration_1 = require("@spinajs/configuration");
20
+ const rbac_http_1 = require("@spinajs/rbac-http");
21
+ const exceptions_1 = require("@spinajs/exceptions");
22
+ const _2FaPolicy_js_1 = require("../policies/2FaPolicy.js");
23
+ const confirm_password_dto_js_1 = require("../dto/confirm-password-dto.js");
24
+ const SessionCookies_js_1 = require("../services/SessionCookies.js");
25
+ const _2fa_js_1 = require("../actions/2fa.js");
26
+ const Default2FaToken_js_1 = require("../2fa/Default2FaToken.js");
27
+ /**
28
+ * Self-service two-factor authentication.
29
+ *
30
+ * Enrolling and unenrolling a TOTP device for one's own account, from a fully
31
+ * authorized session. These operations were previously only reachable from the
32
+ * login-time 2FA window, whose policies (`TwoFacRouteEnabled` +
33
+ * `NotAuthorizedPolicy`) exclude an authorized session by construction — so a
34
+ * normal logged-in user could neither enrol nor unenrol, and the only ways in
35
+ * were the CLI command or an administrator's 2FA reset.
36
+ *
37
+ * Both mutations re-verify the account password. A stolen session cookie must
38
+ * not be enough to attach an attacker-controlled authenticator or to strip the
39
+ * second factor off the account.
40
+ *
41
+ * @tags Two-Factor Authentication
42
+ */
43
+ let TwoFactorAuthUserController = class TwoFactorAuthUserController extends http_1.BaseController {
44
+ /**
45
+ * Get own two-factor status
46
+ * Reports whether the authenticated user currently has a TOTP device enrolled.
47
+ * @security cookieAuth
48
+ * @returns {ITwoFactorStatus} Current enrolment state
49
+ * @response 401 Unauthorized — valid session required
50
+ * @response 403 Forbidden — insufficient permissions
51
+ */
52
+ async status(user) {
53
+ return new http_1.Ok({ Enabled: Boolean(user.Metadata[Default2FaToken_js_1.TWO_FA_METATADATA_KEYS.ENABLED]) });
54
+ }
55
+ /**
56
+ * Enable own two-factor authentication
57
+ * Generates a TOTP secret for the authenticated user and returns the OTP provisioning
58
+ * URI to scan with an authenticator app. Requires the account password to be re-entered.
59
+ * @security cookieAuth
60
+ * @returns {IEnable2faResponse} OTP provisioning URI to scan with an authenticator app
61
+ * @response 400 Two-factor authentication is already enabled for this user
62
+ * @response 401 Unauthorized — valid session required, or password invalid
63
+ * @response 403 Forbidden — insufficient permissions
64
+ */
65
+ async enable(user, confirmation, session) {
66
+ if (user.Metadata[Default2FaToken_js_1.TWO_FA_METATADATA_KEYS.ENABLED]) {
67
+ throw new exceptions_1.InvalidOperation(`User ${user.Uuid} already has 2fa enabled`);
68
+ }
69
+ const confirmed = await this.confirmPassword(user, confirmation.Password);
70
+ if (confirmed !== true) {
71
+ return confirmed;
72
+ }
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.
78
+ const result = await this.enrol(user);
79
+ return new http_1.Ok({ otp: result }, await this.rotate(session));
80
+ }
81
+ /**
82
+ * Disable own two-factor authentication
83
+ * Removes the TOTP secret and disables 2FA for the authenticated user.
84
+ * Requires the account password to be re-entered.
85
+ * @security cookieAuth
86
+ * @response 200 Two-factor authentication disabled successfully
87
+ * @response 400 Two-factor authentication is not enabled for this user
88
+ * @response 401 Unauthorized — valid session required, or password invalid
89
+ * @response 403 Forbidden — insufficient permissions
90
+ */
91
+ async disable(user, confirmation, session) {
92
+ if (!user.Metadata[Default2FaToken_js_1.TWO_FA_METATADATA_KEYS.ENABLED]) {
93
+ throw new exceptions_1.InvalidOperation(`User ${user.Uuid} already has 2fa disabled`);
94
+ }
95
+ const confirmed = await this.confirmPassword(user, confirmation.Password);
96
+ if (confirmed !== true) {
97
+ return confirmed;
98
+ }
99
+ await this.unenrol(user);
100
+ return new http_1.Ok(null, await this.rotate(session));
101
+ }
102
+ /**
103
+ * Rotates the session id after the account's authentication requirements
104
+ * changed, and returns the response options carrying the new cookie.
105
+ *
106
+ * Attaching or removing a second factor changes what the session is worth. A
107
+ * session id that was observed before the change must not keep working after
108
+ * it.
109
+ *
110
+ * @param session - the caller's current session
111
+ */
112
+ async rotate(session) {
113
+ if (!session) {
114
+ return { Headers: [{ Name: 'Cache-Control', Value: 'no-store' }] };
115
+ }
116
+ const regenerated = await (0, rbac_1.regenerateSession)(this.SessionProvider, session);
117
+ return {
118
+ Coockies: [this.SessionCookies.issue(regenerated)],
119
+ Headers: [{ Name: 'Cache-Control', Value: 'no-store' }],
120
+ };
121
+ }
122
+ /**
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.
125
+ */
126
+ enrol(user) {
127
+ return (0, _2fa_js_1.enableUser2Fa)(user);
128
+ }
129
+ /** Clear the TOTP secret. Wrapped for the same reason as {@link enrol}. */
130
+ unenrol(user) {
131
+ return (0, _2fa_js_1.disableUser2Fa)(user);
132
+ }
133
+ /**
134
+ * Re-verify the account password. Returns `true` on success, or the
135
+ * Unauthorized response to hand back to the caller.
136
+ */
137
+ async confirmPassword(user, password) {
138
+ const valid = await this.PasswordProvider.verify(user.Password, password);
139
+ if (!valid) {
140
+ this._log.warn(`2fa change rejected for ${user.Uuid}: password confirmation failed`);
141
+ return new http_1.Unauthorized({
142
+ error: { code: 'E_PASSWORD_INVALID', message: 'Invalid password' },
143
+ });
144
+ }
145
+ return true;
146
+ }
147
+ };
148
+ exports.TwoFactorAuthUserController = TwoFactorAuthUserController;
149
+ __decorate([
150
+ (0, configuration_1.AutoinjectService)('rbac.password'),
151
+ __metadata("design:type", rbac_1.PasswordProvider)
152
+ ], TwoFactorAuthUserController.prototype, "PasswordProvider", void 0);
153
+ __decorate([
154
+ (0, configuration_1.AutoinjectService)('rbac.session'),
155
+ __metadata("design:type", rbac_1.SessionProvider)
156
+ ], TwoFactorAuthUserController.prototype, "SessionProvider", void 0);
157
+ __decorate([
158
+ (0, di_1.Autoinject)(SessionCookies_js_1.SessionCookieFactory),
159
+ __metadata("design:type", SessionCookies_js_1.SessionCookieFactory)
160
+ ], TwoFactorAuthUserController.prototype, "SessionCookies", void 0);
161
+ __decorate([
162
+ (0, http_1.Get)('2fa'),
163
+ (0, rbac_http_1.Permission)(['readOwn']),
164
+ __param(0, (0, rbac_http_1.User)()),
165
+ __metadata("design:type", Function),
166
+ __metadata("design:paramtypes", [rbac_1.User]),
167
+ __metadata("design:returntype", Promise)
168
+ ], TwoFactorAuthUserController.prototype, "status", null);
169
+ __decorate([
170
+ (0, http_1.Post)('2fa/enable'),
171
+ (0, rbac_http_1.Permission)(['updateOwn']),
172
+ __param(0, (0, rbac_http_1.User)()),
173
+ __param(1, (0, http_1.Body)()),
174
+ __param(2, (0, rbac_http_1.Session)()),
175
+ __metadata("design:type", Function),
176
+ __metadata("design:paramtypes", [rbac_1.User, confirm_password_dto_js_1.ConfirmPasswordDto, Object]),
177
+ __metadata("design:returntype", Promise)
178
+ ], TwoFactorAuthUserController.prototype, "enable", null);
179
+ __decorate([
180
+ (0, http_1.Post)('2fa/disable'),
181
+ (0, rbac_http_1.Permission)(['updateOwn']),
182
+ __param(0, (0, rbac_http_1.User)()),
183
+ __param(1, (0, http_1.Body)()),
184
+ __param(2, (0, rbac_http_1.Session)()),
185
+ __metadata("design:type", Function),
186
+ __metadata("design:paramtypes", [rbac_1.User, confirm_password_dto_js_1.ConfirmPasswordDto, Object]),
187
+ __metadata("design:returntype", Promise)
188
+ ], TwoFactorAuthUserController.prototype, "disable", null);
189
+ exports.TwoFactorAuthUserController = TwoFactorAuthUserController = __decorate([
190
+ (0, http_1.BasePath)('user'),
191
+ (0, rbac_http_1.Resource)('user'),
192
+ (0, http_1.Policy)(rbac_http_1.AuthorizedPolicy),
193
+ (0, http_1.Policy)(_2FaPolicy_js_1.TwoFactorAuthEnabled)
194
+ ], TwoFactorAuthUserController);
195
+ //# sourceMappingURL=TwoFactorAuthUserController.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TwoFactorAuthUserController.js","sourceRoot":"","sources":["../../../src/controllers/TwoFactorAuthUserController.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,9 @@
1
1
  import { PasswordDto } from '../dto/password-dto.js';
2
2
  import { User as UserModel, PasswordProvider, SessionProvider, AccessControl } from '@spinajs/rbac';
3
+ import type { ISession } from '@spinajs/rbac';
3
4
  import { BaseController, Ok } from '@spinajs/http';
4
5
  import { IGrantsMap } from '@spinajs/rbac-http';
6
+ import { SessionCookieFactory } from '../services/SessionCookies.js';
5
7
  /**
6
8
  * Current user profile management.
7
9
  * Allows an authenticated user to read and modify their own account — refresh profile data,
@@ -10,9 +12,9 @@ import { IGrantsMap } from '@spinajs/rbac-http';
10
12
  */
11
13
  export declare class UserController extends BaseController {
12
14
  protected PasswordProvider: PasswordProvider;
13
- protected CoockieSecret: string;
14
15
  protected SessionProvider: SessionProvider;
15
16
  protected AC: AccessControl;
17
+ protected SessionCookies: SessionCookieFactory;
16
18
  /**
17
19
  * Refresh current user profile
18
20
  * Reloads the authenticated user's record from the database (including metadata) and
@@ -22,17 +24,18 @@ export declare class UserController extends BaseController {
22
24
  * @response 401 Unauthorized — valid session required
23
25
  * @response 403 Forbidden — insufficient permissions
24
26
  */
25
- refresh(user: UserModel, ssid: string): Promise<Ok<import("@spinajs/orm").ModelData<UserModel>>>;
27
+ refresh(user: UserModel, ssid: string): Promise<Ok<import("@spinajs/orm").ModelDataWithRelationData<UserModel>>>;
26
28
  /**
27
29
  * Get current user grants
28
- * Returns the flattened RBAC grants for the authenticated user, combining all roles
29
- * the user is assigned to into a single permission map keyed by resource.
30
+ * Returns the flattened RBAC grants in effect for the authenticated user those of
31
+ * the session's active role, resolved through its inheritance chain. Switching the
32
+ * active role (`POST /auth/active-role`) changes what this returns.
30
33
  * @security cookieAuth
31
- * @returns {IGrantsMap} Combined RBAC grants map: resource → action → permission descriptor
34
+ * @returns {IGrantsMap} RBAC grants map for the active role: resource → action → permission descriptor
32
35
  * @response 401 Unauthorized — valid session required
33
36
  * @response 403 Forbidden — insufficient permissions
34
37
  */
35
- getGrants(user: UserModel): Promise<Ok<IGrantsMap>>;
38
+ getGrants(user: UserModel, session: ISession): Promise<Ok<IGrantsMap>>;
36
39
  /**
37
40
  * Change own password
38
41
  * Changes the authenticated user's password. Requires the current (old) password for verification.
@@ -42,6 +45,6 @@ export declare class UserController extends BaseController {
42
45
  * @response 401 Unauthorized — valid session required
43
46
  * @response 403 Forbidden — insufficient permissions
44
47
  */
45
- newPassword(user: UserModel, pwd: PasswordDto): Promise<Ok<unknown>>;
48
+ newPassword(user: UserModel, pwd: PasswordDto, session: ISession): Promise<Ok<null>>;
46
49
  }
47
50
  //# sourceMappingURL=UserController.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"UserController.d.ts","sourceRoot":"","sources":["../../../src/controllers/UserController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,gBAAgB,EAAE,eAAe,EAAgD,aAAa,EAAE,MAAM,eAAe,CAAC;AAClJ,OAAO,EAAE,cAAc,EAAiB,EAAE,EAA+B,MAAM,eAAe,CAAC;AAM/F,OAAO,EAAgD,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAK9F;;;;;GAKG;AACH,qBAGa,cAAe,SAAQ,cAAc;IAEhD,SAAS,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAG7C,SAAS,CAAC,aAAa,EAAE,MAAM,CAAC;IAGhC,SAAS,CAAC,eAAe,EAAE,eAAe,CAAC;IAG3C,SAAS,CAAC,EAAE,EAAE,aAAa,CAAC;IAE5B;;;;;;;;OAQG;IAGU,OAAO,CAAS,IAAI,EAAE,SAAS,EAAY,IAAI,EAAE,MAAM;IAqBpE;;;;;;;;OAQG;IAGU,SAAS,CAAS,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC;IAUxE;;;;;;;;OAQG;IAGU,WAAW,CAAS,IAAI,EAAE,SAAS,EAAU,GAAG,EAAE,WAAW;CAkB3E"}
1
+ {"version":3,"file":"UserController.d.ts","sourceRoot":"","sources":["../../../src/controllers/UserController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,gBAAgB,EAAE,eAAe,EAA8C,aAAa,EAAE,MAAM,eAAe,CAAC;AAChJ,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAiB,EAAE,EAAuB,MAAM,eAAe,CAAC;AAIvF,OAAO,EAAgD,UAAU,EAAyD,MAAM,oBAAoB,CAAC;AAGrJ,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAIrE;;;;;GAKG;AACH,qBAGa,cAAe,SAAQ,cAAc;IAEhD,SAAS,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAG7C,SAAS,CAAC,eAAe,EAAE,eAAe,CAAC;IAG3C,SAAS,CAAC,EAAE,EAAE,aAAa,CAAC;IAG5B,SAAS,CAAC,cAAc,EAAE,oBAAoB,CAAC;IAE/C;;;;;;;;OAQG;IAGU,OAAO,CAAS,IAAI,EAAE,SAAS,EAAkB,IAAI,EAAE,MAAM;IA0B1E;;;;;;;;;OASG;IAGU,SAAS,CAAS,IAAI,EAAE,SAAS,EAAqB,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC;IAS9G;;;;;;;;OAQG;IAGU,WAAW,CAAS,IAAI,EAAE,SAAS,EAAU,GAAG,EAAE,WAAW,EAAqB,OAAO,EAAE,QAAQ;CAwCjH"}