@nauth-toolkit/core 0.1.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 (778) hide show
  1. package/dist/adapters/database-columns.d.ts +10 -0
  2. package/dist/adapters/database-columns.d.ts.map +1 -0
  3. package/dist/adapters/database-columns.js +85 -0
  4. package/dist/adapters/database-columns.js.map +1 -0
  5. package/dist/adapters/express.adapter.d.ts +41 -0
  6. package/dist/adapters/express.adapter.d.ts.map +1 -0
  7. package/dist/adapters/express.adapter.js +188 -0
  8. package/dist/adapters/express.adapter.js.map +1 -0
  9. package/dist/adapters/fastify.adapter.d.ts +33 -0
  10. package/dist/adapters/fastify.adapter.d.ts.map +1 -0
  11. package/dist/adapters/fastify.adapter.js +223 -0
  12. package/dist/adapters/fastify.adapter.js.map +1 -0
  13. package/dist/adapters/index.d.ts +5 -0
  14. package/dist/adapters/index.d.ts.map +1 -0
  15. package/dist/adapters/index.js +25 -0
  16. package/dist/adapters/index.js.map +1 -0
  17. package/dist/adapters/storage.factory.d.ts +7 -0
  18. package/dist/adapters/storage.factory.d.ts.map +1 -0
  19. package/dist/adapters/storage.factory.js +24 -0
  20. package/dist/adapters/storage.factory.js.map +1 -0
  21. package/dist/bootstrap.d.ts +41 -0
  22. package/dist/bootstrap.d.ts.map +1 -0
  23. package/dist/bootstrap.js +113 -0
  24. package/dist/bootstrap.js.map +1 -0
  25. package/dist/dto/auth-challenge.dto.d.ts +19 -0
  26. package/dist/dto/auth-challenge.dto.d.ts.map +1 -0
  27. package/dist/dto/auth-challenge.dto.js +86 -0
  28. package/dist/dto/auth-challenge.dto.js.map +1 -0
  29. package/dist/dto/auth-response.dto.d.ts +31 -0
  30. package/dist/dto/auth-response.dto.d.ts.map +1 -0
  31. package/dist/dto/auth-response.dto.js +18 -0
  32. package/dist/dto/auth-response.dto.js.map +1 -0
  33. package/dist/dto/challenge-response.dto.d.ts +36 -0
  34. package/dist/dto/challenge-response.dto.d.ts.map +1 -0
  35. package/dist/dto/challenge-response.dto.js +3 -0
  36. package/dist/dto/challenge-response.dto.js.map +1 -0
  37. package/dist/dto/change-password-request.dto.d.ts +5 -0
  38. package/dist/dto/change-password-request.dto.d.ts.map +1 -0
  39. package/dist/dto/change-password-request.dto.js +30 -0
  40. package/dist/dto/change-password-request.dto.js.map +1 -0
  41. package/dist/dto/change-password-response.dto.d.ts +4 -0
  42. package/dist/dto/change-password-response.dto.d.ts.map +1 -0
  43. package/dist/dto/change-password-response.dto.js +8 -0
  44. package/dist/dto/change-password-response.dto.js.map +1 -0
  45. package/dist/dto/change-password.dto.d.ts +5 -0
  46. package/dist/dto/change-password.dto.d.ts.map +1 -0
  47. package/dist/dto/change-password.dto.js +29 -0
  48. package/dist/dto/change-password.dto.js.map +1 -0
  49. package/dist/dto/error-response.dto.d.ts +9 -0
  50. package/dist/dto/error-response.dto.d.ts.map +1 -0
  51. package/dist/dto/error-response.dto.js +59 -0
  52. package/dist/dto/error-response.dto.js.map +1 -0
  53. package/dist/dto/get-available-methods.dto.d.ts +7 -0
  54. package/dist/dto/get-available-methods.dto.d.ts.map +1 -0
  55. package/dist/dto/get-available-methods.dto.js +33 -0
  56. package/dist/dto/get-available-methods.dto.js.map +1 -0
  57. package/dist/dto/get-challenge-data-response.dto.d.ts +4 -0
  58. package/dist/dto/get-challenge-data-response.dto.d.ts.map +1 -0
  59. package/dist/dto/get-challenge-data-response.dto.js +8 -0
  60. package/dist/dto/get-challenge-data-response.dto.js.map +1 -0
  61. package/dist/dto/get-challenge-data.dto.d.ts +8 -0
  62. package/dist/dto/get-challenge-data.dto.d.ts.map +1 -0
  63. package/dist/dto/get-challenge-data.dto.js +40 -0
  64. package/dist/dto/get-challenge-data.dto.js.map +1 -0
  65. package/dist/dto/get-client-info.dto.d.ts +17 -0
  66. package/dist/dto/get-client-info.dto.d.ts.map +1 -0
  67. package/dist/dto/get-client-info.dto.js +20 -0
  68. package/dist/dto/get-client-info.dto.js.map +1 -0
  69. package/dist/dto/get-device-token-response.dto.d.ts +4 -0
  70. package/dist/dto/get-device-token-response.dto.d.ts.map +1 -0
  71. package/dist/dto/get-device-token-response.dto.js +8 -0
  72. package/dist/dto/get-device-token-response.dto.js.map +1 -0
  73. package/dist/dto/get-events-by-type.dto.d.ts +17 -0
  74. package/dist/dto/get-events-by-type.dto.d.ts.map +1 -0
  75. package/dist/dto/get-events-by-type.dto.js +20 -0
  76. package/dist/dto/get-events-by-type.dto.js.map +1 -0
  77. package/dist/dto/get-ip-address-response.dto.d.ts +4 -0
  78. package/dist/dto/get-ip-address-response.dto.d.ts.map +1 -0
  79. package/dist/dto/get-ip-address-response.dto.js +8 -0
  80. package/dist/dto/get-ip-address-response.dto.js.map +1 -0
  81. package/dist/dto/get-mfa-status.dto.d.ts +16 -0
  82. package/dist/dto/get-mfa-status.dto.d.ts.map +1 -0
  83. package/dist/dto/get-mfa-status.dto.js +41 -0
  84. package/dist/dto/get-mfa-status.dto.js.map +1 -0
  85. package/dist/dto/get-risk-assessment-history.dto.d.ts +9 -0
  86. package/dist/dto/get-risk-assessment-history.dto.d.ts.map +1 -0
  87. package/dist/dto/get-risk-assessment-history.dto.js +13 -0
  88. package/dist/dto/get-risk-assessment-history.dto.js.map +1 -0
  89. package/dist/dto/get-session-id-response.dto.d.ts +4 -0
  90. package/dist/dto/get-session-id-response.dto.d.ts.map +1 -0
  91. package/dist/dto/get-session-id-response.dto.js +8 -0
  92. package/dist/dto/get-session-id-response.dto.js.map +1 -0
  93. package/dist/dto/get-setup-data-response.dto.d.ts +4 -0
  94. package/dist/dto/get-setup-data-response.dto.d.ts.map +1 -0
  95. package/dist/dto/get-setup-data-response.dto.js +8 -0
  96. package/dist/dto/get-setup-data-response.dto.js.map +1 -0
  97. package/dist/dto/get-setup-data.dto.d.ts +7 -0
  98. package/dist/dto/get-setup-data.dto.d.ts.map +1 -0
  99. package/dist/dto/get-setup-data.dto.js +43 -0
  100. package/dist/dto/get-setup-data.dto.js.map +1 -0
  101. package/dist/dto/get-suspicious-activity.dto.d.ts +9 -0
  102. package/dist/dto/get-suspicious-activity.dto.d.ts.map +1 -0
  103. package/dist/dto/get-suspicious-activity.dto.js +13 -0
  104. package/dist/dto/get-suspicious-activity.dto.js.map +1 -0
  105. package/dist/dto/get-user-agent-response.dto.d.ts +4 -0
  106. package/dist/dto/get-user-agent-response.dto.d.ts.map +1 -0
  107. package/dist/dto/get-user-agent-response.dto.js +8 -0
  108. package/dist/dto/get-user-agent-response.dto.js.map +1 -0
  109. package/dist/dto/get-user-auth-history.dto.d.ts +20 -0
  110. package/dist/dto/get-user-auth-history.dto.d.ts.map +1 -0
  111. package/dist/dto/get-user-auth-history.dto.js +22 -0
  112. package/dist/dto/get-user-auth-history.dto.js.map +1 -0
  113. package/dist/dto/get-user-by-email.dto.d.ts +5 -0
  114. package/dist/dto/get-user-by-email.dto.d.ts.map +1 -0
  115. package/dist/dto/get-user-by-email.dto.js +36 -0
  116. package/dist/dto/get-user-by-email.dto.js.map +1 -0
  117. package/dist/dto/get-user-by-id.dto.d.ts +4 -0
  118. package/dist/dto/get-user-by-id.dto.d.ts.map +1 -0
  119. package/dist/dto/get-user-by-id.dto.js +29 -0
  120. package/dist/dto/get-user-by-id.dto.js.map +1 -0
  121. package/dist/dto/get-user-devices.dto.d.ts +8 -0
  122. package/dist/dto/get-user-devices.dto.d.ts.map +1 -0
  123. package/dist/dto/get-user-devices.dto.js +33 -0
  124. package/dist/dto/get-user-devices.dto.js.map +1 -0
  125. package/dist/dto/get-user-response.dto.d.ts +2 -0
  126. package/dist/dto/get-user-response.dto.d.ts.map +1 -0
  127. package/dist/dto/get-user-response.dto.js +6 -0
  128. package/dist/dto/get-user-response.dto.js.map +1 -0
  129. package/dist/dto/has-provider.dto.d.ts +7 -0
  130. package/dist/dto/has-provider.dto.d.ts.map +1 -0
  131. package/dist/dto/has-provider.dto.js +38 -0
  132. package/dist/dto/has-provider.dto.js.map +1 -0
  133. package/dist/dto/index.d.ts +51 -0
  134. package/dist/dto/index.d.ts.map +1 -0
  135. package/dist/dto/index.js +67 -0
  136. package/dist/dto/index.js.map +1 -0
  137. package/dist/dto/is-trusted-device-response.dto.d.ts +4 -0
  138. package/dist/dto/is-trusted-device-response.dto.d.ts.map +1 -0
  139. package/dist/dto/is-trusted-device-response.dto.js +8 -0
  140. package/dist/dto/is-trusted-device-response.dto.js.map +1 -0
  141. package/dist/dto/list-providers-response.dto.d.ts +4 -0
  142. package/dist/dto/list-providers-response.dto.d.ts.map +1 -0
  143. package/dist/dto/list-providers-response.dto.js +8 -0
  144. package/dist/dto/list-providers-response.dto.js.map +1 -0
  145. package/dist/dto/login.dto.d.ts +7 -0
  146. package/dist/dto/login.dto.d.ts.map +1 -0
  147. package/dist/dto/login.dto.js +68 -0
  148. package/dist/dto/login.dto.js.map +1 -0
  149. package/dist/dto/logout-all-response.dto.d.ts +4 -0
  150. package/dist/dto/logout-all-response.dto.d.ts.map +1 -0
  151. package/dist/dto/logout-all-response.dto.js +8 -0
  152. package/dist/dto/logout-all-response.dto.js.map +1 -0
  153. package/dist/dto/logout-all.dto.d.ts +5 -0
  154. package/dist/dto/logout-all.dto.d.ts.map +1 -0
  155. package/dist/dto/logout-all.dto.js +42 -0
  156. package/dist/dto/logout-all.dto.js.map +1 -0
  157. package/dist/dto/logout-response.dto.d.ts +4 -0
  158. package/dist/dto/logout-response.dto.d.ts.map +1 -0
  159. package/dist/dto/logout-response.dto.js +8 -0
  160. package/dist/dto/logout-response.dto.js.map +1 -0
  161. package/dist/dto/logout.dto.d.ts +5 -0
  162. package/dist/dto/logout.dto.d.ts.map +1 -0
  163. package/dist/dto/logout.dto.js +36 -0
  164. package/dist/dto/logout.dto.js.map +1 -0
  165. package/dist/dto/refresh-token.dto.d.ts +4 -0
  166. package/dist/dto/refresh-token.dto.d.ts.map +1 -0
  167. package/dist/dto/refresh-token.dto.js +24 -0
  168. package/dist/dto/refresh-token.dto.js.map +1 -0
  169. package/dist/dto/remove-devices.dto.d.ts +9 -0
  170. package/dist/dto/remove-devices.dto.d.ts.map +1 -0
  171. package/dist/dto/remove-devices.dto.js +50 -0
  172. package/dist/dto/remove-devices.dto.js.map +1 -0
  173. package/dist/dto/resend-code-response.dto.d.ts +4 -0
  174. package/dist/dto/resend-code-response.dto.d.ts.map +1 -0
  175. package/dist/dto/resend-code-response.dto.js +8 -0
  176. package/dist/dto/resend-code-response.dto.js.map +1 -0
  177. package/dist/dto/resend-code.dto.d.ts +4 -0
  178. package/dist/dto/resend-code.dto.d.ts.map +1 -0
  179. package/dist/dto/resend-code.dto.js +29 -0
  180. package/dist/dto/resend-code.dto.js.map +1 -0
  181. package/dist/dto/reset-password.dto.d.ts +8 -0
  182. package/dist/dto/reset-password.dto.d.ts.map +1 -0
  183. package/dist/dto/reset-password.dto.js +61 -0
  184. package/dist/dto/reset-password.dto.js.map +1 -0
  185. package/dist/dto/respond-challenge.dto.d.ts +33 -0
  186. package/dist/dto/respond-challenge.dto.d.ts.map +1 -0
  187. package/dist/dto/respond-challenge.dto.js +131 -0
  188. package/dist/dto/respond-challenge.dto.js.map +1 -0
  189. package/dist/dto/set-mfa-exemption.dto.d.ts +12 -0
  190. package/dist/dto/set-mfa-exemption.dto.d.ts.map +1 -0
  191. package/dist/dto/set-mfa-exemption.dto.js +66 -0
  192. package/dist/dto/set-mfa-exemption.dto.js.map +1 -0
  193. package/dist/dto/set-must-change-password-response.dto.d.ts +4 -0
  194. package/dist/dto/set-must-change-password-response.dto.d.ts.map +1 -0
  195. package/dist/dto/set-must-change-password-response.dto.js +8 -0
  196. package/dist/dto/set-must-change-password-response.dto.js.map +1 -0
  197. package/dist/dto/set-must-change-password.dto.d.ts +4 -0
  198. package/dist/dto/set-must-change-password.dto.d.ts.map +1 -0
  199. package/dist/dto/set-must-change-password.dto.js +29 -0
  200. package/dist/dto/set-must-change-password.dto.js.map +1 -0
  201. package/dist/dto/set-preferred-method.dto.d.ts +8 -0
  202. package/dist/dto/set-preferred-method.dto.d.ts.map +1 -0
  203. package/dist/dto/set-preferred-method.dto.js +49 -0
  204. package/dist/dto/set-preferred-method.dto.js.map +1 -0
  205. package/dist/dto/setup-mfa.dto.d.ts +9 -0
  206. package/dist/dto/setup-mfa.dto.d.ts.map +1 -0
  207. package/dist/dto/setup-mfa.dto.js +55 -0
  208. package/dist/dto/setup-mfa.dto.js.map +1 -0
  209. package/dist/dto/signup.dto.d.ts +10 -0
  210. package/dist/dto/signup.dto.d.ts.map +1 -0
  211. package/dist/dto/signup.dto.js +109 -0
  212. package/dist/dto/signup.dto.js.map +1 -0
  213. package/dist/dto/social-auth.dto.d.ts +54 -0
  214. package/dist/dto/social-auth.dto.d.ts.map +1 -0
  215. package/dist/dto/social-auth.dto.js +232 -0
  216. package/dist/dto/social-auth.dto.js.map +1 -0
  217. package/dist/dto/trust-device-response.dto.d.ts +4 -0
  218. package/dist/dto/trust-device-response.dto.d.ts.map +1 -0
  219. package/dist/dto/trust-device-response.dto.js +8 -0
  220. package/dist/dto/trust-device-response.dto.js.map +1 -0
  221. package/dist/dto/trust-device.dto.d.ts +1 -0
  222. package/dist/dto/trust-device.dto.d.ts.map +1 -0
  223. package/dist/dto/trust-device.dto.js +2 -0
  224. package/dist/dto/trust-device.dto.js.map +1 -0
  225. package/dist/dto/update-user-attributes-request.dto.d.ts +5 -0
  226. package/dist/dto/update-user-attributes-request.dto.d.ts.map +1 -0
  227. package/dist/dto/update-user-attributes-request.dto.js +30 -0
  228. package/dist/dto/update-user-attributes-request.dto.js.map +1 -0
  229. package/dist/dto/user-response.dto.d.ts +20 -0
  230. package/dist/dto/user-response.dto.d.ts.map +1 -0
  231. package/dist/dto/user-response.dto.js +42 -0
  232. package/dist/dto/user-response.dto.js.map +1 -0
  233. package/dist/dto/user-update.dto.d.ts +12 -0
  234. package/dist/dto/user-update.dto.d.ts.map +1 -0
  235. package/dist/dto/user-update.dto.js +119 -0
  236. package/dist/dto/user-update.dto.js.map +1 -0
  237. package/dist/dto/verify-email.dto.d.ts +29 -0
  238. package/dist/dto/verify-email.dto.d.ts.map +1 -0
  239. package/dist/dto/verify-email.dto.js +161 -0
  240. package/dist/dto/verify-email.dto.js.map +1 -0
  241. package/dist/dto/verify-mfa-code.dto.d.ts +10 -0
  242. package/dist/dto/verify-mfa-code.dto.d.ts.map +1 -0
  243. package/dist/dto/verify-mfa-code.dto.js +56 -0
  244. package/dist/dto/verify-mfa-code.dto.js.map +1 -0
  245. package/dist/dto/verify-phone-by-sub.dto.d.ts +6 -0
  246. package/dist/dto/verify-phone-by-sub.dto.d.ts.map +1 -0
  247. package/dist/dto/verify-phone-by-sub.dto.js +49 -0
  248. package/dist/dto/verify-phone-by-sub.dto.js.map +1 -0
  249. package/dist/dto/verify-phone.dto.d.ts +24 -0
  250. package/dist/dto/verify-phone.dto.d.ts.map +1 -0
  251. package/dist/dto/verify-phone.dto.js +124 -0
  252. package/dist/dto/verify-phone.dto.js.map +1 -0
  253. package/dist/entities/auth-audit.entity.d.ts +31 -0
  254. package/dist/entities/auth-audit.entity.d.ts.map +1 -0
  255. package/dist/entities/auth-audit.entity.js +33 -0
  256. package/dist/entities/auth-audit.entity.js.map +1 -0
  257. package/dist/entities/challenge-session.entity.d.ts +17 -0
  258. package/dist/entities/challenge-session.entity.d.ts.map +1 -0
  259. package/dist/entities/challenge-session.entity.js +21 -0
  260. package/dist/entities/challenge-session.entity.js.map +1 -0
  261. package/dist/entities/index.d.ts +12 -0
  262. package/dist/entities/index.d.ts.map +1 -0
  263. package/dist/entities/index.js +26 -0
  264. package/dist/entities/index.js.map +1 -0
  265. package/dist/entities/login-attempt.entity.d.ts +13 -0
  266. package/dist/entities/login-attempt.entity.d.ts.map +1 -0
  267. package/dist/entities/login-attempt.entity.js +17 -0
  268. package/dist/entities/login-attempt.entity.js.map +1 -0
  269. package/dist/entities/mfa-device.entity.d.ts +22 -0
  270. package/dist/entities/mfa-device.entity.d.ts.map +1 -0
  271. package/dist/entities/mfa-device.entity.js +25 -0
  272. package/dist/entities/mfa-device.entity.js.map +1 -0
  273. package/dist/entities/rate-limit.entity.d.ts +9 -0
  274. package/dist/entities/rate-limit.entity.d.ts.map +1 -0
  275. package/dist/entities/rate-limit.entity.js +13 -0
  276. package/dist/entities/rate-limit.entity.js.map +1 -0
  277. package/dist/entities/session.entity.d.ts +32 -0
  278. package/dist/entities/session.entity.d.ts.map +1 -0
  279. package/dist/entities/session.entity.js +36 -0
  280. package/dist/entities/session.entity.js.map +1 -0
  281. package/dist/entities/social-account.entity.d.ts +13 -0
  282. package/dist/entities/social-account.entity.d.ts.map +1 -0
  283. package/dist/entities/social-account.entity.js +17 -0
  284. package/dist/entities/social-account.entity.js.map +1 -0
  285. package/dist/entities/storage-lock.entity.d.ts +8 -0
  286. package/dist/entities/storage-lock.entity.d.ts.map +1 -0
  287. package/dist/entities/storage-lock.entity.js +12 -0
  288. package/dist/entities/storage-lock.entity.js.map +1 -0
  289. package/dist/entities/trusted-device.entity.d.ts +17 -0
  290. package/dist/entities/trusted-device.entity.d.ts.map +1 -0
  291. package/dist/entities/trusted-device.entity.js +21 -0
  292. package/dist/entities/trusted-device.entity.js.map +1 -0
  293. package/dist/entities/user.entity.d.ts +41 -0
  294. package/dist/entities/user.entity.d.ts.map +1 -0
  295. package/dist/entities/user.entity.js +45 -0
  296. package/dist/entities/user.entity.js.map +1 -0
  297. package/dist/entities/verification-token.entity.d.ts +19 -0
  298. package/dist/entities/verification-token.entity.d.ts.map +1 -0
  299. package/dist/entities/verification-token.entity.js +29 -0
  300. package/dist/entities/verification-token.entity.js.map +1 -0
  301. package/dist/enums/auth-audit-event-type.enum.d.ts +55 -0
  302. package/dist/enums/auth-audit-event-type.enum.d.ts.map +1 -0
  303. package/dist/enums/auth-audit-event-type.enum.js +59 -0
  304. package/dist/enums/auth-audit-event-type.enum.js.map +1 -0
  305. package/dist/enums/error-codes.enum.d.ts +53 -0
  306. package/dist/enums/error-codes.enum.d.ts.map +1 -0
  307. package/dist/enums/error-codes.enum.js +57 -0
  308. package/dist/enums/error-codes.enum.js.map +1 -0
  309. package/dist/enums/mfa-method.enum.d.ts +11 -0
  310. package/dist/enums/mfa-method.enum.d.ts.map +1 -0
  311. package/dist/enums/mfa-method.enum.js +18 -0
  312. package/dist/enums/mfa-method.enum.js.map +1 -0
  313. package/dist/enums/risk-factor.enum.d.ts +14 -0
  314. package/dist/enums/risk-factor.enum.d.ts.map +1 -0
  315. package/dist/enums/risk-factor.enum.js +18 -0
  316. package/dist/enums/risk-factor.enum.js.map +1 -0
  317. package/dist/exceptions/nauth.exception.d.ts +18 -0
  318. package/dist/exceptions/nauth.exception.d.ts.map +1 -0
  319. package/dist/exceptions/nauth.exception.js +64 -0
  320. package/dist/exceptions/nauth.exception.js.map +1 -0
  321. package/dist/handlers/auth.handler.d.ts +18 -0
  322. package/dist/handlers/auth.handler.d.ts.map +1 -0
  323. package/dist/handlers/auth.handler.js +173 -0
  324. package/dist/handlers/auth.handler.js.map +1 -0
  325. package/dist/handlers/client-info.handler.d.ts +12 -0
  326. package/dist/handlers/client-info.handler.d.ts.map +1 -0
  327. package/dist/handlers/client-info.handler.js +61 -0
  328. package/dist/handlers/client-info.handler.js.map +1 -0
  329. package/dist/handlers/csrf.handler.d.ts +13 -0
  330. package/dist/handlers/csrf.handler.d.ts.map +1 -0
  331. package/dist/handlers/csrf.handler.js +84 -0
  332. package/dist/handlers/csrf.handler.js.map +1 -0
  333. package/dist/handlers/token-delivery.handler.d.ts +12 -0
  334. package/dist/handlers/token-delivery.handler.d.ts.map +1 -0
  335. package/dist/handlers/token-delivery.handler.js +86 -0
  336. package/dist/handlers/token-delivery.handler.js.map +1 -0
  337. package/dist/index.d.ts +27 -0
  338. package/dist/index.d.ts.map +1 -0
  339. package/dist/index.js +51 -0
  340. package/dist/index.js.map +1 -0
  341. package/dist/interfaces/client-info.interface.d.ts +16 -0
  342. package/dist/interfaces/client-info.interface.d.ts.map +1 -0
  343. package/dist/interfaces/client-info.interface.js +3 -0
  344. package/dist/interfaces/client-info.interface.js.map +1 -0
  345. package/dist/interfaces/config.interface.d.ts +279 -0
  346. package/dist/interfaces/config.interface.d.ts.map +1 -0
  347. package/dist/interfaces/config.interface.js +3 -0
  348. package/dist/interfaces/config.interface.js.map +1 -0
  349. package/dist/interfaces/entities.interface.d.ts +169 -0
  350. package/dist/interfaces/entities.interface.d.ts.map +1 -0
  351. package/dist/interfaces/entities.interface.js +3 -0
  352. package/dist/interfaces/entities.interface.js.map +1 -0
  353. package/dist/interfaces/index.d.ts +11 -0
  354. package/dist/interfaces/index.d.ts.map +1 -0
  355. package/dist/interfaces/index.js +27 -0
  356. package/dist/interfaces/index.js.map +1 -0
  357. package/dist/interfaces/logger.interface.d.ts +43 -0
  358. package/dist/interfaces/logger.interface.d.ts.map +1 -0
  359. package/dist/interfaces/logger.interface.js +12 -0
  360. package/dist/interfaces/logger.interface.js.map +1 -0
  361. package/dist/interfaces/mfa-provider.interface.d.ts +12 -0
  362. package/dist/interfaces/mfa-provider.interface.d.ts.map +1 -0
  363. package/dist/interfaces/mfa-provider.interface.js +3 -0
  364. package/dist/interfaces/mfa-provider.interface.js.map +1 -0
  365. package/dist/interfaces/oauth.interface.d.ts +24 -0
  366. package/dist/interfaces/oauth.interface.d.ts.map +1 -0
  367. package/dist/interfaces/oauth.interface.js +3 -0
  368. package/dist/interfaces/oauth.interface.js.map +1 -0
  369. package/dist/interfaces/provider.interface.d.ts +12 -0
  370. package/dist/interfaces/provider.interface.d.ts.map +1 -0
  371. package/dist/interfaces/provider.interface.js +3 -0
  372. package/dist/interfaces/provider.interface.js.map +1 -0
  373. package/dist/interfaces/social-auth-provider.interface.d.ts +13 -0
  374. package/dist/interfaces/social-auth-provider.interface.d.ts.map +1 -0
  375. package/dist/interfaces/social-auth-provider.interface.js +3 -0
  376. package/dist/interfaces/social-auth-provider.interface.js.map +1 -0
  377. package/dist/interfaces/storage-adapter.interface.d.ts +39 -0
  378. package/dist/interfaces/storage-adapter.interface.d.ts.map +1 -0
  379. package/dist/interfaces/storage-adapter.interface.js +3 -0
  380. package/dist/interfaces/storage-adapter.interface.js.map +1 -0
  381. package/dist/interfaces/template.interface.d.ts +99 -0
  382. package/dist/interfaces/template.interface.d.ts.map +1 -0
  383. package/dist/interfaces/template.interface.js +15 -0
  384. package/dist/interfaces/template.interface.js.map +1 -0
  385. package/dist/interfaces/token-verifier.interface.d.ts +7 -0
  386. package/dist/interfaces/token-verifier.interface.d.ts.map +1 -0
  387. package/dist/interfaces/token-verifier.interface.js +3 -0
  388. package/dist/interfaces/token-verifier.interface.js.map +1 -0
  389. package/dist/internal.d.ts +20 -0
  390. package/dist/internal.d.ts.map +1 -0
  391. package/dist/internal.js +53 -0
  392. package/dist/internal.js.map +1 -0
  393. package/dist/platform/interfaces.d.ts +56 -0
  394. package/dist/platform/interfaces.d.ts.map +1 -0
  395. package/dist/platform/interfaces.js +3 -0
  396. package/dist/platform/interfaces.js.map +1 -0
  397. package/dist/schemas/auth-config.schema.d.ts +3411 -0
  398. package/dist/schemas/auth-config.schema.d.ts.map +1 -0
  399. package/dist/schemas/auth-config.schema.js +428 -0
  400. package/dist/schemas/auth-config.schema.js.map +1 -0
  401. package/dist/services/adaptive-mfa-decision.service.d.ts +39 -0
  402. package/dist/services/adaptive-mfa-decision.service.d.ts.map +1 -0
  403. package/dist/services/adaptive-mfa-decision.service.js +223 -0
  404. package/dist/services/adaptive-mfa-decision.service.js.map +1 -0
  405. package/dist/services/auth-audit.service.d.ts +44 -0
  406. package/dist/services/auth-audit.service.d.ts.map +1 -0
  407. package/dist/services/auth-audit.service.js +241 -0
  408. package/dist/services/auth-audit.service.js.map +1 -0
  409. package/dist/services/auth-challenge-helper.service.d.ts +48 -0
  410. package/dist/services/auth-challenge-helper.service.d.ts.map +1 -0
  411. package/dist/services/auth-challenge-helper.service.js +425 -0
  412. package/dist/services/auth-challenge-helper.service.js.map +1 -0
  413. package/dist/services/auth-flow-context-builder.service.d.ts +31 -0
  414. package/dist/services/auth-flow-context-builder.service.d.ts.map +1 -0
  415. package/dist/services/auth-flow-context-builder.service.js +253 -0
  416. package/dist/services/auth-flow-context-builder.service.js.map +1 -0
  417. package/dist/services/auth-flow-rules.d.ts +18 -0
  418. package/dist/services/auth-flow-rules.d.ts.map +1 -0
  419. package/dist/services/auth-flow-rules.js +55 -0
  420. package/dist/services/auth-flow-rules.js.map +1 -0
  421. package/dist/services/auth-flow-state-definitions.d.ts +5 -0
  422. package/dist/services/auth-flow-state-definitions.d.ts.map +1 -0
  423. package/dist/services/auth-flow-state-definitions.js +87 -0
  424. package/dist/services/auth-flow-state-definitions.js.map +1 -0
  425. package/dist/services/auth-flow-state-machine.service.d.ts +17 -0
  426. package/dist/services/auth-flow-state-machine.service.d.ts.map +1 -0
  427. package/dist/services/auth-flow-state-machine.service.js +91 -0
  428. package/dist/services/auth-flow-state-machine.service.js.map +1 -0
  429. package/dist/services/auth-flow-state-machine.types.d.ts +55 -0
  430. package/dist/services/auth-flow-state-machine.types.d.ts.map +1 -0
  431. package/dist/services/auth-flow-state-machine.types.js +16 -0
  432. package/dist/services/auth-flow-state-machine.types.js.map +1 -0
  433. package/dist/services/auth.service.d.ts +87 -0
  434. package/dist/services/auth.service.d.ts.map +1 -0
  435. package/dist/services/auth.service.js +2356 -0
  436. package/dist/services/auth.service.js.map +1 -0
  437. package/dist/services/challenge.service.d.ts +32 -0
  438. package/dist/services/challenge.service.d.ts.map +1 -0
  439. package/dist/services/challenge.service.js +293 -0
  440. package/dist/services/challenge.service.js.map +1 -0
  441. package/dist/services/client-info.service.d.ts +20 -0
  442. package/dist/services/client-info.service.d.ts.map +1 -0
  443. package/dist/services/client-info.service.js +202 -0
  444. package/dist/services/client-info.service.js.map +1 -0
  445. package/dist/services/csrf.service.d.ts +13 -0
  446. package/dist/services/csrf.service.d.ts.map +1 -0
  447. package/dist/services/csrf.service.js +67 -0
  448. package/dist/services/csrf.service.js.map +1 -0
  449. package/dist/services/email-verification.service.d.ts +30 -0
  450. package/dist/services/email-verification.service.d.ts.map +1 -0
  451. package/dist/services/email-verification.service.js +373 -0
  452. package/dist/services/email-verification.service.js.map +1 -0
  453. package/dist/services/geo-location.service.d.ts +85 -0
  454. package/dist/services/geo-location.service.d.ts.map +1 -0
  455. package/dist/services/geo-location.service.js +338 -0
  456. package/dist/services/geo-location.service.js.map +1 -0
  457. package/dist/services/index.d.ts +14 -0
  458. package/dist/services/index.d.ts.map +1 -0
  459. package/dist/services/index.js +30 -0
  460. package/dist/services/index.js.map +1 -0
  461. package/dist/services/jwt.service.d.ts +62 -0
  462. package/dist/services/jwt.service.d.ts.map +1 -0
  463. package/dist/services/jwt.service.js +261 -0
  464. package/dist/services/jwt.service.js.map +1 -0
  465. package/dist/services/mfa-base.service.d.ts +37 -0
  466. package/dist/services/mfa-base.service.d.ts.map +1 -0
  467. package/dist/services/mfa-base.service.js +297 -0
  468. package/dist/services/mfa-base.service.js.map +1 -0
  469. package/dist/services/mfa.service.d.ts +35 -0
  470. package/dist/services/mfa.service.d.ts.map +1 -0
  471. package/dist/services/mfa.service.js +449 -0
  472. package/dist/services/mfa.service.js.map +1 -0
  473. package/dist/services/password.service.d.ts +19 -0
  474. package/dist/services/password.service.d.ts.map +1 -0
  475. package/dist/services/password.service.js +150 -0
  476. package/dist/services/password.service.js.map +1 -0
  477. package/dist/services/phone-verification.service.d.ts +32 -0
  478. package/dist/services/phone-verification.service.d.ts.map +1 -0
  479. package/dist/services/phone-verification.service.js +474 -0
  480. package/dist/services/phone-verification.service.js.map +1 -0
  481. package/dist/services/risk-detection.service.d.ts +30 -0
  482. package/dist/services/risk-detection.service.d.ts.map +1 -0
  483. package/dist/services/risk-detection.service.js +518 -0
  484. package/dist/services/risk-detection.service.js.map +1 -0
  485. package/dist/services/risk-scoring.service.d.ts +12 -0
  486. package/dist/services/risk-scoring.service.d.ts.map +1 -0
  487. package/dist/services/risk-scoring.service.js +44 -0
  488. package/dist/services/risk-scoring.service.js.map +1 -0
  489. package/dist/services/session.service.d.ts +64 -0
  490. package/dist/services/session.service.d.ts.map +1 -0
  491. package/dist/services/session.service.js +455 -0
  492. package/dist/services/session.service.js.map +1 -0
  493. package/dist/services/social-auth-base.service.d.ts +57 -0
  494. package/dist/services/social-auth-base.service.d.ts.map +1 -0
  495. package/dist/services/social-auth-base.service.js +340 -0
  496. package/dist/services/social-auth-base.service.js.map +1 -0
  497. package/dist/services/social-auth.service.d.ts +31 -0
  498. package/dist/services/social-auth.service.d.ts.map +1 -0
  499. package/dist/services/social-auth.service.js +172 -0
  500. package/dist/services/social-auth.service.js.map +1 -0
  501. package/dist/services/social-provider-registry.service.d.ts +9 -0
  502. package/dist/services/social-provider-registry.service.d.ts.map +1 -0
  503. package/dist/services/social-provider-registry.service.js +30 -0
  504. package/dist/services/social-provider-registry.service.js.map +1 -0
  505. package/dist/services/trusted-device.service.d.ts +29 -0
  506. package/dist/services/trusted-device.service.d.ts.map +1 -0
  507. package/dist/services/trusted-device.service.js +190 -0
  508. package/dist/services/trusted-device.service.js.map +1 -0
  509. package/dist/storage/account-lockout-storage.service.d.ts +16 -0
  510. package/dist/storage/account-lockout-storage.service.d.ts.map +1 -0
  511. package/dist/storage/account-lockout-storage.service.js +50 -0
  512. package/dist/storage/account-lockout-storage.service.js.map +1 -0
  513. package/dist/storage/index.d.ts +4 -0
  514. package/dist/storage/index.d.ts.map +1 -0
  515. package/dist/storage/index.js +20 -0
  516. package/dist/storage/index.js.map +1 -0
  517. package/dist/storage/memory-storage.adapter.d.ts +33 -0
  518. package/dist/storage/memory-storage.adapter.d.ts.map +1 -0
  519. package/dist/storage/memory-storage.adapter.js +195 -0
  520. package/dist/storage/memory-storage.adapter.js.map +1 -0
  521. package/dist/storage/rate-limit-storage.service.d.ts +11 -0
  522. package/dist/storage/rate-limit-storage.service.d.ts.map +1 -0
  523. package/dist/storage/rate-limit-storage.service.js +33 -0
  524. package/dist/storage/rate-limit-storage.service.js.map +1 -0
  525. package/dist/templates/html-template.engine.d.ts +16 -0
  526. package/dist/templates/html-template.engine.d.ts.map +1 -0
  527. package/dist/templates/html-template.engine.js +502 -0
  528. package/dist/templates/html-template.engine.js.map +1 -0
  529. package/dist/templates/index.d.ts +2 -0
  530. package/dist/templates/index.d.ts.map +1 -0
  531. package/dist/templates/index.js +18 -0
  532. package/dist/templates/index.js.map +1 -0
  533. package/dist/utils/common-passwords.d.ts +4 -0
  534. package/dist/utils/common-passwords.d.ts.map +1 -0
  535. package/dist/utils/common-passwords.js +108 -0
  536. package/dist/utils/common-passwords.js.map +1 -0
  537. package/dist/utils/context-storage.d.ts +13 -0
  538. package/dist/utils/context-storage.d.ts.map +1 -0
  539. package/dist/utils/context-storage.js +54 -0
  540. package/dist/utils/context-storage.js.map +1 -0
  541. package/dist/utils/cookie-names.util.d.ts +7 -0
  542. package/dist/utils/cookie-names.util.d.ts.map +1 -0
  543. package/dist/utils/cookie-names.util.js +30 -0
  544. package/dist/utils/cookie-names.util.js.map +1 -0
  545. package/dist/utils/cookies.util.d.ts +12 -0
  546. package/dist/utils/cookies.util.d.ts.map +1 -0
  547. package/dist/utils/cookies.util.js +48 -0
  548. package/dist/utils/cookies.util.js.map +1 -0
  549. package/dist/utils/index.d.ts +8 -0
  550. package/dist/utils/index.d.ts.map +1 -0
  551. package/dist/utils/index.js +24 -0
  552. package/dist/utils/index.js.map +1 -0
  553. package/dist/utils/ip-extractor.d.ts +12 -0
  554. package/dist/utils/ip-extractor.d.ts.map +1 -0
  555. package/dist/utils/ip-extractor.js +88 -0
  556. package/dist/utils/ip-extractor.js.map +1 -0
  557. package/dist/utils/nauth-logger.d.ts +20 -0
  558. package/dist/utils/nauth-logger.d.ts.map +1 -0
  559. package/dist/utils/nauth-logger.js +129 -0
  560. package/dist/utils/nauth-logger.js.map +1 -0
  561. package/dist/utils/pii-redactor.d.ts +16 -0
  562. package/dist/utils/pii-redactor.d.ts.map +1 -0
  563. package/dist/utils/pii-redactor.js +147 -0
  564. package/dist/utils/pii-redactor.js.map +1 -0
  565. package/dist/utils/setup/get-repositories.d.ts +16 -0
  566. package/dist/utils/setup/get-repositories.d.ts.map +1 -0
  567. package/dist/utils/setup/get-repositories.js +36 -0
  568. package/dist/utils/setup/get-repositories.js.map +1 -0
  569. package/dist/utils/setup/init-services.d.ts +41 -0
  570. package/dist/utils/setup/init-services.d.ts.map +1 -0
  571. package/dist/utils/setup/init-services.js +107 -0
  572. package/dist/utils/setup/init-services.js.map +1 -0
  573. package/dist/utils/setup/init-social.d.ts +13 -0
  574. package/dist/utils/setup/init-social.d.ts.map +1 -0
  575. package/dist/utils/setup/init-social.js +77 -0
  576. package/dist/utils/setup/init-social.js.map +1 -0
  577. package/dist/utils/setup/init-storage.d.ts +4 -0
  578. package/dist/utils/setup/init-storage.d.ts.map +1 -0
  579. package/dist/utils/setup/init-storage.js +79 -0
  580. package/dist/utils/setup/init-storage.js.map +1 -0
  581. package/dist/utils/setup/register-mfa.d.ts +5 -0
  582. package/dist/utils/setup/register-mfa.d.ts.map +1 -0
  583. package/dist/utils/setup/register-mfa.js +85 -0
  584. package/dist/utils/setup/register-mfa.js.map +1 -0
  585. package/dist/utils/setup/run-nauth-migrations.d.ts +5 -0
  586. package/dist/utils/setup/run-nauth-migrations.d.ts.map +1 -0
  587. package/dist/utils/setup/run-nauth-migrations.js +67 -0
  588. package/dist/utils/setup/run-nauth-migrations.js.map +1 -0
  589. package/dist/utils/token-delivery-policy.d.ts +6 -0
  590. package/dist/utils/token-delivery-policy.d.ts.map +1 -0
  591. package/dist/utils/token-delivery-policy.js +15 -0
  592. package/dist/utils/token-delivery-policy.js.map +1 -0
  593. package/dist/validators/template.validator.d.ts +7 -0
  594. package/dist/validators/template.validator.d.ts.map +1 -0
  595. package/dist/validators/template.validator.js +95 -0
  596. package/dist/validators/template.validator.js.map +1 -0
  597. package/jest.config.js +15 -0
  598. package/jest.setup.ts +6 -0
  599. package/package.json +73 -0
  600. package/src/adapters/database-columns.ts +165 -0
  601. package/src/adapters/express.adapter.ts +385 -0
  602. package/src/adapters/fastify.adapter.ts +416 -0
  603. package/src/adapters/index.ts +16 -0
  604. package/src/adapters/storage.factory.ts +143 -0
  605. package/src/bootstrap.ts +374 -0
  606. package/src/dto/auth-challenge.dto.ts +231 -0
  607. package/src/dto/auth-response.dto.ts +253 -0
  608. package/src/dto/challenge-response.dto.ts +234 -0
  609. package/src/dto/change-password-request.dto.ts +50 -0
  610. package/src/dto/change-password-response.dto.ts +29 -0
  611. package/src/dto/change-password.dto.ts +57 -0
  612. package/src/dto/error-response.dto.ts +136 -0
  613. package/src/dto/get-available-methods.dto.ts +55 -0
  614. package/src/dto/get-challenge-data-response.dto.ts +28 -0
  615. package/src/dto/get-challenge-data.dto.ts +69 -0
  616. package/src/dto/get-client-info.dto.ts +104 -0
  617. package/src/dto/get-device-token-response.dto.ts +25 -0
  618. package/src/dto/get-events-by-type.dto.ts +76 -0
  619. package/src/dto/get-ip-address-response.dto.ts +24 -0
  620. package/src/dto/get-mfa-status.dto.ts +94 -0
  621. package/src/dto/get-risk-assessment-history.dto.ts +39 -0
  622. package/src/dto/get-session-id-response.dto.ts +25 -0
  623. package/src/dto/get-setup-data-response.dto.ts +31 -0
  624. package/src/dto/get-setup-data.dto.ts +75 -0
  625. package/src/dto/get-suspicious-activity.dto.ts +42 -0
  626. package/src/dto/get-user-agent-response.dto.ts +23 -0
  627. package/src/dto/get-user-auth-history.dto.ts +95 -0
  628. package/src/dto/get-user-by-email.dto.ts +61 -0
  629. package/src/dto/get-user-by-id.dto.ts +46 -0
  630. package/src/dto/get-user-devices.dto.ts +53 -0
  631. package/src/dto/get-user-response.dto.ts +17 -0
  632. package/src/dto/has-provider.dto.ts +56 -0
  633. package/src/dto/index.ts +57 -0
  634. package/src/dto/is-trusted-device-response.dto.ts +34 -0
  635. package/src/dto/list-providers-response.dto.ts +23 -0
  636. package/src/dto/login.dto.ts +95 -0
  637. package/src/dto/logout-all-response.dto.ts +24 -0
  638. package/src/dto/logout-all.dto.ts +65 -0
  639. package/src/dto/logout-response.dto.ts +25 -0
  640. package/src/dto/logout.dto.ts +64 -0
  641. package/src/dto/refresh-token.dto.ts +36 -0
  642. package/src/dto/remove-devices.dto.ts +85 -0
  643. package/src/dto/resend-code-response.dto.ts +32 -0
  644. package/src/dto/resend-code.dto.ts +51 -0
  645. package/src/dto/reset-password.dto.ts +115 -0
  646. package/src/dto/respond-challenge.dto.ts +272 -0
  647. package/src/dto/set-mfa-exemption.dto.ts +112 -0
  648. package/src/dto/set-must-change-password-response.dto.ts +27 -0
  649. package/src/dto/set-must-change-password.dto.ts +46 -0
  650. package/src/dto/set-preferred-method.dto.ts +80 -0
  651. package/src/dto/setup-mfa.dto.ts +98 -0
  652. package/src/dto/signup.dto.ts +174 -0
  653. package/src/dto/social-auth.dto.ts +422 -0
  654. package/src/dto/trust-device-response.dto.ts +30 -0
  655. package/src/dto/trust-device.dto.ts +9 -0
  656. package/src/dto/update-user-attributes-request.dto.ts +51 -0
  657. package/src/dto/user-response.dto.ts +138 -0
  658. package/src/dto/user-update.dto.ts +222 -0
  659. package/src/dto/verify-email.dto.ts +313 -0
  660. package/src/dto/verify-mfa-code.dto.ts +103 -0
  661. package/src/dto/verify-phone-by-sub.dto.ts +78 -0
  662. package/src/dto/verify-phone.dto.ts +245 -0
  663. package/src/entities/auth-audit.entity.ts +232 -0
  664. package/src/entities/challenge-session.entity.ts +116 -0
  665. package/src/entities/index.ts +29 -0
  666. package/src/entities/login-attempt.entity.ts +64 -0
  667. package/src/entities/mfa-device.entity.ts +151 -0
  668. package/src/entities/rate-limit.entity.ts +44 -0
  669. package/src/entities/session.entity.ts +180 -0
  670. package/src/entities/social-account.entity.ts +96 -0
  671. package/src/entities/storage-lock.entity.ts +39 -0
  672. package/src/entities/trusted-device.entity.ts +112 -0
  673. package/src/entities/user.entity.ts +243 -0
  674. package/src/entities/verification-token.entity.ts +141 -0
  675. package/src/enums/auth-audit-event-type.enum.ts +360 -0
  676. package/src/enums/error-codes.enum.ts +420 -0
  677. package/src/enums/mfa-method.enum.ts +97 -0
  678. package/src/enums/risk-factor.enum.ts +111 -0
  679. package/src/exceptions/nauth.exception.ts +231 -0
  680. package/src/handlers/auth.handler.ts +260 -0
  681. package/src/handlers/client-info.handler.ts +101 -0
  682. package/src/handlers/csrf.handler.ts +156 -0
  683. package/src/handlers/token-delivery.handler.ts +118 -0
  684. package/src/index.ts +118 -0
  685. package/src/interfaces/client-info.interface.ts +85 -0
  686. package/src/interfaces/config.interface.ts +2135 -0
  687. package/src/interfaces/entities.interface.ts +226 -0
  688. package/src/interfaces/index.ts +15 -0
  689. package/src/interfaces/logger.interface.ts +283 -0
  690. package/src/interfaces/mfa-provider.interface.ts +154 -0
  691. package/src/interfaces/oauth.interface.ts +148 -0
  692. package/src/interfaces/provider.interface.ts +47 -0
  693. package/src/interfaces/social-auth-provider.interface.ts +131 -0
  694. package/src/interfaces/storage-adapter.interface.ts +82 -0
  695. package/src/interfaces/template.interface.ts +510 -0
  696. package/src/interfaces/token-verifier.interface.ts +110 -0
  697. package/src/internal.ts +178 -0
  698. package/src/platform/interfaces.ts +299 -0
  699. package/src/schemas/auth-config.schema.ts +646 -0
  700. package/src/services/adaptive-mfa-decision.service.spec.ts +1058 -0
  701. package/src/services/adaptive-mfa-decision.service.ts +457 -0
  702. package/src/services/auth-audit.service.spec.ts +675 -0
  703. package/src/services/auth-audit.service.ts +558 -0
  704. package/src/services/auth-challenge-helper.service.spec.ts +3227 -0
  705. package/src/services/auth-challenge-helper.service.ts +825 -0
  706. package/src/services/auth-flow-context-builder.service.ts +520 -0
  707. package/src/services/auth-flow-rules.ts +202 -0
  708. package/src/services/auth-flow-state-definitions.ts +190 -0
  709. package/src/services/auth-flow-state-machine.service.ts +207 -0
  710. package/src/services/auth-flow-state-machine.types.ts +316 -0
  711. package/src/services/auth.service.spec.ts +4195 -0
  712. package/src/services/auth.service.ts +3727 -0
  713. package/src/services/challenge.service.spec.ts +1363 -0
  714. package/src/services/challenge.service.ts +696 -0
  715. package/src/services/client-info.service.spec.ts +572 -0
  716. package/src/services/client-info.service.ts +374 -0
  717. package/src/services/csrf.service.ts +54 -0
  718. package/src/services/email-verification.service.spec.ts +1229 -0
  719. package/src/services/email-verification.service.ts +578 -0
  720. package/src/services/geo-location.service.spec.ts +603 -0
  721. package/src/services/geo-location.service.ts +599 -0
  722. package/src/services/index.ts +13 -0
  723. package/src/services/jwt.service.spec.ts +882 -0
  724. package/src/services/jwt.service.ts +621 -0
  725. package/src/services/mfa-base.service.spec.ts +246 -0
  726. package/src/services/mfa-base.service.ts +611 -0
  727. package/src/services/mfa.service.spec.ts +693 -0
  728. package/src/services/mfa.service.ts +960 -0
  729. package/src/services/password.service.spec.ts +166 -0
  730. package/src/services/password.service.ts +309 -0
  731. package/src/services/phone-verification.service.spec.ts +1120 -0
  732. package/src/services/phone-verification.service.ts +751 -0
  733. package/src/services/risk-detection.service.spec.ts +1292 -0
  734. package/src/services/risk-detection.service.ts +1012 -0
  735. package/src/services/risk-scoring.service.spec.ts +204 -0
  736. package/src/services/risk-scoring.service.ts +131 -0
  737. package/src/services/session.service.spec.ts +1293 -0
  738. package/src/services/session.service.ts +803 -0
  739. package/src/services/social-account.service.spec.ts +725 -0
  740. package/src/services/social-auth-base.service.spec.ts +418 -0
  741. package/src/services/social-auth-base.service.ts +581 -0
  742. package/src/services/social-auth.service.spec.ts +238 -0
  743. package/src/services/social-auth.service.ts +436 -0
  744. package/src/services/social-provider-registry.service.spec.ts +238 -0
  745. package/src/services/social-provider-registry.service.ts +122 -0
  746. package/src/services/trusted-device.service.spec.ts +505 -0
  747. package/src/services/trusted-device.service.ts +339 -0
  748. package/src/storage/account-lockout-storage.service.spec.ts +310 -0
  749. package/src/storage/account-lockout-storage.service.ts +89 -0
  750. package/src/storage/index.ts +3 -0
  751. package/src/storage/memory-storage.adapter.ts +443 -0
  752. package/src/storage/rate-limit-storage.service.spec.ts +247 -0
  753. package/src/storage/rate-limit-storage.service.ts +38 -0
  754. package/src/templates/html-template.engine.spec.ts +161 -0
  755. package/src/templates/html-template.engine.ts +688 -0
  756. package/src/templates/index.ts +7 -0
  757. package/src/utils/common-passwords.spec.ts +230 -0
  758. package/src/utils/common-passwords.ts +170 -0
  759. package/src/utils/context-storage.ts +188 -0
  760. package/src/utils/cookie-names.util.ts +67 -0
  761. package/src/utils/cookies.util.ts +94 -0
  762. package/src/utils/index.ts +12 -0
  763. package/src/utils/ip-extractor.spec.ts +330 -0
  764. package/src/utils/ip-extractor.ts +220 -0
  765. package/src/utils/nauth-logger.spec.ts +388 -0
  766. package/src/utils/nauth-logger.ts +215 -0
  767. package/src/utils/pii-redactor.spec.ts +130 -0
  768. package/src/utils/pii-redactor.ts +288 -0
  769. package/src/utils/setup/get-repositories.ts +140 -0
  770. package/src/utils/setup/init-services.ts +422 -0
  771. package/src/utils/setup/init-social.ts +189 -0
  772. package/src/utils/setup/init-storage.ts +94 -0
  773. package/src/utils/setup/register-mfa.ts +165 -0
  774. package/src/utils/setup/run-nauth-migrations.ts +61 -0
  775. package/src/utils/token-delivery-policy.ts +38 -0
  776. package/src/validators/template.validator.ts +219 -0
  777. package/tsconfig.json +37 -0
  778. package/tsconfig.lint.json +6 -0
