@techelusive/nest-auth 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (340) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/LICENSE +21 -0
  3. package/README.md +204 -2
  4. package/api/openapi.json +4399 -0
  5. package/api/techelusive-authentication.postman_collection.json +3178 -0
  6. package/dist/auth-options.d.ts +156 -0
  7. package/dist/auth-options.js +3 -0
  8. package/dist/auth-options.js.map +1 -0
  9. package/dist/auth-options.validation.d.ts +9 -0
  10. package/dist/auth-options.validation.js +74 -0
  11. package/dist/auth-options.validation.js.map +1 -0
  12. package/dist/auth.module.d.ts +38 -0
  13. package/dist/auth.module.js +173 -0
  14. package/dist/auth.module.js.map +1 -0
  15. package/dist/common/auth-error.d.ts +16 -0
  16. package/dist/common/auth-error.js +23 -0
  17. package/dist/common/auth-error.js.map +1 -0
  18. package/dist/common/auth-exception.filter.d.ts +24 -0
  19. package/dist/common/auth-exception.filter.js +66 -0
  20. package/dist/common/auth-exception.filter.js.map +1 -0
  21. package/dist/common/crypto/jwt.d.ts +89 -0
  22. package/dist/common/crypto/jwt.js +144 -0
  23. package/dist/common/crypto/jwt.js.map +1 -0
  24. package/dist/common/crypto/random-secrets.d.ts +78 -0
  25. package/dist/common/crypto/random-secrets.js +113 -0
  26. package/dist/common/crypto/random-secrets.js.map +1 -0
  27. package/dist/common/crypto/remote-public-keys.d.ts +49 -0
  28. package/dist/common/crypto/remote-public-keys.js +105 -0
  29. package/dist/common/crypto/remote-public-keys.js.map +1 -0
  30. package/dist/common/crypto/totp.d.ts +68 -0
  31. package/dist/common/crypto/totp.js +148 -0
  32. package/dist/common/crypto/totp.js.map +1 -0
  33. package/dist/common/encryption.service.d.ts +36 -0
  34. package/dist/common/encryption.service.js +111 -0
  35. package/dist/common/encryption.service.js.map +1 -0
  36. package/dist/common/identifiers.d.ts +48 -0
  37. package/dist/common/identifiers.js +89 -0
  38. package/dist/common/identifiers.js.map +1 -0
  39. package/dist/common/network-safety.d.ts +19 -0
  40. package/dist/common/network-safety.js +72 -0
  41. package/dist/common/network-safety.js.map +1 -0
  42. package/dist/common/rate-limiter.service.d.ts +63 -0
  43. package/dist/common/rate-limiter.service.js +158 -0
  44. package/dist/common/rate-limiter.service.js.map +1 -0
  45. package/dist/common/refresh-token-cookie.d.ts +78 -0
  46. package/dist/common/refresh-token-cookie.js +185 -0
  47. package/dist/common/refresh-token-cookie.js.map +1 -0
  48. package/dist/common/request-context.d.ts +14 -0
  49. package/dist/common/request-context.js +22 -0
  50. package/dist/common/request-context.js.map +1 -0
  51. package/dist/common/strict-validation.pipe.d.ts +8 -0
  52. package/dist/common/strict-validation.pipe.js +16 -0
  53. package/dist/common/strict-validation.pipe.js.map +1 -0
  54. package/dist/common/time.d.ts +15 -0
  55. package/dist/common/time.js +34 -0
  56. package/dist/common/time.js.map +1 -0
  57. package/dist/constants.d.ts +1326 -0
  58. package/dist/constants.js +1142 -0
  59. package/dist/constants.js.map +1 -0
  60. package/dist/database/create-auth-tables.migration.d.ts +26 -0
  61. package/dist/database/create-auth-tables.migration.js +291 -0
  62. package/dist/database/create-auth-tables.migration.js.map +1 -0
  63. package/dist/database/email-change-and-retention.migration.d.ts +25 -0
  64. package/dist/database/email-change-and-retention.migration.js +54 -0
  65. package/dist/database/email-change-and-retention.migration.js.map +1 -0
  66. package/dist/database/entities/api-key.entity.d.ts +17 -0
  67. package/dist/database/entities/api-key.entity.js +80 -0
  68. package/dist/database/entities/api-key.entity.js.map +1 -0
  69. package/dist/database/entities/audit-log.entity.d.ts +13 -0
  70. package/dist/database/entities/audit-log.entity.js +64 -0
  71. package/dist/database/entities/audit-log.entity.js.map +1 -0
  72. package/dist/database/entities/backup-code.entity.d.ts +9 -0
  73. package/dist/database/entities/backup-code.entity.js +52 -0
  74. package/dist/database/entities/backup-code.entity.js.map +1 -0
  75. package/dist/database/entities/index.d.ts +43 -0
  76. package/dist/database/entities/index.js +82 -0
  77. package/dist/database/entities/index.js.map +1 -0
  78. package/dist/database/entities/json-object.d.ts +12 -0
  79. package/dist/database/entities/json-object.js +3 -0
  80. package/dist/database/entities/json-object.js.map +1 -0
  81. package/dist/database/entities/link-token.entity.d.ts +15 -0
  82. package/dist/database/entities/link-token.entity.js +64 -0
  83. package/dist/database/entities/link-token.entity.js.map +1 -0
  84. package/dist/database/entities/one-time-code.entity.d.ts +16 -0
  85. package/dist/database/entities/one-time-code.entity.js +69 -0
  86. package/dist/database/entities/one-time-code.entity.js.map +1 -0
  87. package/dist/database/entities/organization-invitation.entity.d.ts +14 -0
  88. package/dist/database/entities/organization-invitation.entity.js +73 -0
  89. package/dist/database/entities/organization-invitation.entity.js.map +1 -0
  90. package/dist/database/entities/organization-member.entity.d.ts +9 -0
  91. package/dist/database/entities/organization-member.entity.js +48 -0
  92. package/dist/database/entities/organization-member.entity.js.map +1 -0
  93. package/dist/database/entities/organization.entity.d.ts +12 -0
  94. package/dist/database/entities/organization.entity.js +58 -0
  95. package/dist/database/entities/organization.entity.js.map +1 -0
  96. package/dist/database/entities/passkey.entity.d.ts +19 -0
  97. package/dist/database/entities/passkey.entity.js +78 -0
  98. package/dist/database/entities/passkey.entity.js.map +1 -0
  99. package/dist/database/entities/password.entity.d.ts +6 -0
  100. package/dist/database/entities/password.entity.js +36 -0
  101. package/dist/database/entities/password.entity.js.map +1 -0
  102. package/dist/database/entities/refresh-token.entity.d.ts +9 -0
  103. package/dist/database/entities/refresh-token.entity.js +53 -0
  104. package/dist/database/entities/refresh-token.entity.js.map +1 -0
  105. package/dist/database/entities/session.entity.d.ts +20 -0
  106. package/dist/database/entities/session.entity.js +87 -0
  107. package/dist/database/entities/session.entity.js.map +1 -0
  108. package/dist/database/entities/settings.entity.d.ts +7 -0
  109. package/dist/database/entities/settings.entity.js +41 -0
  110. package/dist/database/entities/settings.entity.js.map +1 -0
  111. package/dist/database/entities/sign-in-challenge.entity.d.ts +23 -0
  112. package/dist/database/entities/sign-in-challenge.entity.js +80 -0
  113. package/dist/database/entities/sign-in-challenge.entity.js.map +1 -0
  114. package/dist/database/entities/signing-key.entity.d.ts +11 -0
  115. package/dist/database/entities/signing-key.entity.js +54 -0
  116. package/dist/database/entities/signing-key.entity.js.map +1 -0
  117. package/dist/database/entities/social-account.entity.d.ts +13 -0
  118. package/dist/database/entities/social-account.entity.js +54 -0
  119. package/dist/database/entities/social-account.entity.js.map +1 -0
  120. package/dist/database/entities/two-factor-secret.entity.d.ts +10 -0
  121. package/dist/database/entities/two-factor-secret.entity.js +48 -0
  122. package/dist/database/entities/two-factor-secret.entity.js.map +1 -0
  123. package/dist/database/entities/user.entity.d.ts +34 -0
  124. package/dist/database/entities/user.entity.js +129 -0
  125. package/dist/database/entities/user.entity.js.map +1 -0
  126. package/dist/database/entities/webhook-delivery.entity.d.ts +17 -0
  127. package/dist/database/entities/webhook-delivery.entity.js +79 -0
  128. package/dist/database/entities/webhook-delivery.entity.js.map +1 -0
  129. package/dist/database/entities/webhook.entity.d.ts +12 -0
  130. package/dist/database/entities/webhook.entity.js +58 -0
  131. package/dist/database/entities/webhook.entity.js.map +1 -0
  132. package/dist/database/typeorm-row.d.ts +21 -0
  133. package/dist/database/typeorm-row.js +29 -0
  134. package/dist/database/typeorm-row.js.map +1 -0
  135. package/dist/features/account/account.controller.d.ts +259 -0
  136. package/dist/features/account/account.controller.js +372 -0
  137. package/dist/features/account/account.controller.js.map +1 -0
  138. package/dist/features/account/account.dto.d.ts +16 -0
  139. package/dist/features/account/account.dto.js +61 -0
  140. package/dist/features/account/account.dto.js.map +1 -0
  141. package/dist/features/account/data-export.service.d.ts +85 -0
  142. package/dist/features/account/data-export.service.js +125 -0
  143. package/dist/features/account/data-export.service.js.map +1 -0
  144. package/dist/features/account/health.service.d.ts +30 -0
  145. package/dist/features/account/health.service.js +59 -0
  146. package/dist/features/account/health.service.js.map +1 -0
  147. package/dist/features/admin/admin.controller.d.ts +382 -0
  148. package/dist/features/admin/admin.controller.js +623 -0
  149. package/dist/features/admin/admin.controller.js.map +1 -0
  150. package/dist/features/admin/admin.dto.d.ts +61 -0
  151. package/dist/features/admin/admin.dto.js +253 -0
  152. package/dist/features/admin/admin.dto.js.map +1 -0
  153. package/dist/features/admin/admin.service.d.ts +142 -0
  154. package/dist/features/admin/admin.service.js +227 -0
  155. package/dist/features/admin/admin.service.js.map +1 -0
  156. package/dist/features/api-keys/api-keys.service.d.ts +67 -0
  157. package/dist/features/api-keys/api-keys.service.js +144 -0
  158. package/dist/features/api-keys/api-keys.service.js.map +1 -0
  159. package/dist/features/email-change/email-change.controller.d.ts +38 -0
  160. package/dist/features/email-change/email-change.controller.js +85 -0
  161. package/dist/features/email-change/email-change.controller.js.map +1 -0
  162. package/dist/features/email-change/email-change.dto.d.ts +10 -0
  163. package/dist/features/email-change/email-change.dto.js +43 -0
  164. package/dist/features/email-change/email-change.dto.js.map +1 -0
  165. package/dist/features/email-change/email-change.service.d.ts +74 -0
  166. package/dist/features/email-change/email-change.service.js +179 -0
  167. package/dist/features/email-change/email-change.service.js.map +1 -0
  168. package/dist/features/email-links/email-verification.service.d.ts +46 -0
  169. package/dist/features/email-links/email-verification.service.js +94 -0
  170. package/dist/features/email-links/email-verification.service.js.map +1 -0
  171. package/dist/features/email-links/link-tokens.service.d.ts +44 -0
  172. package/dist/features/email-links/link-tokens.service.js +122 -0
  173. package/dist/features/email-links/link-tokens.service.js.map +1 -0
  174. package/dist/features/events/auth-events.service.d.ts +52 -0
  175. package/dist/features/events/auth-events.service.js +117 -0
  176. package/dist/features/events/auth-events.service.js.map +1 -0
  177. package/dist/features/maintenance/data-retention.service.d.ts +60 -0
  178. package/dist/features/maintenance/data-retention.service.js +182 -0
  179. package/dist/features/maintenance/data-retention.service.js.map +1 -0
  180. package/dist/features/notifications/notifications.service.d.ts +40 -0
  181. package/dist/features/notifications/notifications.service.js +94 -0
  182. package/dist/features/notifications/notifications.service.js.map +1 -0
  183. package/dist/features/one-time-codes/one-time-codes.service.d.ts +40 -0
  184. package/dist/features/one-time-codes/one-time-codes.service.js +102 -0
  185. package/dist/features/one-time-codes/one-time-codes.service.js.map +1 -0
  186. package/dist/features/organizations/organizations.controller.d.ts +220 -0
  187. package/dist/features/organizations/organizations.controller.js +337 -0
  188. package/dist/features/organizations/organizations.controller.js.map +1 -0
  189. package/dist/features/organizations/organizations.dto.d.ts +31 -0
  190. package/dist/features/organizations/organizations.dto.js +100 -0
  191. package/dist/features/organizations/organizations.dto.js.map +1 -0
  192. package/dist/features/organizations/organizations.service.d.ts +274 -0
  193. package/dist/features/organizations/organizations.service.js +481 -0
  194. package/dist/features/organizations/organizations.service.js.map +1 -0
  195. package/dist/features/passkeys/passkeys.controller.d.ts +92 -0
  196. package/dist/features/passkeys/passkeys.controller.js +183 -0
  197. package/dist/features/passkeys/passkeys.controller.js.map +1 -0
  198. package/dist/features/passkeys/passkeys.dto.d.ts +13 -0
  199. package/dist/features/passkeys/passkeys.dto.js +50 -0
  200. package/dist/features/passkeys/passkeys.dto.js.map +1 -0
  201. package/dist/features/passkeys/passkeys.service.d.ts +159 -0
  202. package/dist/features/passkeys/passkeys.service.js +350 -0
  203. package/dist/features/passkeys/passkeys.service.js.map +1 -0
  204. package/dist/features/passwordless/passwordless-auth.service.d.ts +152 -0
  205. package/dist/features/passwordless/passwordless-auth.service.js +304 -0
  206. package/dist/features/passwordless/passwordless-auth.service.js.map +1 -0
  207. package/dist/features/passwordless/passwordless.controller.d.ts +75 -0
  208. package/dist/features/passwordless/passwordless.controller.js +163 -0
  209. package/dist/features/passwordless/passwordless.controller.js.map +1 -0
  210. package/dist/features/passwordless/passwordless.dto.d.ts +29 -0
  211. package/dist/features/passwordless/passwordless.dto.js +101 -0
  212. package/dist/features/passwordless/passwordless.dto.js.map +1 -0
  213. package/dist/features/passwords/password-auth.service.d.ts +154 -0
  214. package/dist/features/passwords/password-auth.service.js +317 -0
  215. package/dist/features/passwords/password-auth.service.js.map +1 -0
  216. package/dist/features/passwords/password-policy.service.d.ts +63 -0
  217. package/dist/features/passwords/password-policy.service.js +175 -0
  218. package/dist/features/passwords/password-policy.service.js.map +1 -0
  219. package/dist/features/passwords/password.controller.d.ts +95 -0
  220. package/dist/features/passwords/password.controller.js +193 -0
  221. package/dist/features/passwords/password.controller.js.map +1 -0
  222. package/dist/features/passwords/password.dto.d.ts +36 -0
  223. package/dist/features/passwords/password.dto.js +140 -0
  224. package/dist/features/passwords/password.dto.js.map +1 -0
  225. package/dist/features/sessions/session.service.d.ts +132 -0
  226. package/dist/features/sessions/session.service.js +308 -0
  227. package/dist/features/sessions/session.service.js.map +1 -0
  228. package/dist/features/sessions/session.types.d.ts +34 -0
  229. package/dist/features/sessions/session.types.js +3 -0
  230. package/dist/features/sessions/session.types.js.map +1 -0
  231. package/dist/features/settings/settings.defaults.d.ts +2 -0
  232. package/dist/features/settings/settings.defaults.js +7 -0
  233. package/dist/features/settings/settings.defaults.js.map +1 -0
  234. package/dist/features/settings/settings.service.d.ts +44 -0
  235. package/dist/features/settings/settings.service.js +112 -0
  236. package/dist/features/settings/settings.service.js.map +1 -0
  237. package/dist/features/settings/settings.types.d.ts +133 -0
  238. package/dist/features/settings/settings.types.js +3 -0
  239. package/dist/features/settings/settings.types.js.map +1 -0
  240. package/dist/features/settings/settings.validation.d.ts +33 -0
  241. package/dist/features/settings/settings.validation.js +614 -0
  242. package/dist/features/settings/settings.validation.js.map +1 -0
  243. package/dist/features/sign-in/sign-in-challenges.service.d.ts +54 -0
  244. package/dist/features/sign-in/sign-in-challenges.service.js +104 -0
  245. package/dist/features/sign-in/sign-in-challenges.service.js.map +1 -0
  246. package/dist/features/sign-in/sign-in.service.d.ts +127 -0
  247. package/dist/features/sign-in/sign-in.service.js +248 -0
  248. package/dist/features/sign-in/sign-in.service.js.map +1 -0
  249. package/dist/features/sign-in/sign-in.types.d.ts +22 -0
  250. package/dist/features/sign-in/sign-in.types.js +3 -0
  251. package/dist/features/sign-in/sign-in.types.js.map +1 -0
  252. package/dist/features/signing-keys/jwks.controller.d.ts +17 -0
  253. package/dist/features/signing-keys/jwks.controller.js +51 -0
  254. package/dist/features/signing-keys/jwks.controller.js.map +1 -0
  255. package/dist/features/signing-keys/signing-keys.service.d.ts +67 -0
  256. package/dist/features/signing-keys/signing-keys.service.js +142 -0
  257. package/dist/features/signing-keys/signing-keys.service.js.map +1 -0
  258. package/dist/features/social/social-auth.service.d.ts +100 -0
  259. package/dist/features/social/social-auth.service.js +232 -0
  260. package/dist/features/social/social-auth.service.js.map +1 -0
  261. package/dist/features/social/social-providers.service.d.ts +97 -0
  262. package/dist/features/social/social-providers.service.js +214 -0
  263. package/dist/features/social/social-providers.service.js.map +1 -0
  264. package/dist/features/social/social.controller.d.ts +54 -0
  265. package/dist/features/social/social.controller.js +124 -0
  266. package/dist/features/social/social.controller.js.map +1 -0
  267. package/dist/features/social/social.dto.d.ts +11 -0
  268. package/dist/features/social/social.dto.js +38 -0
  269. package/dist/features/social/social.dto.js.map +1 -0
  270. package/dist/features/two-factor/two-factor.controller.d.ts +84 -0
  271. package/dist/features/two-factor/two-factor.controller.js +174 -0
  272. package/dist/features/two-factor/two-factor.controller.js.map +1 -0
  273. package/dist/features/two-factor/two-factor.dto.d.ts +10 -0
  274. package/dist/features/two-factor/two-factor.dto.js +37 -0
  275. package/dist/features/two-factor/two-factor.dto.js.map +1 -0
  276. package/dist/features/two-factor/two-factor.service.d.ts +171 -0
  277. package/dist/features/two-factor/two-factor.service.js +348 -0
  278. package/dist/features/two-factor/two-factor.service.js.map +1 -0
  279. package/dist/features/users/sign-in-methods.service.d.ts +40 -0
  280. package/dist/features/users/sign-in-methods.service.js +81 -0
  281. package/dist/features/users/sign-in-methods.service.js.map +1 -0
  282. package/dist/features/users/sign-up-rules.d.ts +12 -0
  283. package/dist/features/users/sign-up-rules.js +29 -0
  284. package/dist/features/users/sign-up-rules.js.map +1 -0
  285. package/dist/features/users/users.service.d.ts +246 -0
  286. package/dist/features/users/users.service.js +509 -0
  287. package/dist/features/users/users.service.js.map +1 -0
  288. package/dist/features/users/users.types.d.ts +24 -0
  289. package/dist/features/users/users.types.js +3 -0
  290. package/dist/features/users/users.types.js.map +1 -0
  291. package/dist/features/webhooks/webhook-delivery.worker.d.ts +55 -0
  292. package/dist/features/webhooks/webhook-delivery.worker.js +175 -0
  293. package/dist/features/webhooks/webhook-delivery.worker.js.map +1 -0
  294. package/dist/features/webhooks/webhook-signature.d.ts +28 -0
  295. package/dist/features/webhooks/webhook-signature.js +85 -0
  296. package/dist/features/webhooks/webhook-signature.js.map +1 -0
  297. package/dist/features/webhooks/webhooks.service.d.ts +144 -0
  298. package/dist/features/webhooks/webhooks.service.js +238 -0
  299. package/dist/features/webhooks/webhooks.service.js.map +1 -0
  300. package/dist/guards/auth.decorators.d.ts +65 -0
  301. package/dist/guards/auth.decorators.js +68 -0
  302. package/dist/guards/auth.decorators.js.map +1 -0
  303. package/dist/guards/auth.guard.d.ts +47 -0
  304. package/dist/guards/auth.guard.js +132 -0
  305. package/dist/guards/auth.guard.js.map +1 -0
  306. package/dist/index.d.ts +38 -0
  307. package/dist/index.js +95 -0
  308. package/dist/index.js.map +1 -0
  309. package/dist/integrations/console-email-sender.d.ts +15 -0
  310. package/dist/integrations/console-email-sender.js +26 -0
  311. package/dist/integrations/console-email-sender.js.map +1 -0
  312. package/dist/integrations/msg91-sms-sender.d.ts +28 -0
  313. package/dist/integrations/msg91-sms-sender.js +46 -0
  314. package/dist/integrations/msg91-sms-sender.js.map +1 -0
  315. package/docs/README.md +39 -0
  316. package/docs/admin-api-keys-webhooks.md +147 -0
  317. package/docs/api-reference.md +175 -0
  318. package/docs/architecture.md +119 -0
  319. package/docs/client-integration.md +192 -0
  320. package/docs/code-walkthrough.md +273 -0
  321. package/docs/configuration.md +229 -0
  322. package/docs/endpoints/README.md +151 -0
  323. package/docs/endpoints/account.md +363 -0
  324. package/docs/endpoints/admin.md +422 -0
  325. package/docs/endpoints/email-password.md +261 -0
  326. package/docs/endpoints/organizations.md +192 -0
  327. package/docs/endpoints/passkeys.md +195 -0
  328. package/docs/endpoints/passwordless.md +214 -0
  329. package/docs/endpoints/social.md +116 -0
  330. package/docs/endpoints/two-factor.md +146 -0
  331. package/docs/error-codes.md +100 -0
  332. package/docs/events.md +83 -0
  333. package/docs/getting-started.md +139 -0
  334. package/docs/manual-testing.md +215 -0
  335. package/docs/organizations.md +86 -0
  336. package/docs/production-checklist.md +60 -0
  337. package/docs/protecting-routes.md +147 -0
  338. package/docs/security.md +61 -0
  339. package/docs/sign-in-flows.md +294 -0
  340. package/package.json +92 -4
