@ackplus/nest-auth 0.1.51 → 1.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 (505) hide show
  1. package/README.md +6 -513
  2. package/eslint.config.mjs +59 -0
  3. package/jest.config.ts +10 -0
  4. package/package.json +14 -44
  5. package/project.json +86 -0
  6. package/src/index.ts +30 -0
  7. package/src/lib/admin-console/admin-console.module.ts +62 -0
  8. package/src/lib/admin-console/controllers/admin-auth.controller.ts +339 -0
  9. package/src/lib/admin-console/controllers/admin-console.controller.ts +82 -0
  10. package/src/lib/admin-console/controllers/admin-permissions.controller.ts +180 -0
  11. package/src/lib/admin-console/controllers/admin-roles.controller.ts +89 -0
  12. package/src/lib/admin-console/controllers/admin-tenants.controller.ts +68 -0
  13. package/src/lib/admin-console/controllers/admin-users.controller.ts +379 -0
  14. package/src/lib/admin-console/decorators/current-admin.decorator.ts +9 -0
  15. package/src/lib/admin-console/dto/admin-permission.dto.ts +106 -0
  16. package/src/lib/admin-console/dto/admin-role.dto.ts +45 -0
  17. package/src/lib/admin-console/dto/admin-tenant.dto.ts +43 -0
  18. package/src/lib/admin-console/dto/admin-user.dto.ts +87 -0
  19. package/src/lib/admin-console/dto/create-dashboard-admin.dto.ts +34 -0
  20. package/src/lib/admin-console/dto/login.dto.ts +10 -0
  21. package/src/lib/admin-console/dto/reset-password.dto.ts +21 -0
  22. package/src/lib/admin-console/dto/setup-admin.dto.ts +23 -0
  23. package/src/lib/admin-console/dto/signup.dto.ts +51 -0
  24. package/src/lib/admin-console/entities/admin-user.entity.ts +74 -0
  25. package/src/lib/admin-console/guards/admin-session.guard.ts +47 -0
  26. package/src/lib/admin-console/services/admin-auth.service.ts +82 -0
  27. package/src/lib/admin-console/services/admin-console-config.service.ts +62 -0
  28. package/src/lib/admin-console/services/admin-session.service.ts +106 -0
  29. package/src/lib/admin-console/services/admin-user.service.ts +96 -0
  30. package/src/lib/admin-console/static/index.html +771 -0
  31. package/src/lib/auth/auth.module.ts +58 -0
  32. package/src/lib/auth/controllers/auth.controller.ts +393 -0
  33. package/src/lib/auth/controllers/mfa.controller.ts +200 -0
  34. package/src/lib/auth/dto/credentials/email-credentials.dto.ts +24 -0
  35. package/src/lib/auth/dto/credentials/phone-credentials.dto.ts +24 -0
  36. package/src/lib/auth/dto/credentials/social-credentials.dto.ts +15 -0
  37. package/src/lib/auth/dto/index.ts +1 -0
  38. package/src/lib/auth/dto/requests/change-password.request.dto.ts +34 -0
  39. package/src/lib/auth/dto/requests/forgot-password.request.dto.ts +30 -0
  40. package/src/lib/auth/dto/requests/initialize-admin.request.dto.ts +51 -0
  41. package/src/lib/auth/dto/requests/login.request.dto.ts +65 -0
  42. package/src/lib/auth/dto/requests/refresh-token.request.dto.ts +12 -0
  43. package/src/lib/auth/dto/requests/reset-password-with-token.request.dto.ts +22 -0
  44. package/src/lib/auth/dto/requests/reset-password.request.dto.ts +50 -0
  45. package/src/lib/auth/dto/requests/send-email-verification.request.dto.ts +12 -0
  46. package/src/lib/auth/dto/requests/send-mfa-code.request.dto.ts +19 -0
  47. package/src/lib/auth/dto/requests/signup.request.dto.ts +42 -0
  48. package/src/lib/auth/dto/requests/toggle-mfa.request.dto.ts +12 -0
  49. package/src/lib/auth/dto/requests/verify-2fa.request.dto.ts +24 -0
  50. package/src/lib/auth/dto/requests/verify-email.request.dto.ts +22 -0
  51. package/src/lib/auth/dto/requests/verify-forgot-password-otp-request-dto.ts +41 -0
  52. package/src/lib/auth/dto/requests/verify-totp-setup.request.dto.ts +22 -0
  53. package/src/lib/auth/dto/responses/auth-cookie.response.dto.ts +58 -0
  54. package/src/lib/auth/dto/responses/auth-success.response.dto.ts +58 -0
  55. package/src/lib/auth/dto/responses/auth.response.dto.ts +99 -0
  56. package/src/lib/auth/dto/responses/client-config.response.dto.ts +153 -0
  57. package/src/lib/auth/dto/responses/initialize-admin.response.dto.ts +22 -0
  58. package/src/lib/auth/dto/responses/mfa-code-response.dto.ts +27 -0
  59. package/src/lib/auth/dto/responses/mfa-status.response.dto.ts +89 -0
  60. package/src/lib/auth/dto/responses/verify-otp.response.dto.ts +9 -0
  61. package/src/lib/auth/entities/mfa-secret.entity.ts +33 -0
  62. package/src/lib/auth/entities/otp.entity.ts +33 -0
  63. package/src/lib/auth/events/{logged-out-all.event.d.ts → logged-out-all.event.ts} +6 -3
  64. package/src/lib/auth/events/{logged-out.event.d.ts → logged-out.event.ts} +5 -3
  65. package/src/lib/auth/events/{password-reset-requested.event.d.ts → password-reset-requested.event.ts} +6 -3
  66. package/src/lib/auth/events/{password-reset.event.d.ts → password-reset.event.ts} +6 -3
  67. package/src/lib/auth/events/{user-2fa-verified.event.d.ts → user-2fa-verified.event.ts} +6 -3
  68. package/src/lib/auth/events/{user-logged-in.event.d.ts → user-logged-in.event.ts} +7 -3
  69. package/src/lib/auth/events/{user-refresh-token.event.d.ts → user-refresh-token.event.ts} +6 -3
  70. package/src/lib/auth/events/{user-registered.event.d.ts → user-registered.event.ts} +7 -3
  71. package/src/lib/auth/guards/auth.guard.ts +386 -0
  72. package/src/lib/auth/{index.d.ts → index.ts} +28 -1
  73. package/src/lib/auth/interceptors/refresh-token.interceptor.ts +117 -0
  74. package/src/lib/auth/services/auth.service.ts +947 -0
  75. package/src/lib/auth/services/client-config.service.ts +157 -0
  76. package/src/lib/auth/services/cookie.service.ts +43 -0
  77. package/src/lib/auth/services/mfa.service.ts +391 -0
  78. package/src/lib/auth.constants.ts +63 -0
  79. package/src/lib/core/core.module.ts +50 -0
  80. package/src/lib/core/decorators/auth.decorator.ts +38 -0
  81. package/src/lib/core/decorators/permissions.decorator.ts +17 -0
  82. package/src/lib/core/decorators/public.decorator.ts +33 -0
  83. package/src/lib/core/decorators/role.decorator.ts +12 -0
  84. package/src/lib/core/decorators/skip-mfa.decorator.ts +4 -0
  85. package/src/lib/core/dto/message.response.dto.ts +6 -0
  86. package/src/lib/core/{entities.d.ts → entities.ts} +18 -1
  87. package/src/lib/core/{index.d.ts → index.ts} +17 -0
  88. package/src/lib/core/interfaces/auth-module-options.interface.ts +211 -0
  89. package/src/lib/core/interfaces/mfa-options.interface.ts +46 -0
  90. package/src/lib/core/interfaces/otp.interface.ts +6 -0
  91. package/src/lib/core/interfaces/session-options.interface.ts +19 -0
  92. package/src/lib/core/interfaces/{token-payload.interface.d.ts → token-payload.interface.ts} +4 -1
  93. package/src/lib/core/providers/apple-auth.provider.ts +61 -0
  94. package/src/lib/core/providers/base-auth.provider.ts +74 -0
  95. package/src/lib/core/providers/email-auth.provider.ts +71 -0
  96. package/src/lib/core/providers/facebook-auth.provider.ts +55 -0
  97. package/src/lib/core/providers/github-auth.provider.ts +79 -0
  98. package/src/lib/core/providers/google-auth.provider.ts +61 -0
  99. package/src/lib/core/providers/jwt-auth.provider.ts +50 -0
  100. package/src/lib/core/providers/phone-auth.provider.ts +45 -0
  101. package/src/lib/core/services/auth-config.service.ts +184 -0
  102. package/src/lib/core/services/auth-provider-registry.service.ts +93 -0
  103. package/src/lib/core/services/{debug-logger.service.js → debug-logger.service.ts} +92 -59
  104. package/src/lib/core/services/initialization.service.ts +29 -0
  105. package/src/lib/core/services/jwt.service.ts +137 -0
  106. package/src/lib/nest-auth.module.ts +152 -0
  107. package/src/lib/permission/entities/permission.entity.ts +56 -0
  108. package/src/lib/permission/index.ts +4 -0
  109. package/src/lib/permission/permission.module.ts +14 -0
  110. package/src/lib/permission/services/permission.service.ts +233 -0
  111. package/src/lib/request-context/index.ts +2 -0
  112. package/src/lib/request-context/request-context.middleware.ts +13 -0
  113. package/src/lib/request-context/{request-context.js → request-context.ts} +51 -27
  114. package/src/lib/role/entities/role.entity.ts +103 -0
  115. package/src/lib/role/{index.d.ts → index.ts} +2 -0
  116. package/src/lib/role/role.module.ts +15 -0
  117. package/src/lib/role/services/{role.service.js → role.service.ts} +117 -52
  118. package/src/lib/session/entities/session.entity.ts +54 -0
  119. package/src/lib/session/index.ts +20 -0
  120. package/src/lib/session/interfaces/session-repository.interface.ts +58 -0
  121. package/src/lib/session/repositories/base-session.repository.ts +74 -0
  122. package/src/lib/session/repositories/memory-session.repository.ts +153 -0
  123. package/src/lib/session/repositories/redis-session.repository.ts +171 -0
  124. package/src/lib/session/repositories/typeorm-session.repository.ts +86 -0
  125. package/src/lib/session/services/session-manager.service.ts +261 -0
  126. package/src/lib/session/session.module.ts +102 -0
  127. package/src/lib/session/utils/session.util.ts +166 -0
  128. package/src/lib/tenant/entities/tenant.entity.ts +40 -0
  129. package/src/lib/tenant/events/tenant-created.event.ts +9 -0
  130. package/src/lib/tenant/events/tenant-deleted.event.ts +11 -0
  131. package/src/lib/tenant/events/{tenant-updated.event.d.ts → tenant-updated.event.ts} +6 -3
  132. package/src/lib/tenant/index.ts +9 -0
  133. package/src/lib/tenant/services/tenant.service.ts +336 -0
  134. package/src/lib/tenant/tenant.module.ts +19 -0
  135. package/src/lib/types/express.d.ts +14 -0
  136. package/src/lib/user/dto/requests/update-user.dto.ts +15 -0
  137. package/src/lib/user/entities/access-key.entity.ts +53 -0
  138. package/src/lib/user/entities/identity.entity.ts +31 -0
  139. package/src/lib/user/entities/user.entity.ts +212 -0
  140. package/src/lib/user/events/{user-created.event.d.ts → user-created.event.ts} +4 -3
  141. package/src/lib/user/events/{user-deleted.event.d.ts → user-deleted.event.ts} +6 -3
  142. package/src/lib/user/events/{user-updated.event.d.ts → user-updated.event.ts} +6 -3
  143. package/src/lib/user/index.ts +11 -0
  144. package/src/lib/user/services/access-key.service.ts +145 -0
  145. package/src/lib/user/services/{user.service.js → user.service.ts} +199 -95
  146. package/src/lib/user/user.module.ts +26 -0
  147. package/src/lib/utils/database.utils.ts +6 -0
  148. package/src/lib/utils/date.util.ts +106 -0
  149. package/src/lib/utils/device.util.ts +111 -0
  150. package/src/lib/utils/index.ts +6 -0
  151. package/src/lib/utils/otp.ts +3 -0
  152. package/src/lib/utils/security.util.ts +27 -0
  153. package/src/lib/utils/slug.util.ts +58 -0
  154. package/src/types/ms.d.ts +1 -0
  155. package/test/access-key.service.spec.ts +204 -0
  156. package/test/auth.service.spec.ts +541 -0
  157. package/test/mfa.service.spec.ts +359 -0
  158. package/test/role.service.spec.ts +418 -0
  159. package/test/tenant.service.spec.ts +218 -0
  160. package/test/test.setup.ts +66 -0
  161. package/test/user.service.spec.ts +374 -0
  162. package/tsconfig.json +17 -0
  163. package/tsconfig.lib.json +15 -0
  164. package/tsconfig.spec.json +15 -0
  165. package/tsconfig.tsbuildinfo +1 -1
  166. package/ui/.env +1 -0
  167. package/ui/.env.example +1 -0
  168. package/ui/.eslintignore +7 -0
  169. package/ui/README.md +288 -0
  170. package/ui/index.html +17 -0
  171. package/ui/package.json +34 -0
  172. package/ui/postcss.config.js +6 -0
  173. package/ui/src/App.tsx +245 -0
  174. package/ui/src/components/AuthGuard.tsx +59 -0
  175. package/ui/src/components/AuthProvider.tsx +76 -0
  176. package/ui/src/components/Button.tsx +37 -0
  177. package/ui/src/components/Card.tsx +37 -0
  178. package/ui/src/components/ErrorMessage.tsx +15 -0
  179. package/ui/src/components/FormDialog.tsx +61 -0
  180. package/ui/src/components/FormFooter.tsx +37 -0
  181. package/ui/src/components/Layout.tsx +112 -0
  182. package/ui/src/components/LoadingMessage.tsx +11 -0
  183. package/ui/src/components/Modal.tsx +97 -0
  184. package/ui/src/components/MultiSelect.tsx +145 -0
  185. package/ui/src/components/PageHeader.tsx +42 -0
  186. package/ui/src/components/PanelHeader.tsx +28 -0
  187. package/ui/src/components/PermissionInput.tsx +473 -0
  188. package/ui/src/components/SearchInput.tsx +69 -0
  189. package/ui/src/components/Select.tsx +51 -0
  190. package/ui/src/components/SwaggerUIWrapper.tsx +316 -0
  191. package/ui/src/components/Table.tsx +207 -0
  192. package/ui/src/components/Tag.tsx +9 -0
  193. package/ui/src/components/TagsInput.tsx +96 -0
  194. package/ui/src/components/admin/AdminForm.tsx +170 -0
  195. package/ui/src/components/admin/CreateAdminDialog.tsx +38 -0
  196. package/ui/src/components/auth/LoginFooter.tsx +17 -0
  197. package/ui/src/components/auth/LoginHeader.tsx +14 -0
  198. package/ui/src/components/auth/components/CodeBlock.tsx +43 -0
  199. package/ui/src/components/auth/components/CreateAccountCodeExamples.tsx +60 -0
  200. package/ui/src/components/auth/components/PasswordRequirements.tsx +16 -0
  201. package/ui/src/components/auth/components/PasswordStrengthIndicator.tsx +48 -0
  202. package/ui/src/components/auth/components/ResetPasswordCodeExamples.tsx +76 -0
  203. package/ui/src/components/auth/components/Tabs.tsx +32 -0
  204. package/ui/src/components/auth/dialogs/CreateAccountDialog.tsx +79 -0
  205. package/ui/src/components/auth/dialogs/ForgotPasswordDialog.tsx +79 -0
  206. package/ui/src/components/auth/forms/CreateAccountForm.tsx +226 -0
  207. package/ui/src/components/auth/forms/LoginForm.tsx +149 -0
  208. package/ui/src/components/auth/forms/ResetPasswordForm.tsx +202 -0
  209. package/ui/src/components/auth/types.ts +17 -0
  210. package/ui/src/components/auth/utils/security.ts +82 -0
  211. package/ui/src/components/auth/utils/utils.ts +25 -0
  212. package/ui/src/components/form/EmailField.tsx +25 -0
  213. package/ui/src/components/form/FormField.tsx +102 -0
  214. package/ui/src/components/form/FormMultiSelect.tsx +46 -0
  215. package/ui/src/components/form/FormSelect.tsx +60 -0
  216. package/ui/src/components/form/FormTagsInput.tsx +42 -0
  217. package/ui/src/components/form/FormTextarea.tsx +42 -0
  218. package/ui/src/components/form/PasswordField.tsx +93 -0
  219. package/ui/src/components/form/SecretKeyField.tsx +49 -0
  220. package/ui/src/components/permission/CreatePermissionDialog.tsx +44 -0
  221. package/ui/src/components/permission/EditPermissionDialog.tsx +55 -0
  222. package/ui/src/components/permission/PermissionForm.tsx +251 -0
  223. package/ui/src/components/role/CreateRoleDialog.tsx +45 -0
  224. package/ui/src/components/role/EditRoleDialog.tsx +55 -0
  225. package/ui/src/components/role/RoleDialog.tsx +252 -0
  226. package/ui/src/components/role/RoleForm.tsx +246 -0
  227. package/ui/src/components/tenant/CreateTenantDialog.tsx +41 -0
  228. package/ui/src/components/tenant/EditTenantDialog.tsx +52 -0
  229. package/ui/src/components/tenant/TenantForm.tsx +160 -0
  230. package/ui/src/components/user/CreateUserDialog.tsx +45 -0
  231. package/ui/src/components/user/UserDetailModal.tsx +815 -0
  232. package/ui/src/components/user/UserForm.tsx +191 -0
  233. package/ui/src/data/nest-auth.json +1687 -0
  234. package/ui/src/hooks/useApi.ts +69 -0
  235. package/ui/src/hooks/useAuth.ts +100 -0
  236. package/ui/src/hooks/useConfirm.tsx +105 -0
  237. package/ui/src/hooks/useFormFooter.tsx +42 -0
  238. package/ui/src/hooks/usePagination.ts +69 -0
  239. package/ui/src/index.css +59 -0
  240. package/ui/src/main.tsx +13 -0
  241. package/ui/src/pages/AdminsPage.tsx +178 -0
  242. package/ui/src/pages/ApiPage.tsx +89 -0
  243. package/ui/src/pages/DashboardPage.tsx +281 -0
  244. package/ui/src/pages/LoginPage.tsx +39 -0
  245. package/ui/src/pages/PermissionsPage.tsx +376 -0
  246. package/ui/src/pages/RolesPage.tsx +274 -0
  247. package/ui/src/pages/TenantsPage.tsx +221 -0
  248. package/ui/src/pages/UsersPage.tsx +387 -0
  249. package/ui/src/services/api.ts +115 -0
  250. package/ui/src/types/index.ts +136 -0
  251. package/ui/src/vite-env.d.ts +9 -0
  252. package/ui/tailwind.config.js +45 -0
  253. package/ui/tsconfig.json +24 -0
  254. package/ui/tsconfig.node.json +10 -0
  255. package/ui/vite.config.ts +37 -0
  256. package/ui/yarn.lock +3137 -0
  257. package/src/index.d.ts +0 -11
  258. package/src/index.js +0 -18
  259. package/src/index.js.map +0 -1
  260. package/src/lib/auth/auth.module.d.ts +0 -2
  261. package/src/lib/auth/auth.module.js +0 -54
  262. package/src/lib/auth/auth.module.js.map +0 -1
  263. package/src/lib/auth/controllers/auth.controller.d.ts +0 -29
  264. package/src/lib/auth/controllers/auth.controller.js +0 -206
  265. package/src/lib/auth/controllers/auth.controller.js.map +0 -1
  266. package/src/lib/auth/controllers/mfa.controller.d.ts +0 -23
  267. package/src/lib/auth/controllers/mfa.controller.js +0 -131
  268. package/src/lib/auth/controllers/mfa.controller.js.map +0 -1
  269. package/src/lib/auth/dto/index.d.ts +0 -0
  270. package/src/lib/auth/dto/index.js +0 -1
  271. package/src/lib/auth/dto/index.js.map +0 -1
  272. package/src/lib/auth/dto/requests/forgot-password.request.dto.d.ts +0 -5
  273. package/src/lib/auth/dto/requests/forgot-password.request.dto.js +0 -30
  274. package/src/lib/auth/dto/requests/forgot-password.request.dto.js.map +0 -1
  275. package/src/lib/auth/dto/requests/login.request.dto.d.ts +0 -6
  276. package/src/lib/auth/dto/requests/login.request.dto.js +0 -38
  277. package/src/lib/auth/dto/requests/login.request.dto.js.map +0 -1
  278. package/src/lib/auth/dto/requests/refresh-token.request.dto.d.ts +0 -3
  279. package/src/lib/auth/dto/requests/refresh-token.request.dto.js +0 -15
  280. package/src/lib/auth/dto/requests/refresh-token.request.dto.js.map +0 -1
  281. package/src/lib/auth/dto/requests/reset-password.request.dto.d.ts +0 -7
  282. package/src/lib/auth/dto/requests/reset-password.request.dto.js +0 -42
  283. package/src/lib/auth/dto/requests/reset-password.request.dto.js.map +0 -1
  284. package/src/lib/auth/dto/requests/send-mfa-code.request.dto.d.ts +0 -4
  285. package/src/lib/auth/dto/requests/send-mfa-code.request.dto.js +0 -16
  286. package/src/lib/auth/dto/requests/send-mfa-code.request.dto.js.map +0 -1
  287. package/src/lib/auth/dto/requests/signup.request.dto.d.ts +0 -7
  288. package/src/lib/auth/dto/requests/signup.request.dto.js +0 -37
  289. package/src/lib/auth/dto/requests/signup.request.dto.js.map +0 -1
  290. package/src/lib/auth/dto/requests/social-login.request.dto.d.ts +0 -3
  291. package/src/lib/auth/dto/requests/social-login.request.dto.js +0 -16
  292. package/src/lib/auth/dto/requests/social-login.request.dto.js.map +0 -1
  293. package/src/lib/auth/dto/requests/verify-2fa.request.dto.d.ts +0 -5
  294. package/src/lib/auth/dto/requests/verify-2fa.request.dto.js +0 -21
  295. package/src/lib/auth/dto/requests/verify-2fa.request.dto.js.map +0 -1
  296. package/src/lib/auth/dto/requests/verify-forgot-password-otp-request-dto.d.ts +0 -6
  297. package/src/lib/auth/dto/requests/verify-forgot-password-otp-request-dto.js +0 -35
  298. package/src/lib/auth/dto/requests/verify-forgot-password-otp-request-dto.js.map +0 -1
  299. package/src/lib/auth/dto/requests/verify-totp-setup.request.dto.d.ts +0 -4
  300. package/src/lib/auth/dto/requests/verify-totp-setup.request.dto.js +0 -20
  301. package/src/lib/auth/dto/requests/verify-totp-setup.request.dto.js.map +0 -1
  302. package/src/lib/auth/dto/responses/auth.response.dto.d.ts +0 -16
  303. package/src/lib/auth/dto/responses/auth.response.dto.js +0 -50
  304. package/src/lib/auth/dto/responses/auth.response.dto.js.map +0 -1
  305. package/src/lib/auth/entities/mfa-secret.entity.d.ts +0 -12
  306. package/src/lib/auth/entities/mfa-secret.entity.js +0 -50
  307. package/src/lib/auth/entities/mfa-secret.entity.js.map +0 -1
  308. package/src/lib/auth/entities/otp.entity.d.ts +0 -13
  309. package/src/lib/auth/entities/otp.entity.js +0 -50
  310. package/src/lib/auth/entities/otp.entity.js.map +0 -1
  311. package/src/lib/auth/events/logged-out-all.event.js +0 -10
  312. package/src/lib/auth/events/logged-out-all.event.js.map +0 -1
  313. package/src/lib/auth/events/logged-out.event.js +0 -10
  314. package/src/lib/auth/events/logged-out.event.js.map +0 -1
  315. package/src/lib/auth/events/password-reset-requested.event.js +0 -10
  316. package/src/lib/auth/events/password-reset-requested.event.js.map +0 -1
  317. package/src/lib/auth/events/password-reset.event.js +0 -10
  318. package/src/lib/auth/events/password-reset.event.js.map +0 -1
  319. package/src/lib/auth/events/user-2fa-verified.event.js +0 -10
  320. package/src/lib/auth/events/user-2fa-verified.event.js.map +0 -1
  321. package/src/lib/auth/events/user-logged-in.event.js +0 -10
  322. package/src/lib/auth/events/user-logged-in.event.js.map +0 -1
  323. package/src/lib/auth/events/user-refresh-token.event.js +0 -10
  324. package/src/lib/auth/events/user-refresh-token.event.js.map +0 -1
  325. package/src/lib/auth/events/user-registered.event.js +0 -10
  326. package/src/lib/auth/events/user-registered.event.js.map +0 -1
  327. package/src/lib/auth/guards/auth.guard.d.ts +0 -28
  328. package/src/lib/auth/guards/auth.guard.js +0 -304
  329. package/src/lib/auth/guards/auth.guard.js.map +0 -1
  330. package/src/lib/auth/index.js +0 -31
  331. package/src/lib/auth/index.js.map +0 -1
  332. package/src/lib/auth/services/auth.service.d.ts +0 -53
  333. package/src/lib/auth/services/auth.service.js +0 -522
  334. package/src/lib/auth/services/auth.service.js.map +0 -1
  335. package/src/lib/auth/services/cookie.service.d.ts +0 -9
  336. package/src/lib/auth/services/cookie.service.js +0 -43
  337. package/src/lib/auth/services/cookie.service.js.map +0 -1
  338. package/src/lib/auth/services/mfa.service.d.ts +0 -38
  339. package/src/lib/auth/services/mfa.service.js +0 -254
  340. package/src/lib/auth/services/mfa.service.js.map +0 -1
  341. package/src/lib/auth.constants.d.ts +0 -39
  342. package/src/lib/auth.constants.js +0 -43
  343. package/src/lib/auth.constants.js.map +0 -1
  344. package/src/lib/core/core.module.d.ts +0 -2
  345. package/src/lib/core/core.module.js +0 -53
  346. package/src/lib/core/core.module.js.map +0 -1
  347. package/src/lib/core/decorators/auth.decorator.d.ts +0 -1
  348. package/src/lib/core/decorators/auth.decorator.js +0 -8
  349. package/src/lib/core/decorators/auth.decorator.js.map +0 -1
  350. package/src/lib/core/decorators/permissions.decorator.d.ts +0 -2
  351. package/src/lib/core/decorators/permissions.decorator.js +0 -14
  352. package/src/lib/core/decorators/permissions.decorator.js.map +0 -1
  353. package/src/lib/core/decorators/role.decorator.d.ts +0 -3
  354. package/src/lib/core/decorators/role.decorator.js +0 -14
  355. package/src/lib/core/decorators/role.decorator.js.map +0 -1
  356. package/src/lib/core/decorators/skip-mfa.decorator.d.ts +0 -2
  357. package/src/lib/core/decorators/skip-mfa.decorator.js +0 -8
  358. package/src/lib/core/decorators/skip-mfa.decorator.js.map +0 -1
  359. package/src/lib/core/dto/message.response.dto.d.ts +0 -3
  360. package/src/lib/core/dto/message.response.dto.js +0 -13
  361. package/src/lib/core/dto/message.response.dto.js.map +0 -1
  362. package/src/lib/core/entities.js +0 -31
  363. package/src/lib/core/entities.js.map +0 -1
  364. package/src/lib/core/index.js +0 -27
  365. package/src/lib/core/index.js.map +0 -1
  366. package/src/lib/core/interfaces/auth-module-options.interface.d.ts +0 -62
  367. package/src/lib/core/interfaces/auth-module-options.interface.js +0 -3
  368. package/src/lib/core/interfaces/auth-module-options.interface.js.map +0 -1
  369. package/src/lib/core/interfaces/mfa-options.interface.d.ts +0 -25
  370. package/src/lib/core/interfaces/mfa-options.interface.js +0 -10
  371. package/src/lib/core/interfaces/mfa-options.interface.js.map +0 -1
  372. package/src/lib/core/interfaces/otp.interface.d.ts +0 -5
  373. package/src/lib/core/interfaces/otp.interface.js +0 -10
  374. package/src/lib/core/interfaces/otp.interface.js.map +0 -1
  375. package/src/lib/core/interfaces/session-options.interface.d.ts +0 -12
  376. package/src/lib/core/interfaces/session-options.interface.js +0 -9
  377. package/src/lib/core/interfaces/session-options.interface.js.map +0 -1
  378. package/src/lib/core/interfaces/token-payload.interface.js +0 -3
  379. package/src/lib/core/interfaces/token-payload.interface.js.map +0 -1
  380. package/src/lib/core/providers/apple-auth.provider.d.ts +0 -18
  381. package/src/lib/core/providers/apple-auth.provider.js +0 -57
  382. package/src/lib/core/providers/apple-auth.provider.js.map +0 -1
  383. package/src/lib/core/providers/base-auth.provider.d.ts +0 -26
  384. package/src/lib/core/providers/base-auth.provider.js +0 -43
  385. package/src/lib/core/providers/base-auth.provider.js.map +0 -1
  386. package/src/lib/core/providers/email-auth.provider.d.ts +0 -17
  387. package/src/lib/core/providers/email-auth.provider.js +0 -40
  388. package/src/lib/core/providers/email-auth.provider.js.map +0 -1
  389. package/src/lib/core/providers/facebook-auth.provider.d.ts +0 -18
  390. package/src/lib/core/providers/facebook-auth.provider.js +0 -56
  391. package/src/lib/core/providers/facebook-auth.provider.js.map +0 -1
  392. package/src/lib/core/providers/google-auth.provider.d.ts +0 -21
  393. package/src/lib/core/providers/google-auth.provider.js +0 -58
  394. package/src/lib/core/providers/google-auth.provider.js.map +0 -1
  395. package/src/lib/core/providers/jwt-auth.provider.d.ts +0 -33
  396. package/src/lib/core/providers/jwt-auth.provider.js +0 -50
  397. package/src/lib/core/providers/jwt-auth.provider.js.map +0 -1
  398. package/src/lib/core/providers/phone-auth.provider.d.ts +0 -18
  399. package/src/lib/core/providers/phone-auth.provider.js +0 -43
  400. package/src/lib/core/providers/phone-auth.provider.js.map +0 -1
  401. package/src/lib/core/services/auth-config.service.d.ts +0 -12
  402. package/src/lib/core/services/auth-config.service.js +0 -79
  403. package/src/lib/core/services/auth-config.service.js.map +0 -1
  404. package/src/lib/core/services/auth-provider-registry.service.d.ts +0 -24
  405. package/src/lib/core/services/auth-provider-registry.service.js +0 -71
  406. package/src/lib/core/services/auth-provider-registry.service.js.map +0 -1
  407. package/src/lib/core/services/debug-logger.service.d.ts +0 -38
  408. package/src/lib/core/services/debug-logger.service.js.map +0 -1
  409. package/src/lib/core/services/initialization.service.d.ts +0 -10
  410. package/src/lib/core/services/initialization.service.js +0 -34
  411. package/src/lib/core/services/initialization.service.js.map +0 -1
  412. package/src/lib/core/services/jwt.service.d.ts +0 -14
  413. package/src/lib/core/services/jwt.service.js +0 -92
  414. package/src/lib/core/services/jwt.service.js.map +0 -1
  415. package/src/lib/nest-auth.module.d.ts +0 -11
  416. package/src/lib/nest-auth.module.js +0 -177
  417. package/src/lib/nest-auth.module.js.map +0 -1
  418. package/src/lib/request-context/request-context.d.ts +0 -22
  419. package/src/lib/request-context/request-context.js.map +0 -1
  420. package/src/lib/request-context/request-context.middleware.d.ts +0 -4
  421. package/src/lib/request-context/request-context.middleware.js +0 -16
  422. package/src/lib/request-context/request-context.middleware.js.map +0 -1
  423. package/src/lib/role/entities/role.entity.d.ts +0 -20
  424. package/src/lib/role/entities/role.entity.js +0 -110
  425. package/src/lib/role/entities/role.entity.js.map +0 -1
  426. package/src/lib/role/index.js +0 -5
  427. package/src/lib/role/index.js.map +0 -1
  428. package/src/lib/role/role.module.d.ts +0 -2
  429. package/src/lib/role/role.module.js +0 -23
  430. package/src/lib/role/role.module.js.map +0 -1
  431. package/src/lib/role/services/role.service.d.ts +0 -20
  432. package/src/lib/role/services/role.service.js.map +0 -1
  433. package/src/lib/session/entities/session.entity.d.ts +0 -16
  434. package/src/lib/session/entities/session.entity.js +0 -63
  435. package/src/lib/session/entities/session.entity.js.map +0 -1
  436. package/src/lib/session/index.d.ts +0 -3
  437. package/src/lib/session/index.js +0 -7
  438. package/src/lib/session/index.js.map +0 -1
  439. package/src/lib/session/services/base-session.service.d.ts +0 -23
  440. package/src/lib/session/services/base-session.service.js +0 -64
  441. package/src/lib/session/services/base-session.service.js.map +0 -1
  442. package/src/lib/session/services/database-session.service.d.ts +0 -17
  443. package/src/lib/session/services/database-session.service.js +0 -51
  444. package/src/lib/session/services/database-session.service.js.map +0 -1
  445. package/src/lib/session/services/redis-session.service.d.ts +0 -20
  446. package/src/lib/session/services/redis-session.service.js +0 -117
  447. package/src/lib/session/services/redis-session.service.js.map +0 -1
  448. package/src/lib/session/session.module.d.ts +0 -2
  449. package/src/lib/session/session.module.js +0 -33
  450. package/src/lib/session/session.module.js.map +0 -1
  451. package/src/lib/tenant/entities/tenant.entity.d.ts +0 -10
  452. package/src/lib/tenant/entities/tenant.entity.js +0 -44
  453. package/src/lib/tenant/entities/tenant.entity.js.map +0 -1
  454. package/src/lib/tenant/events/tenant-created.event.d.ts +0 -8
  455. package/src/lib/tenant/events/tenant-created.event.js +0 -10
  456. package/src/lib/tenant/events/tenant-created.event.js.map +0 -1
  457. package/src/lib/tenant/events/tenant-deleted.event.d.ts +0 -8
  458. package/src/lib/tenant/events/tenant-deleted.event.js +0 -10
  459. package/src/lib/tenant/events/tenant-deleted.event.js.map +0 -1
  460. package/src/lib/tenant/events/tenant-updated.event.js +0 -10
  461. package/src/lib/tenant/events/tenant-updated.event.js.map +0 -1
  462. package/src/lib/tenant/index.d.ts +0 -1
  463. package/src/lib/tenant/index.js +0 -5
  464. package/src/lib/tenant/index.js.map +0 -1
  465. package/src/lib/tenant/services/tenant.service.d.ts +0 -26
  466. package/src/lib/tenant/services/tenant.service.js +0 -200
  467. package/src/lib/tenant/services/tenant.service.js.map +0 -1
  468. package/src/lib/tenant/tenant.module.d.ts +0 -2
  469. package/src/lib/tenant/tenant.module.js +0 -27
  470. package/src/lib/tenant/tenant.module.js.map +0 -1
  471. package/src/lib/user/dto/requests/update-user.dto.d.ts +0 -5
  472. package/src/lib/user/dto/requests/update-user.dto.js +0 -24
  473. package/src/lib/user/dto/requests/update-user.dto.js.map +0 -1
  474. package/src/lib/user/entities/access-key.entity.d.ts +0 -16
  475. package/src/lib/user/entities/access-key.entity.js +0 -63
  476. package/src/lib/user/entities/access-key.entity.js.map +0 -1
  477. package/src/lib/user/entities/identity.entity.d.ts +0 -12
  478. package/src/lib/user/entities/identity.entity.js +0 -47
  479. package/src/lib/user/entities/identity.entity.js.map +0 -1
  480. package/src/lib/user/entities/user.entity.d.ts +0 -39
  481. package/src/lib/user/entities/user.entity.js +0 -201
  482. package/src/lib/user/entities/user.entity.js.map +0 -1
  483. package/src/lib/user/events/user-created.event.js +0 -10
  484. package/src/lib/user/events/user-created.event.js.map +0 -1
  485. package/src/lib/user/events/user-deleted.event.js +0 -10
  486. package/src/lib/user/events/user-deleted.event.js.map +0 -1
  487. package/src/lib/user/events/user-updated.event.js +0 -10
  488. package/src/lib/user/events/user-updated.event.js.map +0 -1
  489. package/src/lib/user/index.d.ts +0 -3
  490. package/src/lib/user/index.js +0 -7
  491. package/src/lib/user/index.js.map +0 -1
  492. package/src/lib/user/services/access-key.service.d.ts +0 -19
  493. package/src/lib/user/services/access-key.service.js +0 -119
  494. package/src/lib/user/services/access-key.service.js.map +0 -1
  495. package/src/lib/user/services/user.service.d.ts +0 -24
  496. package/src/lib/user/services/user.service.js.map +0 -1
  497. package/src/lib/user/user.module.d.ts +0 -2
  498. package/src/lib/user/user.module.js +0 -34
  499. package/src/lib/user/user.module.js.map +0 -1
  500. package/src/lib/utils/database.utils.d.ts +0 -2
  501. package/src/lib/utils/database.utils.js +0 -8
  502. package/src/lib/utils/database.utils.js.map +0 -1
  503. package/src/lib/utils/otp.d.ts +0 -1
  504. package/src/lib/utils/otp.js +0 -7
  505. package/src/lib/utils/otp.js.map +0 -1