@@ -0,0 +1,751 @@
1
+ import { Repository, IsNull } from 'typeorm';
2
+ import { IUser, IVerificationToken } from '../interfaces/entities.interface';
3
+ import { BaseVerificationToken, BaseUser } from '../entities';
4
+ import { SMSProvider } from '../interfaces/provider.interface';
5
+ import { StorageAdapter } from '../interfaces/storage-adapter.interface';
6
+ import { NAuthConfig } from '../interfaces/config.interface';
7
+ import { ClientInfoService } from './client-info.service';
8
+ import { InternalAuthAuditService as AuthAuditService } from './auth-audit.service';
9
+ import { AuthAuditEventType } from '../enums/auth-audit-event-type.enum';
10
+ import { NAuthException } from '../exceptions/nauth.exception';
11
+ import { AuthErrorCode } from '../enums/error-codes.enum';
12
+ import { NAuthLogger } from '../utils/nauth-logger';
13
+ import {
14
+ SendVerificationSMSDTO,
15
+ SendVerificationSMSResponseDTO,
16
+ VerifyPhoneWithCodeDTO,
17
+ VerifyPhoneResponseDTO,
18
+ ResendVerificationSMSDTO,
19
+ ResendVerificationSMSResponseDTO,
20
+ } from '../dto/verify-phone.dto';
21
+ import { VerifyPhoneWithCodeBySubDTO } from '../dto/verify-phone-by-sub.dto';
22
+ import * as crypto from 'crypto';
23
+
24
+ /**
25
+ * Phone Verification Service (Core)
26
+ *
27
+ * Database-agnostic phone verification workflow with provider-driven SMS delivery.
28
+ *
29
+ * WHY: Keeps core business logic independent of database and SMS vendors. Databases are
30
+ * injected via repository tokens and SMS via an `SMSProvider` adapter so consumers
31
+ * can plug in Postgres, MySQL, or any SMS provider without code changes.
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * // Send OTP
36
+ * const tokenId = await phoneVerificationService.sendVerificationSMS('user-sub');
37
+ *
38
+ * // Verify by sub
39
+ * await phoneVerificationService.verifyPhoneWithCodeBySub('user-sub', '123456');
40
+ *
41
+ * // Resend
42
+ * await phoneVerificationService.resendVerificationSMS('user-sub');
43
+ * ```
44
+ */
45
+ export class PhoneVerificationService {
46
+ constructor(
47
+ private readonly verificationTokenRepo: Repository<BaseVerificationToken>,
48
+ private readonly userRepo: Repository<BaseUser>,
49
+ private readonly smsProvider: SMSProvider,
50
+ private readonly storageAdapter: StorageAdapter,
51
+ private readonly config: NAuthConfig,
52
+ private readonly clientInfoService: ClientInfoService,
53
+ private readonly logger: NAuthLogger,
54
+ private readonly auditService?: AuthAuditService, // Optional - audit trail service (enabled via config.auditLogs.enabled)
55
+ ) {}
56
+
57
+ /**
58
+ * Send verification SMS to user identified by `sub`.
59
+ * Applies rate limits and resend delay, stores hashed token + OTP, and sends via SMS provider.
60
+ *
61
+ * @param dto - Request DTO containing sub and skipAlreadyVerifiedCheck
62
+ * @returns Response DTO with verification token ID
63
+ * @throws {NAuthException} RATE_LIMIT_SMS | NOT_FOUND | PHONE_REQUIRED | ALREADY_VERIFIED | RATE_LIMIT_RESEND
64
+ */
65
+ async sendVerificationSMS(dto: SendVerificationSMSDTO): Promise<SendVerificationSMSResponseDTO> {
66
+ const { sub, skipAlreadyVerifiedCheck = true, challengeSessionId } = dto;
67
+ const rateLimitKey = `phone-verification:${sub}`;
68
+
69
+ // Get rate limit configuration from config (moved to signup.phoneVerification)
70
+ const rateLimitMax = this.config.signup?.phoneVerification?.rateLimitMax || 3;
71
+ const rateLimitWindow = this.config.signup?.phoneVerification?.rateLimitWindow || 3600; // 1 hour in seconds
72
+
73
+ // Check if key exists and has valid TTL (not expired)
74
+ const ttlBefore = await this.storageAdapter.ttl(rateLimitKey);
75
+ // Window is expired if: key doesn't exist (-1), expired (<0), or TTL is longer than configured window (config changed)
76
+ const isWindowExpired = ttlBefore === -1 || ttlBefore < 0 || ttlBefore > rateLimitWindow;
77
+
78
+ // If TTL is longer than configured window (config changed), delete the old key to reset it
79
+ // This ensures the new window uses the current rateLimitWindow instead of preserving old expiry
80
+ if (ttlBefore > rateLimitWindow) {
81
+ await this.storageAdapter.del(rateLimitKey);
82
+ }
83
+
84
+ // Increment counter (will reset to 1 if key expired or doesn't exist)
85
+ // Pass TTL so new records are created with correct expiry immediately
86
+ const currentCount = await this.storageAdapter.incr(rateLimitKey, isWindowExpired ? rateLimitWindow : undefined);
87
+
88
+ // If we created a new window, log it
89
+ if (isWindowExpired && currentCount === 1) {
90
+ this.logger?.debug?.(
91
+ `Rate limit window reset for phone verification: sub=${sub}, window=${rateLimitWindow}s, max=${rateLimitMax}`,
92
+ );
93
+ }
94
+
95
+ // Get actual TTL after setting expiry (for error message)
96
+ const actualTtl = await this.storageAdapter.ttl(rateLimitKey);
97
+
98
+ this.logger?.debug?.(
99
+ `Phone verification rate limit check: sub=${sub}, count=${currentCount}/${rateLimitMax}, ttl=${actualTtl}s`,
100
+ );
101
+
102
+ if (currentCount > rateLimitMax) {
103
+ this.logger?.warn?.(
104
+ `SMS rate limit exceeded: sub=${sub}, count=${currentCount}, max=${rateLimitMax}, retryAfter=${actualTtl}s`,
105
+ );
106
+ throw new NAuthException(
107
+ AuthErrorCode.RATE_LIMIT_SMS,
108
+ `Too many verification SMS sent. Please try again in ${actualTtl > 0 ? actualTtl : rateLimitWindow} seconds`,
109
+ {
110
+ retryAfter: actualTtl > 0 ? actualTtl : rateLimitWindow,
111
+ currentCount,
112
+ maxAttempts: rateLimitMax,
113
+ },
114
+ );
115
+ }
116
+
117
+ // Load user by external identifier
118
+ const user = (await this.userRepo.findOne({ where: { sub } })) as IUser | null;
119
+ if (!user) {
120
+ throw new NAuthException(AuthErrorCode.NOT_FOUND, 'User not found');
121
+ }
122
+ if (!user.phone) {
123
+ throw new NAuthException(AuthErrorCode.PHONE_REQUIRED, 'No phone number associated with this account');
124
+ }
125
+ // Only check "already verified" if not skipping (skip for MFA contexts where codes are needed even if phone is verified)
126
+ if (!skipAlreadyVerifiedCheck && user.isPhoneVerified) {
127
+ throw new NAuthException(AuthErrorCode.ALREADY_VERIFIED, 'Phone already verified');
128
+ }
129
+
130
+ // Enforce resend delay to prevent abuse
131
+ const resendDelay = this.config.signup?.phoneVerification?.resendDelay ?? 60;
132
+ const lastToken = (await this.verificationTokenRepo.findOne({
133
+ where: { userId: user.id, type: 'phone' },
134
+ order: { createdAt: 'DESC' },
135
+ })) as IVerificationToken | null;
136
+ if (lastToken) {
137
+ const secondsSinceLastSend = (Date.now() - lastToken.createdAt.getTime()) / 1000;
138
+ if (secondsSinceLastSend < resendDelay) {
139
+ const waitSeconds = Math.ceil(resendDelay - secondsSinceLastSend);
140
+ throw new NAuthException(
141
+ AuthErrorCode.RATE_LIMIT_RESEND,
142
+ `Please wait ${waitSeconds} seconds before requesting another code`,
143
+ {
144
+ retryAfter: waitSeconds,
145
+ resendDelay,
146
+ },
147
+ );
148
+ }
149
+ }
150
+
151
+ // Invalidate existing unused tokens for this user
152
+ await this.verificationTokenRepo.update(
153
+ { userId: user.id, type: 'phone', usedAt: IsNull() },
154
+ { usedAt: new Date() },
155
+ );
156
+
157
+ // Generate OTP and hashed token
158
+ const code = this.generateCode();
159
+ const token = this.generateToken();
160
+ const tokenHash = this.hashToken(token);
161
+
162
+ // Capture client info for auditability
163
+ const clientInfo = this.clientInfoService.get();
164
+ const { ipAddress, userAgent } = clientInfo;
165
+
166
+ const verificationToken = this.verificationTokenRepo.create({
167
+ userId: user.id,
168
+ challengeSessionId: challengeSessionId ?? null, // Link to challenge session if provided
169
+ type: 'phone',
170
+ token: tokenHash,
171
+ code,
172
+ expiresAt: new Date(Date.now() + (this.config.signup?.phoneVerification?.expiresIn || 300) * 1000),
173
+ attempts: 0,
174
+ ipAddress,
175
+ userAgent,
176
+ });
177
+
178
+ const saved = (await this.verificationTokenRepo.save(verificationToken)) as unknown as IVerificationToken;
179
+
180
+ this.logger?.log?.(
181
+ `SMS token created: sub=${sub}, tokenId=${saved.id}, code=${code}, codeType=${typeof code}, userId=${user.id}, usedAt=${saved.usedAt || 'null'}`,
182
+ );
183
+
184
+ await this.smsProvider.sendOTP(user.phone, code);
185
+ this.logger?.log?.(
186
+ `SMS verification code sent: sub=${sub}, tokenId=${saved.id}, phone=${this.maskPhone(user.phone)}`,
187
+ );
188
+
189
+ // ============================================================================
190
+ // Audit: Record phone verification request
191
+ // ============================================================================
192
+ try {
193
+ await this.auditService?.recordEvent({
194
+ userId: user.id,
195
+ eventType: AuthAuditEventType.PHONE_VERIFICATION_REQUESTED,
196
+ eventStatus: 'INFO',
197
+ metadata: {
198
+ // Client info automatically included from context
199
+ verificationTokenId: saved.id,
200
+ phone: this.maskPhone(user.phone),
201
+ },
202
+ });
203
+ } catch (auditError) {
204
+ // Non-blocking: Log but continue
205
+ const errorMessage = auditError instanceof Error ? auditError.message : 'Unknown error';
206
+ this.logger?.error?.(`Failed to record PHONE_VERIFICATION_REQUESTED audit event: ${errorMessage}`, {
207
+ error: auditError,
208
+ userId: user.id,
209
+ });
210
+ }
211
+
212
+ return { tokenId: saved.id };
213
+ }
214
+
215
+ /**
216
+ * Verify phone by phone number and code.
217
+ * Handles duplicate phone numbers by selecting the token whose user matches the phone provided.
218
+ *
219
+ * @param dto - Request DTO containing phone and code
220
+ * @returns Response DTO with success message
221
+ * @throws {NAuthException} VERIFICATION_CODE_INVALID | VERIFICATION_CODE_EXPIRED | VERIFICATION_TOO_MANY_ATTEMPTS
222
+ */
223
+ async verifyPhoneWithCode(dto: VerifyPhoneWithCodeDTO): Promise<VerifyPhoneResponseDTO> {
224
+ const { phone, code, challengeSessionId } = dto;
225
+ // Find all unused tokens matching the code and type
226
+ // If challengeSessionId is provided, ensure token belongs to specific session
227
+ const whereClause = {
228
+ type: 'phone' as const,
229
+ code,
230
+ usedAt: IsNull(),
231
+ ...(challengeSessionId !== undefined && { challengeSessionId }), // Include if provided
232
+ };
233
+
234
+ const candidateTokens = (await this.verificationTokenRepo.find({
235
+ where: whereClause,
236
+ order: { createdAt: 'DESC' },
237
+ })) as unknown as IVerificationToken[];
238
+
239
+ // Resolve the token whose user has the given phone
240
+ let matched: { token: IVerificationToken; user: IUser } | null = null;
241
+ for (const token of candidateTokens) {
242
+ const user = (await this.userRepo.findOne({ where: { id: token.userId } })) as IUser | null;
243
+ if (user && user.phone === phone) {
244
+ matched = { token, user };
245
+ break;
246
+ }
247
+ }
248
+
249
+ if (!matched) {
250
+ throw new NAuthException(AuthErrorCode.VERIFICATION_CODE_INVALID, 'Invalid or expired verification code');
251
+ }
252
+
253
+ const { token, user } = matched;
254
+
255
+ // Get verification attempt rate limit configuration from config
256
+ const maxAttemptsPerUser = this.config.signup?.phoneVerification?.maxAttemptsPerUser ?? 10;
257
+ const maxAttemptsPerIP = this.config.signup?.phoneVerification?.maxAttemptsPerIP ?? 20;
258
+ const attemptWindow = this.config.signup?.phoneVerification?.attemptWindow ?? 3600; // 1 hour
259
+
260
+ // Rate limit verification attempts per user (not just per token)
261
+ const userRateLimitKey = `verify-attempts:user:${user.id}`;
262
+ const userAttempts = await this.storageAdapter.incr(userRateLimitKey);
263
+
264
+ if (userAttempts === 1) {
265
+ await this.storageAdapter.expire(userRateLimitKey, attemptWindow);
266
+ }
267
+
268
+ if (userAttempts > maxAttemptsPerUser) {
269
+ throw new NAuthException(
270
+ AuthErrorCode.VERIFICATION_TOO_MANY_ATTEMPTS,
271
+ 'Too many verification attempts. Please try again later.',
272
+ );
273
+ }
274
+
275
+ // Also rate limit by IP
276
+ const clientInfo = this.clientInfoService.get();
277
+ if (clientInfo.ipAddress) {
278
+ const ipRateLimitKey = `verify-attempts:ip:${clientInfo.ipAddress}`;
279
+ const ipAttempts = await this.storageAdapter.incr(ipRateLimitKey);
280
+
281
+ if (ipAttempts === 1) {
282
+ await this.storageAdapter.expire(ipRateLimitKey, attemptWindow);
283
+ }
284
+
285
+ if (ipAttempts > maxAttemptsPerIP) {
286
+ throw new NAuthException(
287
+ AuthErrorCode.VERIFICATION_TOO_MANY_ATTEMPTS,
288
+ 'Too many verification attempts from this IP. Please try again later.',
289
+ );
290
+ }
291
+ }
292
+
293
+ // Expiry check (use entity method if provided)
294
+ const isExpired =
295
+ typeof token.isExpired === 'function' ? !!token.isExpired() : token.expiresAt.getTime() <= Date.now();
296
+ if (isExpired) {
297
+ throw new NAuthException(AuthErrorCode.VERIFICATION_CODE_EXPIRED, 'Verification code has expired');
298
+ }
299
+
300
+ // Attempts check (use entity method if provided)
301
+ const maxAttempts = this.config.signup?.phoneVerification?.maxAttempts ?? 3;
302
+ const tooManyAttempts =
303
+ typeof token.maxAttemptsExceeded === 'function'
304
+ ? !!token.maxAttemptsExceeded(maxAttempts)
305
+ : token.attempts >= maxAttempts;
306
+ if (tooManyAttempts) {
307
+ throw new NAuthException(
308
+ AuthErrorCode.VERIFICATION_TOO_MANY_ATTEMPTS,
309
+ 'Too many failed attempts. Request a new code.',
310
+ {
311
+ maxAttempts,
312
+ currentAttempts: token.attempts,
313
+ },
314
+ );
315
+ }
316
+
317
+ // Increment attempts even on success to prevent reuse by race
318
+ token.attempts += 1;
319
+ if (token.code !== code) {
320
+ await this.verificationTokenRepo.save(token);
321
+ this.logger?.debug?.(
322
+ `Phone verification failed: phone=${this.maskPhone(phone)}, attempts=${token.attempts}/${maxAttempts}`,
323
+ );
324
+
325
+ // ============================================================================
326
+ // Audit: Record phone verification failure
327
+ // ============================================================================
328
+ try {
329
+ await this.auditService?.recordEvent({
330
+ userId: user.id,
331
+ eventType: AuthAuditEventType.PHONE_VERIFICATION_FAILED,
332
+ eventStatus: 'FAILURE',
333
+ reason: 'invalid_code',
334
+ // Client info automatically included from context
335
+ description: 'Invalid verification code provided',
336
+ metadata: {
337
+ verificationTokenId: token.id,
338
+ attempts: token.attempts,
339
+ phone: this.maskPhone(phone),
340
+ },
341
+ });
342
+ } catch (auditError) {
343
+ // Non-blocking: Log but continue
344
+ const errorMessage = auditError instanceof Error ? auditError.message : 'Unknown error';
345
+ this.logger?.error?.(`Failed to record PHONE_VERIFICATION_FAILED audit event: ${errorMessage}`, {
346
+ error: auditError,
347
+ userId: user.id,
348
+ });
349
+ }
350
+
351
+ throw new NAuthException(AuthErrorCode.VERIFICATION_CODE_INVALID, 'Invalid verification code', {
352
+ attemptsRemaining: Math.max(0, maxAttempts - token.attempts),
353
+ });
354
+ }
355
+
356
+ // Mark token used
357
+ token.usedAt = new Date();
358
+ await this.verificationTokenRepo.save(token);
359
+
360
+ // Update user flags
361
+ await this.userRepo.update(user.id, {
362
+ isPhoneVerified: true,
363
+ isActive: true,
364
+ });
365
+
366
+ this.logger?.log?.(`Phone verification successful: userId=${user.id}, phone=${this.maskPhone(phone)}`);
367
+
368
+ // ============================================================================
369
+ // Audit: Record phone verification success
370
+ // ============================================================================
371
+ try {
372
+ // Client info (ipAddress, userAgent) automatically extracted from ClientInfoService
373
+ // Note: ClientInfoService is used transparently by AuditService
374
+ await this.auditService?.recordEvent({
375
+ userId: user.id,
376
+ eventType: AuthAuditEventType.PHONE_VERIFIED,
377
+ eventStatus: 'SUCCESS',
378
+ metadata: {
379
+ // Client info automatically included from context
380
+ verificationTokenId: token.id,
381
+ verificationMethod: 'code',
382
+ phone: this.maskPhone(phone),
383
+ },
384
+ });
385
+ } catch (auditError) {
386
+ // Non-blocking: Log but continue
387
+ const errorMessage = auditError instanceof Error ? auditError.message : 'Unknown error';
388
+ this.logger?.error?.(`Failed to record PHONE_VERIFIED audit event: ${errorMessage}`, {
389
+ error: auditError,
390
+ userId: user.id,
391
+ });
392
+ }
393
+
394
+ return { message: 'Phone verified successfully. Please log in to continue.' };
395
+ }
396
+
397
+ /**
398
+ * Verify phone by user sub and code.
399
+ *
400
+ * @param dto - Request DTO containing sub and code
401
+ * @returns Response DTO with success message
402
+ */
403
+ async verifyPhoneWithCodeBySub(dto: VerifyPhoneWithCodeBySubDTO): Promise<VerifyPhoneResponseDTO> {
404
+ const { sub, code, challengeSessionId } = dto;
405
+ // Load user to get current phone verification status
406
+ // This ensures we have the latest state from the database
407
+ const user = (await this.userRepo.findOne({ where: { sub } })) as IUser | null;
408
+ if (!user) {
409
+ throw new NAuthException(AuthErrorCode.NOT_FOUND, 'User not found');
410
+ }
411
+ if (!user.phone) {
412
+ throw new NAuthException(AuthErrorCode.PHONE_REQUIRED, 'No phone number associated with this account');
413
+ }
414
+
415
+ // Store initial verification status to avoid unnecessary updates
416
+ const wasPhoneVerified = Boolean(user.isPhoneVerified);
417
+
418
+ // ============================================================================
419
+ // Security: Rate limit configuration
420
+ // IP-based rate limiting applies only to INVALID attempts to prevent brute force
421
+ // Valid codes should not be blocked by IP rate limits
422
+ // ============================================================================
423
+ const maxAttemptsPerIP = this.config.signup?.phoneVerification?.maxAttemptsPerIP ?? 20;
424
+ const attemptWindow = this.config.signup?.phoneVerification?.attemptWindow ?? 3600; // 1 hour
425
+ const clientInfo = this.clientInfoService.get();
426
+
427
+ // Find verification token
428
+ // Query for unused tokens matching the code (order by newest first)
429
+ // Ensure code is a string (database stores as varchar/string)
430
+ // TypeORM may receive code as number from JSON, so convert to string for query
431
+ const codeString = String(code);
432
+ this.logger?.log?.(
433
+ `Looking for verification token: sub=${sub}, code=${codeString}, codeType=${typeof code}, userId=${user.id}`,
434
+ );
435
+ // If challengeSessionId is provided, ensure token belongs to specific session
436
+ const whereClause = {
437
+ userId: user.id,
438
+ type: 'phone' as const,
439
+ code: codeString,
440
+ usedAt: IsNull(),
441
+ ...(challengeSessionId !== undefined && { challengeSessionId }), // Include if provided
442
+ };
443
+
444
+ const verificationToken = (await this.verificationTokenRepo.findOne({
445
+ where: whereClause,
446
+ order: { createdAt: 'DESC' },
447
+ })) as IVerificationToken | null;
448
+
449
+ // ============================================================================
450
+ // Security: Increment IP rate limit for invalid attempts only
451
+ // This prevents brute force attacks while allowing valid codes through
452
+ // ============================================================================
453
+ const incrementIPRateLimit = async (): Promise<void> => {
454
+ if (clientInfo.ipAddress) {
455
+ const ipRateLimitKey = `verify-attempts:ip:${clientInfo.ipAddress}`;
456
+ const ipAttempts = await this.storageAdapter.incr(ipRateLimitKey);
457
+
458
+ if (ipAttempts === 1) {
459
+ await this.storageAdapter.expire(ipRateLimitKey, attemptWindow);
460
+ }
461
+
462
+ if (ipAttempts > maxAttemptsPerIP) {
463
+ throw new NAuthException(
464
+ AuthErrorCode.VERIFICATION_TOO_MANY_ATTEMPTS,
465
+ 'Too many verification attempts from this IP. Please try again later.',
466
+ );
467
+ }
468
+ }
469
+ };
470
+
471
+ if (!verificationToken) {
472
+ this.logger?.warn?.(
473
+ `Phone verification token not found: sub=${sub}, code=${codeString}, originalCodeType=${typeof code}, userId=${user.id}`,
474
+ );
475
+ // Invalid attempt - increment IP rate limit
476
+ await incrementIPRateLimit();
477
+ throw new NAuthException(AuthErrorCode.VERIFICATION_CODE_INVALID, 'Invalid or expired verification code');
478
+ }
479
+
480
+ const isExpired =
481
+ typeof verificationToken.isExpired === 'function'
482
+ ? !!verificationToken.isExpired()
483
+ : verificationToken.expiresAt.getTime() <= Date.now();
484
+ if (isExpired) {
485
+ // Expired token - increment IP rate limit
486
+ await incrementIPRateLimit();
487
+ throw new NAuthException(AuthErrorCode.VERIFICATION_CODE_EXPIRED, 'Verification code has expired');
488
+ }
489
+
490
+ const maxAttempts = this.config.signup?.phoneVerification?.maxAttempts ?? 3;
491
+ const tooManyAttempts =
492
+ typeof verificationToken.maxAttemptsExceeded === 'function'
493
+ ? !!verificationToken.maxAttemptsExceeded(maxAttempts)
494
+ : verificationToken.attempts >= maxAttempts;
495
+ if (tooManyAttempts) {
496
+ // Token exceeded max attempts - increment IP rate limit
497
+ await incrementIPRateLimit();
498
+ throw new NAuthException(
499
+ AuthErrorCode.VERIFICATION_TOO_MANY_ATTEMPTS,
500
+ 'Too many failed attempts. Request a new code.',
501
+ {
502
+ maxAttempts,
503
+ currentAttempts: verificationToken.attempts,
504
+ },
505
+ );
506
+ }
507
+
508
+ // ============================================================================
509
+ // Security: Rate limit verification attempts per user (for invalid attempts only)
510
+ // This prevents users from exhausting their own tokens through repeated attempts
511
+ // Valid codes should not be blocked by user rate limits
512
+ // ============================================================================
513
+ const maxAttemptsPerUser = this.config.signup?.phoneVerification?.maxAttemptsPerUser ?? 10;
514
+
515
+ // Helper to increment user rate limit (only for invalid attempts)
516
+ const incrementUserRateLimit = async (): Promise<void> => {
517
+ const userRateLimitKey = `verify-attempts:user:${user.id}`;
518
+ const userAttempts = await this.storageAdapter.incr(userRateLimitKey);
519
+
520
+ if (userAttempts === 1) {
521
+ await this.storageAdapter.expire(userRateLimitKey, attemptWindow);
522
+ }
523
+
524
+ if (userAttempts > maxAttemptsPerUser) {
525
+ throw new NAuthException(
526
+ AuthErrorCode.VERIFICATION_TOO_MANY_ATTEMPTS,
527
+ 'Too many verification attempts. Please try again later.',
528
+ );
529
+ }
530
+ };
531
+
532
+ verificationToken.attempts += 1;
533
+ // Compare normalized codes (trim whitespace for comparison)
534
+ const storedCode = String(verificationToken.code).trim();
535
+ const providedCode = String(code).trim();
536
+ if (storedCode !== providedCode) {
537
+ // Invalid code - increment both IP and user rate limits
538
+ await incrementIPRateLimit();
539
+ await incrementUserRateLimit();
540
+
541
+ await this.verificationTokenRepo.save(verificationToken);
542
+ this.logger?.debug?.(
543
+ `Phone verification failed: sub=${sub}, attempts=${verificationToken.attempts}/${maxAttempts}`,
544
+ );
545
+
546
+ // ============================================================================
547
+ // Audit: Record phone verification failure (by sub)
548
+ // ============================================================================
549
+ try {
550
+ await this.auditService?.recordEvent({
551
+ userId: user.id,
552
+ eventType: AuthAuditEventType.PHONE_VERIFICATION_FAILED,
553
+ eventStatus: 'FAILURE',
554
+ reason: 'invalid_code',
555
+ // Client info automatically included from context
556
+ description: 'Invalid verification code provided',
557
+ metadata: {
558
+ verificationTokenId: verificationToken.id,
559
+ attempts: verificationToken.attempts,
560
+ phone: this.maskPhone(user.phone || ''),
561
+ },
562
+ });
563
+ } catch (auditError) {
564
+ // Non-blocking: Log but continue
565
+ const errorMessage = auditError instanceof Error ? auditError.message : 'Unknown error';
566
+ this.logger?.error?.(`Failed to record PHONE_VERIFICATION_FAILED audit event (by sub): ${errorMessage}`, {
567
+ error: auditError,
568
+ userId: user.id,
569
+ });
570
+ }
571
+
572
+ throw new NAuthException(AuthErrorCode.VERIFICATION_CODE_INVALID, 'Invalid verification code', {
573
+ attemptsRemaining: Math.max(0, maxAttempts - verificationToken.attempts),
574
+ });
575
+ }
576
+
577
+ // ============================================================================
578
+ // Code is valid - proceed without rate limit checks
579
+ // Valid codes should always be allowed through
580
+ // ============================================================================
581
+
582
+ verificationToken.usedAt = new Date();
583
+ await this.verificationTokenRepo.save(verificationToken);
584
+
585
+ // ============================================================================
586
+ // Only update user if phone is not already verified to avoid unnecessary DB write
587
+ // This prevents updating updatedAt timestamp when phone is already verified
588
+ // We use the verification status from when user was loaded at the start
589
+ // ============================================================================
590
+ if (!wasPhoneVerified) {
591
+ // Use update() with explicit WHERE clause to ensure the change is persisted
592
+ // This bypasses entity tracking issues and ensures the update is committed
593
+ await this.userRepo.update(
594
+ { sub },
595
+ {
596
+ isPhoneVerified: true,
597
+ isActive: true,
598
+ },
599
+ );
600
+ this.logger?.log?.(`Phone verification successful: sub=${sub}, userId=${user.id} - phone marked as verified`);
601
+ } else {
602
+ // Phone already verified - just mark token as used, no user update needed
603
+ this.logger?.log?.(`Phone verification code validated: sub=${sub}, userId=${user.id} - phone already verified`);
604
+ }
605
+
606
+ // ============================================================================
607
+ // Audit: Record phone verification success (by sub)
608
+ // ============================================================================
609
+ try {
610
+ // Client info (ipAddress, userAgent) automatically extracted from ClientInfoService
611
+ // Note: ClientInfoService is used transparently by AuditService
612
+ await this.auditService?.recordEvent({
613
+ userId: user.id,
614
+ eventType: AuthAuditEventType.PHONE_VERIFIED,
615
+ eventStatus: 'SUCCESS',
616
+ metadata: {
617
+ // Client info automatically included from context
618
+ verificationTokenId: verificationToken.id,
619
+ verificationMethod: 'code',
620
+ phone: this.maskPhone(user.phone || ''),
621
+ },
622
+ });
623
+ } catch (auditError) {
624
+ // Non-blocking: Log but continue
625
+ const errorMessage = auditError instanceof Error ? auditError.message : 'Unknown error';
626
+ this.logger?.error?.(`Failed to record PHONE_VERIFIED audit event (by sub): ${errorMessage}`, {
627
+ error: auditError,
628
+ userId: user.id,
629
+ });
630
+ }
631
+
632
+ return { message: 'Phone verified successfully. Please log in to continue.' };
633
+ }
634
+
635
+ /**
636
+ * Resend verification SMS
637
+ * Supports both sub and phone-based resend
638
+ *
639
+ * @param dto - Request DTO containing sub or phone
640
+ * @returns Response DTO with verification token ID
641
+ */
642
+ async resendVerificationSMS(dto: ResendVerificationSMSDTO): Promise<ResendVerificationSMSResponseDTO> {
643
+ // Validate that either sub or phone is provided
644
+ if (!dto.sub && !dto.phone) {
645
+ throw new NAuthException(AuthErrorCode.VALIDATION_FAILED, 'Either sub or phone must be provided');
646
+ }
647
+
648
+ if (dto.sub) {
649
+ return this.resendVerificationSMSBySub(dto.sub);
650
+ }
651
+
652
+ return this.resendVerificationSMSForPhone(dto.phone!);
653
+ }
654
+
655
+ /**
656
+ * Resend verification SMS by user sub (private helper)
657
+ *
658
+ * @param sub - External user identifier
659
+ * @returns New verification token id
660
+ */
661
+ private async resendVerificationSMSBySub(sub: string): Promise<ResendVerificationSMSResponseDTO> {
662
+ const user = (await this.userRepo.findOne({ where: { sub } })) as IUser | null;
663
+ if (!user) {
664
+ throw new NAuthException(AuthErrorCode.NOT_FOUND, 'User not found');
665
+ }
666
+
667
+ const resendDelay = this.config.signup?.phoneVerification?.resendDelay ?? 60;
668
+ const lastToken = (await this.verificationTokenRepo.findOne({
669
+ where: { userId: user.id, type: 'phone' },
670
+ order: { createdAt: 'DESC' },
671
+ })) as IVerificationToken | null;
672
+ if (lastToken) {
673
+ const secondsSinceLastSend = (Date.now() - lastToken.createdAt.getTime()) / 1000;
674
+ if (secondsSinceLastSend < resendDelay) {
675
+ const waitSeconds = Math.ceil(resendDelay - secondsSinceLastSend);
676
+ this.logger?.debug?.(`Resend rate limit: sub=${sub}, wait=${waitSeconds}s, delay=${resendDelay}s`);
677
+ throw new NAuthException(
678
+ AuthErrorCode.RATE_LIMIT_RESEND,
679
+ `Please wait ${waitSeconds} seconds before requesting another code`,
680
+ {
681
+ retryAfter: waitSeconds,
682
+ resendDelay,
683
+ },
684
+ );
685
+ }
686
+ }
687
+
688
+ this.logger?.debug?.(`Resending SMS verification code: sub=${sub}`);
689
+ // Preserve challengeSessionId from the last token to ensure verification succeeds
690
+ const sendDto = Object.assign(new SendVerificationSMSDTO(), {
691
+ sub,
692
+ challengeSessionId: lastToken?.challengeSessionId ?? undefined,
693
+ });
694
+ const result = await this.sendVerificationSMS(sendDto);
695
+ return { tokenId: result.tokenId };
696
+ }
697
+
698
+ /**
699
+ * Resend verification SMS by phone number (private helper)
700
+ *
701
+ * @param phone - Phone number
702
+ * @returns New verification token id
703
+ */
704
+ private async resendVerificationSMSForPhone(phone: string): Promise<ResendVerificationSMSResponseDTO> {
705
+ const user = (await this.userRepo.findOne({ where: { phone } })) as IUser | null;
706
+ if (!user) {
707
+ throw new NAuthException(AuthErrorCode.NOT_FOUND, 'User not found');
708
+ }
709
+ if (user.isPhoneVerified) {
710
+ throw new NAuthException(AuthErrorCode.ALREADY_VERIFIED, 'Phone number is already verified');
711
+ }
712
+ return this.resendVerificationSMSBySub(user.sub);
713
+ }
714
+
715
+ // ============================================================================
716
+ // Helpers
717
+ // ============================================================================
718
+
719
+ /**
720
+ * Generate N-digit OTP code (default 6)
721
+ */
722
+ private generateCode(): string {
723
+ const codeLength = this.config.signup?.phoneVerification?.codeLength || 6;
724
+ const min = Math.pow(10, codeLength - 1);
725
+ const max = Math.pow(10, codeLength) - 1;
726
+ return Math.floor(min + Math.random() * (max - min + 1)).toString();
727
+ }
728
+
729
+ /**
730
+ * Generate secure random token
731
+ */
732
+ private generateToken(): string {
733
+ return crypto.randomBytes(32).toString('hex');
734
+ }
735
+
736
+ /**
737
+ * Hash token with SHA-256
738
+ */
739
+ private hashToken(token: string): string {
740
+ return crypto.createHash('sha256').update(token).digest('hex');
741
+ }
742
+
743
+ /**
744
+ * Mask phone number for logging (preserves last 4 digits)
745
+ * @private
746
+ */
747
+ private maskPhone(phone: string): string {
748
+ if (!phone || phone.length < 4) return '***';
749
+ return `***${phone.slice(-4)}`;
750
+ }
751
+ }