@@ -0,0 +1,63 @@
1
+ import { AuthSettings } from '../settings/settings.types.js';
2
+ /**
3
+ * Everything about password strength and storage:
4
+ * - checks a new password against the rules in settings.password,
5
+ * - refuses passwords known from data breaches,
6
+ * - hashes with Argon2id (the current OWASP recommendation) and verifies hashes.
7
+ */
8
+ export declare class PasswordPolicyService {
9
+ private readonly logger;
10
+ /**
11
+ * A hash of a random password, checked when an email has no account. Sign-in then takes the same
12
+ * time whether or not the account exists, so timing can't reveal who has an account.
13
+ */
14
+ private dummyPasswordHash?;
15
+ /**
16
+ * Checks a new password against the rules in settings, then against known data breaches.
17
+ *
18
+ * @param password - The new password from the request.
19
+ * @param settings - The current settings (length and character rules).
20
+ * @returns The password, now known to be a string.
21
+ * @throws AuthError INVALID_PASSWORD with `requirements` listing every broken rule.
22
+ * @throws AuthError INVALID_PASSWORD (with a breach message) when the password appeared in a data breach.
23
+ */
24
+ assertPasswordIsAcceptable(password: unknown, settings: AuthSettings): Promise<string>;
25
+ /**
26
+ * Hashes a password with Argon2id.
27
+ *
28
+ * @param password - The plain password.
29
+ * @returns The hash to store (it includes its own salt and settings).
30
+ */
31
+ hashPassword(password: string): Promise<string>;
32
+ /**
33
+ * Checks a typed password against a stored hash.
34
+ *
35
+ * @param storedHash - The user's hash, or `null` when there is no account. A dummy hash is then
36
+ * checked anyway, so the response takes the same time either way.
37
+ * @param typedPassword - The password from the request.
38
+ * @returns True only when there is a stored hash and the password matches it.
39
+ */
40
+ verifyPassword(storedHash: string | null, typedPassword: unknown): Promise<boolean>;
41
+ /**
42
+ * Checks whether an old hash was made with weaker settings and should be replaced on next sign-in.
43
+ *
44
+ * @param storedHash - The user's current hash.
45
+ * @returns True when the hash should be recreated.
46
+ */
47
+ needsRehash(storedHash: string): boolean;
48
+ /**
49
+ * Asks haveibeenpwned.com whether the password appeared in a breach, using "k-anonymity":
50
+ * only the first 5 characters of its SHA-1 hash are sent, never the password.
51
+ * If the service is slow or down, the password is allowed (sign-up should not depend on it).
52
+ *
53
+ * @param password - The new password.
54
+ * @returns True when the password is known from a breach.
55
+ */
56
+ private isKnownBreachedPassword;
57
+ /**
58
+ * Creates (once) the hash of a random password, used by `verifyPassword` when there is no account.
59
+ *
60
+ * @returns The dummy hash.
61
+ */
62
+ private getDummyPasswordHash;
63
+ }
@@ -0,0 +1,175 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
+ 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;
22
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
23
+ };
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.PasswordPolicyService = void 0;
43
+ const common_1 = require("@nestjs/common");
44
+ const argon2 = __importStar(require("argon2"));
45
+ const node_crypto_1 = require("node:crypto");
46
+ const auth_error_1 = require("../../common/auth-error.js");
47
+ const constants_1 = require("../../constants.js");
48
+ /**
49
+ * Everything about password strength and storage:
50
+ * - checks a new password against the rules in settings.password,
51
+ * - refuses passwords known from data breaches,
52
+ * - hashes with Argon2id (the current OWASP recommendation) and verifies hashes.
53
+ */
54
+ let PasswordPolicyService = class PasswordPolicyService {
55
+ logger = new common_1.Logger(constants_1.LOG_CONTEXT.passwordPolicy);
56
+ /**
57
+ * A hash of a random password, checked when an email has no account. Sign-in then takes the same
58
+ * time whether or not the account exists, so timing can't reveal who has an account.
59
+ */
60
+ dummyPasswordHash;
61
+ /**
62
+ * Checks a new password against the rules in settings, then against known data breaches.
63
+ *
64
+ * @param password - The new password from the request.
65
+ * @param settings - The current settings (length and character rules).
66
+ * @returns The password, now known to be a string.
67
+ * @throws AuthError INVALID_PASSWORD with `requirements` listing every broken rule.
68
+ * @throws AuthError INVALID_PASSWORD (with a breach message) when the password appeared in a data breach.
69
+ */
70
+ async assertPasswordIsAcceptable(password, settings) {
71
+ if (typeof password !== 'string')
72
+ throw new auth_error_1.AuthError(constants_1.AUTH_ERRORS.invalidPassword);
73
+ const rules = settings.password;
74
+ const brokenRules = [];
75
+ if (password.length < rules.minimumLength)
76
+ brokenRules.push(constants_1.PASSWORD_REQUIREMENT.minimumLength(rules.minimumLength));
77
+ if (password.length > constants_1.PASSWORD_MAX_LENGTH)
78
+ brokenRules.push(constants_1.PASSWORD_REQUIREMENT.maximumLength(constants_1.PASSWORD_MAX_LENGTH));
79
+ if (rules.requireUppercaseLetter && !constants_1.UPPERCASE_LETTER_PATTERN.test(password))
80
+ brokenRules.push(constants_1.PASSWORD_REQUIREMENT.uppercaseLetter);
81
+ if (rules.requireLowercaseLetter && !constants_1.LOWERCASE_LETTER_PATTERN.test(password))
82
+ brokenRules.push(constants_1.PASSWORD_REQUIREMENT.lowercaseLetter);
83
+ if (rules.requireNumber && !constants_1.DIGIT_PATTERN.test(password))
84
+ brokenRules.push(constants_1.PASSWORD_REQUIREMENT.number);
85
+ if (rules.requireSymbol && !constants_1.PASSWORD_SYMBOL_PATTERN.test(password))
86
+ brokenRules.push(constants_1.PASSWORD_REQUIREMENT.symbol);
87
+ if (brokenRules.length > 0)
88
+ throw new auth_error_1.AuthError(constants_1.AUTH_ERRORS.invalidPassword, { requirements: brokenRules });
89
+ if (rules.rejectBreachedPasswords && (await this.isKnownBreachedPassword(password))) {
90
+ throw new auth_error_1.AuthError(constants_1.AUTH_ERRORS.breachedPassword);
91
+ }
92
+ return password;
93
+ }
94
+ /**
95
+ * Hashes a password with Argon2id.
96
+ *
97
+ * @param password - The plain password.
98
+ * @returns The hash to store (it includes its own salt and settings).
99
+ */
100
+ hashPassword(password) {
101
+ return argon2.hash(password, { type: argon2.argon2id, ...constants_1.ARGON2_HASHING_OPTIONS });
102
+ }
103
+ /**
104
+ * Checks a typed password against a stored hash.
105
+ *
106
+ * @param storedHash - The user's hash, or `null` when there is no account. A dummy hash is then
107
+ * checked anyway, so the response takes the same time either way.
108
+ * @param typedPassword - The password from the request.
109
+ * @returns True only when there is a stored hash and the password matches it.
110
+ */
111
+ async verifyPassword(storedHash, typedPassword) {
112
+ const password = typeof typedPassword === 'string' ? typedPassword.slice(0, constants_1.PASSWORD_MAX_LENGTH) : '';
113
+ const hashToCheck = storedHash ?? (await this.getDummyPasswordHash());
114
+ try {
115
+ const matches = await argon2.verify(hashToCheck, password);
116
+ return storedHash !== null && matches;
117
+ }
118
+ catch {
119
+ return false;
120
+ }
121
+ }
122
+ /**
123
+ * Checks whether an old hash was made with weaker settings and should be replaced on next sign-in.
124
+ *
125
+ * @param storedHash - The user's current hash.
126
+ * @returns True when the hash should be recreated.
127
+ */
128
+ needsRehash(storedHash) {
129
+ return argon2.needsRehash(storedHash, { ...constants_1.ARGON2_HASHING_OPTIONS });
130
+ }
131
+ /**
132
+ * Asks haveibeenpwned.com whether the password appeared in a breach, using "k-anonymity":
133
+ * only the first 5 characters of its SHA-1 hash are sent, never the password.
134
+ * If the service is slow or down, the password is allowed (sign-up should not depend on it).
135
+ *
136
+ * @param password - The new password.
137
+ * @returns True when the password is known from a breach.
138
+ */
139
+ async isKnownBreachedPassword(password) {
140
+ const sha1 = (0, node_crypto_1.createHash)(constants_1.HASH_ALGORITHM.sha1).update(password).digest(constants_1.TEXT_ENCODING.hex).toUpperCase();
141
+ const hashPrefix = sha1.slice(0, constants_1.BREACHED_PASSWORD_HASH_PREFIX_LENGTH);
142
+ const hashSuffix = sha1.slice(constants_1.BREACHED_PASSWORD_HASH_PREFIX_LENGTH);
143
+ try {
144
+ const response = await fetch(`${constants_1.BREACHED_PASSWORD_API_URL}${hashPrefix}`, {
145
+ headers: { [constants_1.BREACHED_PASSWORD_API.paddingHeader]: constants_1.BREACHED_PASSWORD_API.paddingHeaderValue },
146
+ signal: AbortSignal.timeout(constants_1.BREACHED_PASSWORD_CHECK_TIMEOUT_MS),
147
+ });
148
+ if (!response.ok)
149
+ return false;
150
+ const responseLines = (await response.text()).split(constants_1.BREACHED_PASSWORD_API.lineSeparator);
151
+ return responseLines.some((line) => {
152
+ const [suffix, timesSeen] = line.trim().split(constants_1.BREACHED_PASSWORD_API.countSeparator);
153
+ return suffix === hashSuffix && Number(timesSeen) > 0;
154
+ });
155
+ }
156
+ catch (error) {
157
+ this.logger.warn(`Breached-password check skipped: ${error.message}`);
158
+ return false;
159
+ }
160
+ }
161
+ /**
162
+ * Creates (once) the hash of a random password, used by `verifyPassword` when there is no account.
163
+ *
164
+ * @returns The dummy hash.
165
+ */
166
+ getDummyPasswordHash() {
167
+ this.dummyPasswordHash ??= this.hashPassword((0, node_crypto_1.createHash)(constants_1.HASH_ALGORITHM.sha256).update(String(Math.random())).digest(constants_1.TEXT_ENCODING.hex));
168
+ return this.dummyPasswordHash;
169
+ }
170
+ };
171
+ exports.PasswordPolicyService = PasswordPolicyService;
172
+ exports.PasswordPolicyService = PasswordPolicyService = __decorate([
173
+ (0, common_1.Injectable)()
174
+ ], PasswordPolicyService);
175
+ //# sourceMappingURL=password-policy.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"password-policy.service.js","sourceRoot":"","sources":["../../../src/features/passwords/password-policy.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,95 @@
1
+ import { RequestContext } from '../../common/request-context.js';
2
+ import { EmailVerificationService } from '../email-links/email-verification.service.js';
3
+ import { AccessTokenClaims } from '../sessions/session.types.js';
4
+ import { PasswordAuthService } from './password-auth.service';
5
+ import { ChangePasswordInput, EmailOnlyInput, RegisterInput, ResetPasswordInput, SignInWithPasswordInput, TokenInput } from './password.dto';
6
+ /**
7
+ * Email + password and email verification.
8
+ *
9
+ * POST /auth/register create an account
10
+ * POST /auth/login sign in
11
+ * POST /auth/email/send-verification (re)send the verification link
12
+ * POST /auth/email/verify use the token from the link
13
+ * POST /auth/password/forgot email a reset link
14
+ * POST /auth/password/reset set a new password with the token from the link
15
+ * POST /auth/password/change signed in: change (or first set) the password
16
+ */
17
+ export declare class PasswordController {
18
+ private readonly passwordAuth;
19
+ private readonly emailVerification;
20
+ constructor(passwordAuth: PasswordAuthService, emailVerification: EmailVerificationService);
21
+ /**
22
+ * POST /auth/register — Creates an account. Public.
23
+ *
24
+ * @param body - The sign-up form.
25
+ * @param request - Who is asking.
26
+ * @returns See `PasswordAuthService.register`.
27
+ */
28
+ register(body: RegisterInput, request: RequestContext): Promise<import("../..").SignInResult | import("./password-auth.service").RegisteredResult>;
29
+ /**
30
+ * POST /auth/login — Signs in with email + password. Public.
31
+ *
32
+ * @param body - `{ email, password }`.
33
+ * @param request - Who is asking.
34
+ * @returns Tokens, or a 2FA challenge.
35
+ */
36
+ login(body: SignInWithPasswordInput, request: RequestContext): Promise<import("../..").SignInResult>;
37
+ /**
38
+ * POST /auth/email/send-verification — (Re)sends the email verification link. Public.
39
+ *
40
+ * @param body - `{ email }`.
41
+ * @param request - Who is asking.
42
+ * @returns A generic success message.
43
+ */
44
+ sendVerificationEmail(body: EmailOnlyInput, request: RequestContext): Promise<{
45
+ success: true;
46
+ message: "If this email needs verifying, a verification link is on its way.";
47
+ }>;
48
+ /**
49
+ * POST /auth/email/verify — Verifies the email with the token from the link. Public.
50
+ *
51
+ * @param body - `{ token }`.
52
+ * @param request - Who is asking.
53
+ * @returns See `EmailVerificationService.verifyEmail`.
54
+ */
55
+ verifyEmail(body: TokenInput, request: RequestContext): Promise<{
56
+ success: true;
57
+ message: "Your email has been verified.";
58
+ status: import("../../constants.js").AccountStatus;
59
+ pendingVerifications: import("../../constants.js").PendingVerification[];
60
+ }>;
61
+ /**
62
+ * POST /auth/password/forgot — Emails a password reset link. Public.
63
+ *
64
+ * @param body - `{ email }`.
65
+ * @param request - Who is asking.
66
+ * @returns A generic success message.
67
+ */
68
+ forgotPassword(body: EmailOnlyInput, request: RequestContext): Promise<{
69
+ success: true;
70
+ message: "If an account exists for this email, a password reset link is on its way.";
71
+ }>;
72
+ /**
73
+ * POST /auth/password/reset — Sets a new password with the token from the link. Public.
74
+ *
75
+ * @param body - `{ token, newPassword }`.
76
+ * @param request - Who is asking.
77
+ * @returns A success message.
78
+ */
79
+ resetPassword(body: ResetPasswordInput, request: RequestContext): Promise<{
80
+ success: true;
81
+ message: "Your password has been reset. Please sign in with your new password.";
82
+ }>;
83
+ /**
84
+ * POST /auth/password/change — Changes (or first sets) the signed-in user's password.
85
+ *
86
+ * @param user - The access token's claims (user id and session id).
87
+ * @param body - `{ currentPassword, newPassword }`.
88
+ * @param request - Who is asking.
89
+ * @returns A success message.
90
+ */
91
+ changePassword(user: AccessTokenClaims, body: ChangePasswordInput, request: RequestContext): Promise<{
92
+ success: true;
93
+ message: "Your password has been changed. Other devices have been signed out.";
94
+ }>;
95
+ }
@@ -0,0 +1,193 @@
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.PasswordController = void 0;
16
+ const common_1 = require("@nestjs/common");
17
+ const strict_validation_pipe_1 = require("../../common/strict-validation.pipe.js");
18
+ const request_context_1 = require("../../common/request-context.js");
19
+ const auth_decorators_1 = require("../../guards/auth.decorators.js");
20
+ const email_verification_service_1 = require("../email-links/email-verification.service.js");
21
+ const password_auth_service_1 = require("./password-auth.service");
22
+ const password_dto_1 = require("./password.dto");
23
+ const constants_1 = require("../../constants.js");
24
+ const refresh_token_cookie_1 = require("../../common/refresh-token-cookie.js");
25
+ /**
26
+ * Email + password and email verification.
27
+ *
28
+ * POST /auth/register create an account
29
+ * POST /auth/login sign in
30
+ * POST /auth/email/send-verification (re)send the verification link
31
+ * POST /auth/email/verify use the token from the link
32
+ * POST /auth/password/forgot email a reset link
33
+ * POST /auth/password/reset set a new password with the token from the link
34
+ * POST /auth/password/change signed in: change (or first set) the password
35
+ */
36
+ let PasswordController = class PasswordController {
37
+ passwordAuth;
38
+ emailVerification;
39
+ constructor(passwordAuth, emailVerification) {
40
+ this.passwordAuth = passwordAuth;
41
+ this.emailVerification = emailVerification;
42
+ }
43
+ /**
44
+ * POST /auth/register — Creates an account. Public.
45
+ *
46
+ * @param body - The sign-up form.
47
+ * @param request - Who is asking.
48
+ * @returns See `PasswordAuthService.register`.
49
+ */
50
+ register(body, request) {
51
+ return this.passwordAuth.register(body, request);
52
+ }
53
+ /**
54
+ * POST /auth/login — Signs in with email + password. Public.
55
+ *
56
+ * @param body - `{ email, password }`.
57
+ * @param request - Who is asking.
58
+ * @returns Tokens, or a 2FA challenge.
59
+ */
60
+ login(body, request) {
61
+ return this.passwordAuth.signInWithPassword(body.email, body.password, request);
62
+ }
63
+ /**
64
+ * POST /auth/email/send-verification — (Re)sends the email verification link. Public.
65
+ *
66
+ * @param body - `{ email }`.
67
+ * @param request - Who is asking.
68
+ * @returns A generic success message.
69
+ */
70
+ sendVerificationEmail(body, request) {
71
+ return this.emailVerification.sendVerificationEmail(body.email, request);
72
+ }
73
+ /**
74
+ * POST /auth/email/verify — Verifies the email with the token from the link. Public.
75
+ *
76
+ * @param body - `{ token }`.
77
+ * @param request - Who is asking.
78
+ * @returns See `EmailVerificationService.verifyEmail`.
79
+ */
80
+ verifyEmail(body, request) {
81
+ return this.emailVerification.verifyEmail(body.token, request);
82
+ }
83
+ /**
84
+ * POST /auth/password/forgot — Emails a password reset link. Public.
85
+ *
86
+ * @param body - `{ email }`.
87
+ * @param request - Who is asking.
88
+ * @returns A generic success message.
89
+ */
90
+ forgotPassword(body, request) {
91
+ return this.passwordAuth.requestPasswordReset(body.email, request);
92
+ }
93
+ /**
94
+ * POST /auth/password/reset — Sets a new password with the token from the link. Public.
95
+ *
96
+ * @param body - `{ token, newPassword }`.
97
+ * @param request - Who is asking.
98
+ * @returns A success message.
99
+ */
100
+ resetPassword(body, request) {
101
+ return this.passwordAuth.resetPassword(body.token, body.newPassword, request);
102
+ }
103
+ /**
104
+ * POST /auth/password/change — Changes (or first sets) the signed-in user's password.
105
+ *
106
+ * @param user - The access token's claims (user id and session id).
107
+ * @param body - `{ currentPassword, newPassword }`.
108
+ * @param request - Who is asking.
109
+ * @returns A success message.
110
+ */
111
+ changePassword(user, body, request) {
112
+ return this.passwordAuth.changePassword(user.sub, user.sid, body.currentPassword, body.newPassword, request);
113
+ }
114
+ };
115
+ exports.PasswordController = PasswordController;
116
+ __decorate([
117
+ (0, common_1.Post)(constants_1.ROUTES.auth.register),
118
+ (0, auth_decorators_1.Public)(),
119
+ (0, common_1.HttpCode)(common_1.HttpStatus.CREATED),
120
+ __param(0, (0, common_1.Body)()),
121
+ __param(1, (0, request_context_1.CurrentRequest)()),
122
+ __metadata("design:type", Function),
123
+ __metadata("design:paramtypes", [password_dto_1.RegisterInput, Object]),
124
+ __metadata("design:returntype", void 0)
125
+ ], PasswordController.prototype, "register", null);
126
+ __decorate([
127
+ (0, common_1.Post)(constants_1.ROUTES.auth.login),
128
+ (0, auth_decorators_1.Public)(),
129
+ (0, common_1.HttpCode)(common_1.HttpStatus.OK),
130
+ __param(0, (0, common_1.Body)()),
131
+ __param(1, (0, request_context_1.CurrentRequest)()),
132
+ __metadata("design:type", Function),
133
+ __metadata("design:paramtypes", [password_dto_1.SignInWithPasswordInput, Object]),
134
+ __metadata("design:returntype", void 0)
135
+ ], PasswordController.prototype, "login", null);
136
+ __decorate([
137
+ (0, common_1.Post)(constants_1.ROUTES.auth.emailSendVerification),
138
+ (0, auth_decorators_1.Public)(),
139
+ (0, common_1.HttpCode)(common_1.HttpStatus.OK),
140
+ __param(0, (0, common_1.Body)()),
141
+ __param(1, (0, request_context_1.CurrentRequest)()),
142
+ __metadata("design:type", Function),
143
+ __metadata("design:paramtypes", [password_dto_1.EmailOnlyInput, Object]),
144
+ __metadata("design:returntype", void 0)
145
+ ], PasswordController.prototype, "sendVerificationEmail", null);
146
+ __decorate([
147
+ (0, common_1.Post)(constants_1.ROUTES.auth.emailVerify),
148
+ (0, auth_decorators_1.Public)(),
149
+ (0, common_1.HttpCode)(common_1.HttpStatus.OK),
150
+ __param(0, (0, common_1.Body)()),
151
+ __param(1, (0, request_context_1.CurrentRequest)()),
152
+ __metadata("design:type", Function),
153
+ __metadata("design:paramtypes", [password_dto_1.TokenInput, Object]),
154
+ __metadata("design:returntype", void 0)
155
+ ], PasswordController.prototype, "verifyEmail", null);
156
+ __decorate([
157
+ (0, common_1.Post)(constants_1.ROUTES.auth.passwordForgot),
158
+ (0, auth_decorators_1.Public)(),
159
+ (0, common_1.HttpCode)(common_1.HttpStatus.OK),
160
+ __param(0, (0, common_1.Body)()),
161
+ __param(1, (0, request_context_1.CurrentRequest)()),
162
+ __metadata("design:type", Function),
163
+ __metadata("design:paramtypes", [password_dto_1.EmailOnlyInput, Object]),
164
+ __metadata("design:returntype", void 0)
165
+ ], PasswordController.prototype, "forgotPassword", null);
166
+ __decorate([
167
+ (0, common_1.Post)(constants_1.ROUTES.auth.passwordReset),
168
+ (0, auth_decorators_1.Public)(),
169
+ (0, common_1.HttpCode)(common_1.HttpStatus.OK),
170
+ __param(0, (0, common_1.Body)()),
171
+ __param(1, (0, request_context_1.CurrentRequest)()),
172
+ __metadata("design:type", Function),
173
+ __metadata("design:paramtypes", [password_dto_1.ResetPasswordInput, Object]),
174
+ __metadata("design:returntype", void 0)
175
+ ], PasswordController.prototype, "resetPassword", null);
176
+ __decorate([
177
+ (0, common_1.Post)(constants_1.ROUTES.auth.passwordChange),
178
+ (0, common_1.HttpCode)(common_1.HttpStatus.OK),
179
+ __param(0, (0, auth_decorators_1.CurrentUser)()),
180
+ __param(1, (0, common_1.Body)()),
181
+ __param(2, (0, request_context_1.CurrentRequest)()),
182
+ __metadata("design:type", Function),
183
+ __metadata("design:paramtypes", [Object, password_dto_1.ChangePasswordInput, Object]),
184
+ __metadata("design:returntype", void 0)
185
+ ], PasswordController.prototype, "changePassword", null);
186
+ exports.PasswordController = PasswordController = __decorate([
187
+ (0, common_1.Controller)(constants_1.ROUTES.auth.prefix),
188
+ (0, refresh_token_cookie_1.LibraryController)(),
189
+ (0, common_1.UsePipes)(strict_validation_pipe_1.strictValidationPipe),
190
+ __metadata("design:paramtypes", [password_auth_service_1.PasswordAuthService,
191
+ email_verification_service_1.EmailVerificationService])
192
+ ], PasswordController);
193
+ //# sourceMappingURL=password.controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"password.controller.js","sourceRoot":"","sources":["../../../src/features/passwords/password.controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /** POST /auth/register */
2
+ export declare class RegisterInput {
3
+ email: string;
4
+ password: string;
5
+ firstName?: string;
6
+ lastName?: string;
7
+ /** International format, e.g. +919876543210. */
8
+ phoneNumber?: string;
9
+ acceptTerms?: boolean;
10
+ acceptPrivacyPolicy?: boolean;
11
+ }
12
+ /** POST /auth/login */
13
+ export declare class SignInWithPasswordInput {
14
+ email: string;
15
+ password: string;
16
+ }
17
+ /** POST /auth/password/forgot, /auth/email/send-verification, /auth/email/send-otp, magic link */
18
+ export declare class EmailOnlyInput {
19
+ email: string;
20
+ }
21
+ /** POST /auth/password/reset */
22
+ export declare class ResetPasswordInput {
23
+ /** The token from the reset link. */
24
+ token: string;
25
+ newPassword: string;
26
+ }
27
+ /** POST /auth/password/change */
28
+ export declare class ChangePasswordInput {
29
+ /** Leave out only if the account has no password yet (signed up with Google etc.). */
30
+ currentPassword?: string;
31
+ newPassword: string;
32
+ }
33
+ /** Any endpoint that receives a single token: verify email, magic link, refresh, reactivate... */
34
+ export declare class TokenInput {
35
+ token: string;
36
+ }