@@ -0,0 +1,58 @@
1
+ import { Module, forwardRef } from '@nestjs/common';
2
+ import { AuthService } from './services/auth.service';
3
+ import { CookieService } from './services/cookie.service';
4
+ import { MfaService } from './services/mfa.service';
5
+ import { ClientConfigService } from './services/client-config.service';
6
+ import { NestAuthAuthGuard } from './guards/auth.guard';
7
+ import { RefreshTokenInterceptor } from './interceptors/refresh-token.interceptor';
8
+ import { AuthController } from './controllers/auth.controller';
9
+ import { MfaController } from './controllers/mfa.controller';
10
+ import { NestAuthIdentity } from '../user/entities/identity.entity';
11
+ import { TypeOrmModule } from '@nestjs/typeorm';
12
+ import { NestAuthUser } from '../user/entities/user.entity';
13
+ import { NestAuthOTP } from './entities/otp.entity';
14
+ import { NestAuthMFASecret } from './entities/mfa-secret.entity';
15
+ import { NestAuthAccessKey } from '../user/entities/access-key.entity';
16
+ import { EventEmitterModule } from '@nestjs/event-emitter';
17
+ import { UserModule } from '../user/user.module';
18
+ import { CoreModule } from '../core/core.module';
19
+ import { SessionModule } from '../session/session.module';
20
+ import { TenantModule } from '../tenant/tenant.module';
21
+ import { RoleModule } from '../role/role.module';
22
+
23
+ @Module({
24
+ imports: [
25
+ EventEmitterModule,
26
+ TypeOrmModule.forFeature([
27
+ NestAuthUser,
28
+ NestAuthOTP,
29
+ NestAuthMFASecret,
30
+ NestAuthAccessKey,
31
+ NestAuthIdentity,
32
+ ]),
33
+ forwardRef(() => CoreModule),
34
+ forwardRef(() => UserModule),
35
+ forwardRef(() => SessionModule),
36
+ forwardRef(() => TenantModule),
37
+ forwardRef(() => RoleModule),
38
+ ],
39
+ providers: [
40
+ AuthService,
41
+ CookieService,
42
+ MfaService,
43
+ ClientConfigService,
44
+ NestAuthAuthGuard,
45
+ RefreshTokenInterceptor,
46
+ ],
47
+ controllers: [AuthController, MfaController],
48
+ exports: [
49
+ AuthService,
50
+ CookieService,
51
+ MfaService,
52
+ ClientConfigService,
53
+ NestAuthAuthGuard,
54
+ RefreshTokenInterceptor,
55
+ ],
56
+ })
57
+ export class AuthModule {
58
+ }
@@ -0,0 +1,393 @@
1
+ import { Controller, Post, Body, Get, UseGuards, Res, HttpCode, Query, Param } from '@nestjs/common';
2
+ import { AuthService } from '../services/auth.service';
3
+ import { Verify2faRequestDto } from '../dto/requests/verify-2fa.request.dto';
4
+ import { RefreshTokenRequestDto } from '../dto/requests/refresh-token.request.dto';
5
+ import { Response } from 'express';
6
+ import { ApiResponse } from '@nestjs/swagger';
7
+ import { ApiOperation } from '@nestjs/swagger';
8
+ import { CookieService } from '../services/cookie.service';
9
+ import { AuthConfigService } from '../../core/services/auth-config.service';
10
+ import { AuthWithTokensResponseDto, UserResponseDto, Verify2faWithTokensResponseDto } from '../dto/responses/auth.response.dto';
11
+ import { AuthCookieResponseDto } from '../dto/responses/auth-cookie.response.dto';
12
+ import { SignupRequestDto } from '../dto/requests/signup.request.dto';
13
+ import { LoginRequestDto } from '../dto/requests/login.request.dto';
14
+ import { RequestContext } from '../../request-context/request-context';
15
+ import { MessageResponseDto, MFAMethodEnum, SkipMfa } from '../../core';
16
+ import { ForgotPasswordRequestDto } from '../dto/requests/forgot-password.request.dto';
17
+ import { ResetPasswordRequestDto } from '../dto/requests/reset-password.request.dto';
18
+ import { NestAuthAuthGuard } from '../guards/auth.guard';
19
+ import { VerifyForgotPasswordOtpRequestDto } from '../dto/requests/verify-forgot-password-otp-request-dto';
20
+ import { ResetPasswordWithTokenRequestDto } from '../dto/requests/reset-password-with-token.request.dto';
21
+ import { VerifyOtpResponseDto } from '../dto/responses/verify-otp.response.dto';
22
+ import { ChangePasswordRequestDto } from '../dto/requests/change-password.request.dto';
23
+ import { SendEmailVerificationRequestDto } from '../dto/requests/send-email-verification.request.dto';
24
+ import { VerifyEmailRequestDto } from '../dto/requests/verify-email.request.dto';
25
+ import { ClientConfigService } from '../services/client-config.service';
26
+ import { ClientConfigResponseDto } from '../dto/responses/client-config.response.dto';
27
+
28
+
29
+ @Controller('auth')
30
+ export class AuthController {
31
+ constructor(
32
+ private readonly authService: AuthService,
33
+ private readonly cookieService: CookieService,
34
+ private readonly authConfig: AuthConfigService,
35
+ private readonly clientConfigService: ClientConfigService,
36
+ ) { }
37
+
38
+ /**
39
+ * Check if using cookie-based authentication
40
+ */
41
+ protected isUsingCookies(): boolean {
42
+ const config = this.authConfig.getConfig();
43
+ return config.accessTokenType === 'cookie';
44
+ }
45
+
46
+ /**
47
+ * Handle auth response based on configuration
48
+ * - If cookie mode: Sets tokens in cookies, returns success message
49
+ * - If header mode: Returns tokens in response body
50
+ */
51
+ protected handleAuthResponse(
52
+ res: Response,
53
+ authResult: { accessToken: string; refreshToken: string; isRequiresMfa: boolean },
54
+ successMessage: string = 'Authentication successful'
55
+ ): void {
56
+ if (this.isUsingCookies()) {
57
+ // Cookie mode: Set tokens in cookies, return success message
58
+ this.cookieService.setTokens(res, authResult.accessToken, authResult.refreshToken);
59
+ res.status(200).json({
60
+ message: successMessage,
61
+ isRequiresMfa: authResult.isRequiresMfa
62
+ } as AuthCookieResponseDto);
63
+ } else {
64
+ // Header mode: Return tokens in response body
65
+ res.status(200).json({
66
+ message: successMessage,
67
+ accessToken: authResult.accessToken,
68
+ refreshToken: authResult.refreshToken,
69
+ isRequiresMfa: authResult.isRequiresMfa
70
+ } as AuthWithTokensResponseDto);
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Handle 2FA verification response based on configuration
76
+ */
77
+ protected handle2faResponse(
78
+ res: Response,
79
+ authResult: { accessToken: string; refreshToken: string }
80
+ ): void {
81
+ if (this.isUsingCookies()) {
82
+ // Cookie mode: Set tokens in cookies, return success message
83
+ this.cookieService.setTokens(res, authResult.accessToken, authResult.refreshToken);
84
+ res.status(200).json({
85
+ message: '2FA verification successful'
86
+ // Note: No isRequiresMfa for 2FA verification (it's already verified)
87
+ } as AuthCookieResponseDto);
88
+ } else {
89
+ // Header mode: Return message AND tokens in response body
90
+ res.status(200).json({
91
+ message: '2FA verification successful',
92
+ accessToken: authResult.accessToken,
93
+ refreshToken: authResult.refreshToken
94
+ } as Verify2faWithTokensResponseDto);
95
+ }
96
+ }
97
+
98
+ @ApiOperation({
99
+ summary: 'Signup',
100
+ description: 'Register a new user. Response format depends on accessTokenType configuration:\n' +
101
+ '- Header mode (default): Returns tokens in response body\n' +
102
+ '- Cookie mode: Sets tokens in HTTP-only cookies and returns success message'
103
+ })
104
+ @ApiResponse({ status: 200, type: AuthWithTokensResponseDto, description: 'Header mode: Returns message + tokens in body' })
105
+ @ApiResponse({ status: 200, type: AuthCookieResponseDto, description: 'Cookie mode: Returns message only, tokens in cookies' })
106
+ @HttpCode(200)
107
+ @Post('signup')
108
+ async signup(@Body() input: SignupRequestDto, @Res() res: Response) {
109
+ const response = await this.authService.signup(input);
110
+ this.handleAuthResponse(res, response, 'Signup successful');
111
+ }
112
+
113
+ @ApiOperation({
114
+ summary: 'Login',
115
+ description: 'Authenticate user. Response format depends on accessTokenType configuration:\n' +
116
+ '- Header mode (default): Returns tokens in response body\n' +
117
+ '- Cookie mode: Sets tokens in HTTP-only cookies and returns success message'
118
+ })
119
+ @ApiResponse({ status: 200, type: AuthWithTokensResponseDto, description: 'Header mode: Returns message + tokens in body' })
120
+ @ApiResponse({ status: 200, type: AuthCookieResponseDto, description: 'Cookie mode: Returns message only, tokens in cookies' })
121
+ @HttpCode(200)
122
+ @Post('login')
123
+ async login(@Body() input: LoginRequestDto, @Res() res: Response) {
124
+ const response = await this.authService.login(input);
125
+ this.handleAuthResponse(res, response, 'Login successful');
126
+ }
127
+
128
+ @ApiOperation({
129
+ summary: 'Refresh Token',
130
+ description: 'Refresh access token. Response format depends on accessTokenType configuration:\n' +
131
+ '- Header mode (default): Returns new tokens in response body\n' +
132
+ '- Cookie mode: Sets new tokens in HTTP-only cookies and returns success message'
133
+ })
134
+ @ApiResponse({ status: 200, type: AuthWithTokensResponseDto, description: 'Header mode: Returns message + tokens in body' })
135
+ @ApiResponse({ status: 200, type: AuthCookieResponseDto, description: 'Cookie mode: Returns message only, tokens in cookies' })
136
+ @HttpCode(200)
137
+ @Post('refresh-token')
138
+ async refreshToken(@Body() input: RefreshTokenRequestDto, @Res() res: Response) {
139
+ const response = await this.authService.refreshToken(input.refreshToken);
140
+ // Note: Refresh response doesn't have isRequiresMfa, so we create a compatible object
141
+ this.handleAuthResponse(res, { ...response, isRequiresMfa: false }, 'Token refreshed successfully');
142
+ }
143
+
144
+
145
+ @ApiOperation({ summary: 'Send 2FA Code' })
146
+ @ApiResponse({ status: 200, type: MessageResponseDto })
147
+ @HttpCode(200)
148
+ @Post('send-2fa-code')
149
+ @SkipMfa()
150
+ @UseGuards(NestAuthAuthGuard)
151
+ async send2faCode(@Body('method') method: MFAMethodEnum) {
152
+ const user = RequestContext.currentUser();
153
+ await this.authService.send2faCode(user.id, method);
154
+ return { message: '2FA code sent successfully' }
155
+ }
156
+
157
+ @ApiOperation({
158
+ summary: 'Verify 2FA',
159
+ description: 'Verify two-factor authentication. Response format depends on accessTokenType configuration:\n' +
160
+ '- Header mode (default): Returns tokens in response body\n' +
161
+ '- Cookie mode: Sets tokens in HTTP-only cookies and returns success message'
162
+ })
163
+ @ApiResponse({ status: 200, type: Verify2faWithTokensResponseDto, description: 'Header mode: Returns message + tokens in body' })
164
+ @ApiResponse({ status: 200, type: AuthCookieResponseDto, description: 'Cookie mode: Returns message only, tokens in cookies' })
165
+ @HttpCode(200)
166
+ @Post('verify-2fa')
167
+ @SkipMfa()
168
+ @UseGuards(NestAuthAuthGuard)
169
+ async verify2fa(@Body() input: Verify2faRequestDto, @Res() res: Response) {
170
+ const response = await this.authService.verify2fa(input);
171
+ this.handle2faResponse(res, response);
172
+ }
173
+
174
+ @ApiOperation({ summary: 'Logout' })
175
+ @ApiResponse({ status: 200, type: MessageResponseDto })
176
+ @HttpCode(200)
177
+ @Post('logout')
178
+ @SkipMfa()
179
+ @UseGuards(NestAuthAuthGuard)
180
+ async logout(@Res() res: Response) {
181
+ await this.authService.logout();
182
+
183
+ // Only clear cookies if using cookie-based auth
184
+ if (this.isUsingCookies()) {
185
+ this.cookieService.clearCookies(res);
186
+ }
187
+
188
+ res.status(200).json({ message: 'Logged out successfully' });
189
+ }
190
+
191
+ @ApiOperation({ summary: 'Logout All' })
192
+ @ApiResponse({ status: 200, type: MessageResponseDto })
193
+ @HttpCode(200)
194
+ @Post('logout-all')
195
+ @SkipMfa()
196
+ @UseGuards(NestAuthAuthGuard)
197
+ async logoutAll(): Promise<MessageResponseDto> {
198
+ const user = RequestContext.currentUser();
199
+ await this.authService.logoutAll(user.id);
200
+ return { message: 'Logged out from all devices successfully' };
201
+ }
202
+
203
+ @ApiOperation({ summary: 'Change Password' })
204
+ @ApiResponse({ status: 200, type: AuthWithTokensResponseDto })
205
+ @HttpCode(200)
206
+ @Post('change-password')
207
+ @SkipMfa()
208
+ @UseGuards(NestAuthAuthGuard)
209
+ async changePassword(@Body() input: ChangePasswordRequestDto, @Res() res: Response) {
210
+ const response = await this.authService.changePassword(input);
211
+ this.handleAuthResponse(res, response, 'Password updated successfully');
212
+ }
213
+
214
+ @ApiOperation({ summary: 'Forgot Password' })
215
+ @ApiResponse({ status: 200, type: MessageResponseDto })
216
+ @HttpCode(200)
217
+ @Post('forgot-password')
218
+ @SkipMfa()
219
+ async forgotPassword(@Body() input: ForgotPasswordRequestDto): Promise<MessageResponseDto> {
220
+ await this.authService.forgotPassword(input);
221
+ return { message: 'If the account exists, a password reset code has been sent' }
222
+ }
223
+
224
+ @ApiOperation({ summary: 'Verify Forgot Password OTP and get reset token' })
225
+ @ApiResponse({ status: 200, type: VerifyOtpResponseDto })
226
+ @HttpCode(200)
227
+ @Post('verify-forgot-password-otp')
228
+ @SkipMfa()
229
+ async verifyForgotPasswordOtp(@Body() input: VerifyForgotPasswordOtpRequestDto): Promise<VerifyOtpResponseDto> {
230
+ return await this.authService.verifyForgotPasswordOtp(input);
231
+ }
232
+
233
+ @ApiOperation({ summary: 'Reset Password (Legacy - using OTP)' })
234
+ @ApiResponse({ status: 200, type: MessageResponseDto })
235
+ @HttpCode(200)
236
+ @Post('reset-password')
237
+ @SkipMfa()
238
+ async resetPassword(@Body() input: ResetPasswordRequestDto): Promise<MessageResponseDto> {
239
+ await this.authService.resetPassword(input);
240
+ return { message: 'Password reset successfully' }
241
+ }
242
+
243
+ @ApiOperation({ summary: 'Reset Password with Token' })
244
+ @ApiResponse({ status: 200, type: MessageResponseDto })
245
+ @HttpCode(200)
246
+ @Post('reset-password-with-token')
247
+ @SkipMfa()
248
+ async resetPasswordWithToken(@Body() input: ResetPasswordWithTokenRequestDto): Promise<MessageResponseDto> {
249
+ await this.authService.resetPasswordWithToken(input);
250
+ return { message: 'Password reset successfully' }
251
+ }
252
+
253
+ @ApiOperation({ summary: 'Get Logged In User' })
254
+ @ApiResponse({ status: 200, type: UserResponseDto })
255
+ @UseGuards(NestAuthAuthGuard)
256
+ @Get('user')
257
+ async getUser() {
258
+ return await this.authService.getUser();
259
+ }
260
+
261
+ @ApiOperation({ summary: 'Send Email Verification' })
262
+ @ApiResponse({ status: 200, type: MessageResponseDto })
263
+ @HttpCode(200)
264
+ @Post('send-email-verification')
265
+ @SkipMfa()
266
+ @UseGuards(NestAuthAuthGuard)
267
+ async sendEmailVerification(@Body() input: SendEmailVerificationRequestDto): Promise<MessageResponseDto> {
268
+ return await this.authService.sendEmailVerification(input);
269
+ }
270
+
271
+ @ApiOperation({ summary: 'Verify Email' })
272
+ @ApiResponse({ status: 200, type: MessageResponseDto })
273
+ @HttpCode(200)
274
+ @Post('verify-email')
275
+ @SkipMfa()
276
+ @UseGuards(NestAuthAuthGuard)
277
+ async verifyEmail(@Body() input: VerifyEmailRequestDto): Promise<MessageResponseDto> {
278
+ return await this.authService.verifyEmail(input);
279
+ }
280
+
281
+ @ApiOperation({
282
+ summary: 'Get Client Configuration',
283
+ description: 'Returns backend configuration for frontend clients. Includes enabled auth methods, registration settings, MFA options, tenant configuration, and SSO providers. Can be customized via clientConfig.factory in AuthModuleOptions.',
284
+ })
285
+ @ApiResponse({ status: 200, type: ClientConfigResponseDto })
286
+ @HttpCode(200)
287
+ @Get('client-config')
288
+ async getClientConfig(): Promise<ClientConfigResponseDto> {
289
+ return await this.clientConfigService.getClientConfig();
290
+ }
291
+
292
+ @ApiOperation({
293
+ summary: 'SSO Callback',
294
+ description: 'OAuth callback endpoint for SSO providers. Exchanges authorization code for access token and returns raw SSO user info. Returns HTML page that posts SSO data to parent window and auto-closes.',
295
+ })
296
+ @Get('callback/:provider')
297
+ async ssoCallback(
298
+ @Param('provider') provider: string,
299
+ @Query() data: any,
300
+ @Res() res: Response,
301
+ ) {
302
+
303
+ const jsonData = JSON.stringify(data);
304
+ const escapedData = jsonData.replace(/</g, '\\u003c').replace(/>/g, '\\u003e');
305
+
306
+ const html = `<!DOCTYPE html>
307
+ <html lang="en">
308
+ <head>
309
+ <meta charset="UTF-8">
310
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
311
+ <title>SSO Callback</title>
312
+ <style>
313
+ body {
314
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
315
+ display: flex;
316
+ justify-content: center;
317
+ align-items: center;
318
+ min-height: 100vh;
319
+ margin: 0;
320
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
321
+ }
322
+ .container {
323
+ background: white;
324
+ padding: 2rem;
325
+ border-radius: 8px;
326
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
327
+ text-align: center;
328
+ max-width: 400px;
329
+ }
330
+ .spinner {
331
+ border: 3px solid #f3f3f3;
332
+ border-top: 3px solid #667eea;
333
+ border-radius: 50%;
334
+ width: 40px;
335
+ height: 40px;
336
+ animation: spin 1s linear infinite;
337
+ margin: 0 auto 1rem;
338
+ }
339
+ @keyframes spin {
340
+ 0% { transform: rotate(0deg); }
341
+ 100% { transform: rotate(360deg); }
342
+ }
343
+ .message {
344
+ color: #333;
345
+ margin-top: 1rem;
346
+ }
347
+ .error {
348
+ color: #dc3545;
349
+ }
350
+ </style>
351
+ </head>
352
+ <body>
353
+ <div class="container">
354
+ <div class="spinner"></div>
355
+ <div class="message" id="message">Processing...</div>
356
+ </div>
357
+ <script>
358
+ (function() {
359
+ const data = ${escapedData};
360
+
361
+ // Post message to parent window
362
+ if (window.opener) {
363
+ window.opener.postMessage({
364
+ type: 'nest-auth-sso-callback',
365
+ ...data
366
+ }, '*');
367
+
368
+ // Auto-close immediately
369
+ window.close();
370
+ } else if (window.parent && window.parent !== window) {
371
+ // Iframe context
372
+ window.parent.postMessage({
373
+ type: 'nest-auth-sso-callback',
374
+ ...data
375
+ }, '*');
376
+ // Note: Can't close iframe from inside
377
+ } else {
378
+ // No parent window, show message
379
+ document.getElementById('message').textContent = data.success
380
+ ? 'Success! You can close this window.'
381
+ : 'Error: ' + (data.errorDescription || data.error);
382
+ document.getElementById('message').className = data.success ? 'message' : 'message error';
383
+ }
384
+ })();
385
+ </script>
386
+ </body>
387
+ </html>`;
388
+
389
+ res.setHeader('Content-Type', 'text/html');
390
+ res.status(200).send(html);
391
+ }
392
+
393
+ }
@@ -0,0 +1,200 @@
1
+ import { Controller, Post, Body, UnauthorizedException, UseGuards, HttpCode, Get, Delete, Param } from '@nestjs/common';
2
+ import { SkipMfa, MessageResponseDto, MFAMethodEnum, NestAuthUser } from '../../core';
3
+ import { MfaService } from '../services/mfa.service';
4
+ import { RequestContext } from '../../request-context/request-context';
5
+ import { SendMfaCodeRequestDto } from '../dto/requests/send-mfa-code.request.dto';
6
+ import { VerifyTotpSetupRequestDto } from '../dto/requests/verify-totp-setup.request.dto';
7
+ import { ApiOperation, ApiResponse } from '@nestjs/swagger';
8
+ import { INVALID_MFA_EXCEPTION_CODE, USER_NOT_FOUND_EXCEPTION_CODE } from '../../auth.constants';
9
+ import { NestAuthAuthGuard } from '../guards/auth.guard';
10
+ import { ToggleMfaRequestDto } from '../dto/requests/toggle-mfa.request.dto';
11
+ import { MfaStatusResponseDto, MfaDeviceDto } from '../dto/responses/mfa-status.response.dto';
12
+ import { AuthConfigService } from '../../core/services/auth-config.service';
13
+
14
+ @Controller('auth/mfa')
15
+ export class MfaController {
16
+ constructor(
17
+ private readonly mfaService: MfaService,
18
+ private readonly authConfig: AuthConfigService,
19
+ ) { }
20
+
21
+ private getCurrentUserOrThrow() {
22
+ const user = RequestContext.currentUser();
23
+ if (!user) {
24
+ throw new UnauthorizedException('User not found');
25
+ }
26
+ return user;
27
+ }
28
+
29
+ @ApiOperation({ summary: 'Get MFA status for the current user' })
30
+ @ApiResponse({ status: 200, type: MfaStatusResponseDto })
31
+ @HttpCode(200)
32
+ @Get('status')
33
+ @SkipMfa()
34
+ @UseGuards(NestAuthAuthGuard)
35
+ async getStatus(): Promise<MfaStatusResponseDto> {
36
+ const user = this.getCurrentUserOrThrow();
37
+
38
+ const config = this.mfaService.mfaConfig;
39
+ const globallyEnabled = config?.enabled ?? false;
40
+
41
+ let enabledMethods: MFAMethodEnum[] = [];
42
+ let totpDevices: MfaDeviceDto[] = [];
43
+ let hasRecoveryCode = false;
44
+ let isEnabled = false;
45
+
46
+ if (globallyEnabled) {
47
+ [enabledMethods, totpDevices, hasRecoveryCode, isEnabled] = await Promise.all([
48
+ this.mfaService.getEnabledMethods(user.id),
49
+ this.mfaService.getTotpDevices(user.id),
50
+ this.mfaService.hasRecoveryCode(user.id),
51
+ this.mfaService.isMfaEnabled(user.id),
52
+ ]);
53
+ }
54
+
55
+ return {
56
+ isEnabled,
57
+ enabledMethods,
58
+ availableMethods: this.mfaService.getAvailableMethods(),
59
+ allowUserToggle: config?.allowUserToggle ?? false,
60
+ allowMethodSelection: config?.allowMethodSelection ?? false,
61
+ totpDevices,
62
+ hasRecoveryCode,
63
+ };
64
+ }
65
+
66
+ @ApiOperation({ summary: 'Enable or disable MFA for the current user' })
67
+ @ApiResponse({ status: 200, type: MessageResponseDto })
68
+ @HttpCode(200)
69
+ @Post('toggle')
70
+ @SkipMfa()
71
+ @UseGuards(NestAuthAuthGuard)
72
+ async toggleMfa(@Body() input: ToggleMfaRequestDto): Promise<MessageResponseDto> {
73
+ const user = this.getCurrentUserOrThrow();
74
+
75
+ this.mfaService.requireMfaEnabledForApp(true);
76
+
77
+ if (input.enabled) {
78
+ await this.mfaService.enableMFA(user.id);
79
+ return { message: 'MFA enabled successfully' };
80
+ }
81
+
82
+ await this.mfaService.disableMFA(user.id);
83
+ return { message: 'MFA disabled successfully' };
84
+ }
85
+
86
+ @ApiOperation({ summary: 'List registered MFA devices' })
87
+ @ApiResponse({ status: 200, type: [MfaDeviceDto] })
88
+ @HttpCode(200)
89
+ @Get('devices')
90
+ @SkipMfa()
91
+ @UseGuards(NestAuthAuthGuard)
92
+ async listDevices(): Promise<MfaDeviceDto[]> {
93
+ const user = this.getCurrentUserOrThrow();
94
+
95
+ this.mfaService.requireMfaEnabledForApp(true);
96
+ return await this.mfaService.getTotpDevices(user.id);
97
+ }
98
+
99
+ @ApiOperation({ summary: 'Remove a registered MFA device' })
100
+ @ApiResponse({ status: 200, type: MessageResponseDto })
101
+ @HttpCode(200)
102
+ @Delete('devices/:deviceId')
103
+ @SkipMfa()
104
+ @UseGuards(NestAuthAuthGuard)
105
+ async removeDevice(@Param('deviceId') deviceId: string): Promise<MessageResponseDto> {
106
+ const user = this.getCurrentUserOrThrow();
107
+
108
+ this.mfaService.requireMfaEnabledForApp(true);
109
+ await this.mfaService.removeTotpDevice(deviceId);
110
+ return { message: 'MFA device removed successfully' };
111
+ }
112
+
113
+ @ApiOperation({ summary: 'Send MFA Code' })
114
+ @ApiResponse({ status: 200, type: MessageResponseDto })
115
+ @HttpCode(200)
116
+ @Post('send-mfa-code')
117
+ @SkipMfa()
118
+ @UseGuards(NestAuthAuthGuard)
119
+ async sendMfaCode(@Body() input: SendMfaCodeRequestDto) {
120
+ const user = this.getCurrentUserOrThrow();
121
+
122
+ await this.mfaService.sendMfaCode(user.id, input.method);
123
+
124
+ return { message: 'MFA code sent' };
125
+ }
126
+
127
+ // These routes skip MFA verification
128
+ @ApiOperation({ summary: 'Setup TOTP Device' })
129
+ @ApiResponse({ status: 200, type: MessageResponseDto })
130
+ @HttpCode(200)
131
+ @Post('setup-totp')
132
+ @SkipMfa()
133
+ @UseGuards(NestAuthAuthGuard)
134
+ async setupTotp() {
135
+ const user = this.getCurrentUserOrThrow();
136
+
137
+ const config = this.authConfig.getConfig();
138
+
139
+ // Get app name from config, fallback to default
140
+ const appName = config.appName;
141
+
142
+ // Get user email - try from JWT token first, then from database
143
+ let userEmail = user.email;
144
+ if (!userEmail) {
145
+ const fullUser = await NestAuthUser.findOne({ where: { id: user.id } });
146
+ userEmail = fullUser?.email || 'User';
147
+ }
148
+
149
+ // Generate meaningful device name: {APP_NAME} : {email}
150
+ const deviceName = `${appName} : ${userEmail}`;
151
+
152
+ const { secret, qrCode } = await this.mfaService.setupTotpDevice(user.id, deviceName);
153
+ return { secret, qrCode };
154
+ }
155
+
156
+ @ApiOperation({ summary: 'Verify TOTP Setup' })
157
+ @ApiResponse({ status: 200, type: MessageResponseDto })
158
+ @HttpCode(200)
159
+ @Post('verify-totp-setup')
160
+ @SkipMfa()
161
+ @UseGuards(NestAuthAuthGuard)
162
+ async verifyTotpSetup(@Body() input: VerifyTotpSetupRequestDto) {
163
+ const user = this.getCurrentUserOrThrow();
164
+
165
+ const isVerified = await this.mfaService.verifyTotpSetup(user.id, input.secret, input.otp);
166
+ if (!isVerified) {
167
+ throw new UnauthorizedException({
168
+ message: 'Invalid OTP',
169
+ code: INVALID_MFA_EXCEPTION_CODE
170
+ });
171
+ }
172
+ return { message: 'Device setup successfully' };
173
+ }
174
+
175
+ @ApiOperation({ summary: 'Generate Recovery Codes' })
176
+ @ApiResponse({ status: 200, type: MessageResponseDto })
177
+ @HttpCode(200)
178
+ @Post('generate-recovery-code')
179
+ @SkipMfa()
180
+ @UseGuards(NestAuthAuthGuard)
181
+ async generateRecoveryCodes() {
182
+ const user = this.getCurrentUserOrThrow();
183
+
184
+ // Generate recovery codes
185
+ const code = await this.mfaService.generateRecoveryCode(user.id);
186
+ return { code };
187
+ }
188
+
189
+ @ApiOperation({ summary: 'Reset TOTP Device' })
190
+ @ApiResponse({ status: 200, type: MessageResponseDto })
191
+ @HttpCode(200)
192
+ @Post('reset-totp')
193
+ @SkipMfa()
194
+ @UseGuards(NestAuthAuthGuard)
195
+ async resetTotp(@Body('code') code: string) {
196
+ const user = this.getCurrentUserOrThrow();
197
+ await this.mfaService.resetMfa(user.id, code);
198
+ return { message: 'MFA reset successfully' };
199
+ }
200
+ }
@@ -0,0 +1,24 @@
1
+ import { ApiProperty } from '@nestjs/swagger';
2
+ import { IsEmail, IsString, IsNotEmpty } from 'class-validator';
3
+
4
+ /**
5
+ * Email-based login credentials
6
+ */
7
+ export class EmailCredentialsDto {
8
+ @ApiProperty({
9
+ description: 'User email address',
10
+ example: 'user@example.com',
11
+ })
12
+ @IsEmail()
13
+ @IsNotEmpty()
14
+ email: string;
15
+
16
+ @ApiProperty({
17
+ description: 'User password',
18
+ example: 'SecurePass123!',
19
+ minLength: 8,
20
+ })
21
+ @IsString()
22
+ @IsNotEmpty()
23
+ password: string;
24
+ }