@techelusive/nest-auth 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (340) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/LICENSE +21 -0
  3. package/README.md +204 -2
  4. package/api/openapi.json +4399 -0
  5. package/api/techelusive-authentication.postman_collection.json +3178 -0
  6. package/dist/auth-options.d.ts +156 -0
  7. package/dist/auth-options.js +3 -0
  8. package/dist/auth-options.js.map +1 -0
  9. package/dist/auth-options.validation.d.ts +9 -0
  10. package/dist/auth-options.validation.js +74 -0
  11. package/dist/auth-options.validation.js.map +1 -0
  12. package/dist/auth.module.d.ts +38 -0
  13. package/dist/auth.module.js +173 -0
  14. package/dist/auth.module.js.map +1 -0
  15. package/dist/common/auth-error.d.ts +16 -0
  16. package/dist/common/auth-error.js +23 -0
  17. package/dist/common/auth-error.js.map +1 -0
  18. package/dist/common/auth-exception.filter.d.ts +24 -0
  19. package/dist/common/auth-exception.filter.js +66 -0
  20. package/dist/common/auth-exception.filter.js.map +1 -0
  21. package/dist/common/crypto/jwt.d.ts +89 -0
  22. package/dist/common/crypto/jwt.js +144 -0
  23. package/dist/common/crypto/jwt.js.map +1 -0
  24. package/dist/common/crypto/random-secrets.d.ts +78 -0
  25. package/dist/common/crypto/random-secrets.js +113 -0
  26. package/dist/common/crypto/random-secrets.js.map +1 -0
  27. package/dist/common/crypto/remote-public-keys.d.ts +49 -0
  28. package/dist/common/crypto/remote-public-keys.js +105 -0
  29. package/dist/common/crypto/remote-public-keys.js.map +1 -0
  30. package/dist/common/crypto/totp.d.ts +68 -0
  31. package/dist/common/crypto/totp.js +148 -0
  32. package/dist/common/crypto/totp.js.map +1 -0
  33. package/dist/common/encryption.service.d.ts +36 -0
  34. package/dist/common/encryption.service.js +111 -0
  35. package/dist/common/encryption.service.js.map +1 -0
  36. package/dist/common/identifiers.d.ts +48 -0
  37. package/dist/common/identifiers.js +89 -0
  38. package/dist/common/identifiers.js.map +1 -0
  39. package/dist/common/network-safety.d.ts +19 -0
  40. package/dist/common/network-safety.js +72 -0
  41. package/dist/common/network-safety.js.map +1 -0
  42. package/dist/common/rate-limiter.service.d.ts +63 -0
  43. package/dist/common/rate-limiter.service.js +158 -0
  44. package/dist/common/rate-limiter.service.js.map +1 -0
  45. package/dist/common/refresh-token-cookie.d.ts +78 -0
  46. package/dist/common/refresh-token-cookie.js +185 -0
  47. package/dist/common/refresh-token-cookie.js.map +1 -0
  48. package/dist/common/request-context.d.ts +14 -0
  49. package/dist/common/request-context.js +22 -0
  50. package/dist/common/request-context.js.map +1 -0
  51. package/dist/common/strict-validation.pipe.d.ts +8 -0
  52. package/dist/common/strict-validation.pipe.js +16 -0
  53. package/dist/common/strict-validation.pipe.js.map +1 -0
  54. package/dist/common/time.d.ts +15 -0
  55. package/dist/common/time.js +34 -0
  56. package/dist/common/time.js.map +1 -0
  57. package/dist/constants.d.ts +1326 -0
  58. package/dist/constants.js +1142 -0
  59. package/dist/constants.js.map +1 -0
  60. package/dist/database/create-auth-tables.migration.d.ts +26 -0
  61. package/dist/database/create-auth-tables.migration.js +291 -0
  62. package/dist/database/create-auth-tables.migration.js.map +1 -0
  63. package/dist/database/email-change-and-retention.migration.d.ts +25 -0
  64. package/dist/database/email-change-and-retention.migration.js +54 -0
  65. package/dist/database/email-change-and-retention.migration.js.map +1 -0
  66. package/dist/database/entities/api-key.entity.d.ts +17 -0
  67. package/dist/database/entities/api-key.entity.js +80 -0
  68. package/dist/database/entities/api-key.entity.js.map +1 -0
  69. package/dist/database/entities/audit-log.entity.d.ts +13 -0
  70. package/dist/database/entities/audit-log.entity.js +64 -0
  71. package/dist/database/entities/audit-log.entity.js.map +1 -0
  72. package/dist/database/entities/backup-code.entity.d.ts +9 -0
  73. package/dist/database/entities/backup-code.entity.js +52 -0
  74. package/dist/database/entities/backup-code.entity.js.map +1 -0
  75. package/dist/database/entities/index.d.ts +43 -0
  76. package/dist/database/entities/index.js +82 -0
  77. package/dist/database/entities/index.js.map +1 -0
  78. package/dist/database/entities/json-object.d.ts +12 -0
  79. package/dist/database/entities/json-object.js +3 -0
  80. package/dist/database/entities/json-object.js.map +1 -0
  81. package/dist/database/entities/link-token.entity.d.ts +15 -0
  82. package/dist/database/entities/link-token.entity.js +64 -0
  83. package/dist/database/entities/link-token.entity.js.map +1 -0
  84. package/dist/database/entities/one-time-code.entity.d.ts +16 -0
  85. package/dist/database/entities/one-time-code.entity.js +69 -0
  86. package/dist/database/entities/one-time-code.entity.js.map +1 -0
  87. package/dist/database/entities/organization-invitation.entity.d.ts +14 -0
  88. package/dist/database/entities/organization-invitation.entity.js +73 -0
  89. package/dist/database/entities/organization-invitation.entity.js.map +1 -0
  90. package/dist/database/entities/organization-member.entity.d.ts +9 -0
  91. package/dist/database/entities/organization-member.entity.js +48 -0
  92. package/dist/database/entities/organization-member.entity.js.map +1 -0
  93. package/dist/database/entities/organization.entity.d.ts +12 -0
  94. package/dist/database/entities/organization.entity.js +58 -0
  95. package/dist/database/entities/organization.entity.js.map +1 -0
  96. package/dist/database/entities/passkey.entity.d.ts +19 -0
  97. package/dist/database/entities/passkey.entity.js +78 -0
  98. package/dist/database/entities/passkey.entity.js.map +1 -0
  99. package/dist/database/entities/password.entity.d.ts +6 -0
  100. package/dist/database/entities/password.entity.js +36 -0
  101. package/dist/database/entities/password.entity.js.map +1 -0
  102. package/dist/database/entities/refresh-token.entity.d.ts +9 -0
  103. package/dist/database/entities/refresh-token.entity.js +53 -0
  104. package/dist/database/entities/refresh-token.entity.js.map +1 -0
  105. package/dist/database/entities/session.entity.d.ts +20 -0
  106. package/dist/database/entities/session.entity.js +87 -0
  107. package/dist/database/entities/session.entity.js.map +1 -0
  108. package/dist/database/entities/settings.entity.d.ts +7 -0
  109. package/dist/database/entities/settings.entity.js +41 -0
  110. package/dist/database/entities/settings.entity.js.map +1 -0
  111. package/dist/database/entities/sign-in-challenge.entity.d.ts +23 -0
  112. package/dist/database/entities/sign-in-challenge.entity.js +80 -0
  113. package/dist/database/entities/sign-in-challenge.entity.js.map +1 -0
  114. package/dist/database/entities/signing-key.entity.d.ts +11 -0
  115. package/dist/database/entities/signing-key.entity.js +54 -0
  116. package/dist/database/entities/signing-key.entity.js.map +1 -0
  117. package/dist/database/entities/social-account.entity.d.ts +13 -0
  118. package/dist/database/entities/social-account.entity.js +54 -0
  119. package/dist/database/entities/social-account.entity.js.map +1 -0
  120. package/dist/database/entities/two-factor-secret.entity.d.ts +10 -0
  121. package/dist/database/entities/two-factor-secret.entity.js +48 -0
  122. package/dist/database/entities/two-factor-secret.entity.js.map +1 -0
  123. package/dist/database/entities/user.entity.d.ts +34 -0
  124. package/dist/database/entities/user.entity.js +129 -0
  125. package/dist/database/entities/user.entity.js.map +1 -0
  126. package/dist/database/entities/webhook-delivery.entity.d.ts +17 -0
  127. package/dist/database/entities/webhook-delivery.entity.js +79 -0
  128. package/dist/database/entities/webhook-delivery.entity.js.map +1 -0
  129. package/dist/database/entities/webhook.entity.d.ts +12 -0
  130. package/dist/database/entities/webhook.entity.js +58 -0
  131. package/dist/database/entities/webhook.entity.js.map +1 -0
  132. package/dist/database/typeorm-row.d.ts +21 -0
  133. package/dist/database/typeorm-row.js +29 -0
  134. package/dist/database/typeorm-row.js.map +1 -0
  135. package/dist/features/account/account.controller.d.ts +259 -0
  136. package/dist/features/account/account.controller.js +372 -0
  137. package/dist/features/account/account.controller.js.map +1 -0
  138. package/dist/features/account/account.dto.d.ts +16 -0
  139. package/dist/features/account/account.dto.js +61 -0
  140. package/dist/features/account/account.dto.js.map +1 -0
  141. package/dist/features/account/data-export.service.d.ts +85 -0
  142. package/dist/features/account/data-export.service.js +125 -0
  143. package/dist/features/account/data-export.service.js.map +1 -0
  144. package/dist/features/account/health.service.d.ts +30 -0
  145. package/dist/features/account/health.service.js +59 -0
  146. package/dist/features/account/health.service.js.map +1 -0
  147. package/dist/features/admin/admin.controller.d.ts +382 -0
  148. package/dist/features/admin/admin.controller.js +623 -0
  149. package/dist/features/admin/admin.controller.js.map +1 -0
  150. package/dist/features/admin/admin.dto.d.ts +61 -0
  151. package/dist/features/admin/admin.dto.js +253 -0
  152. package/dist/features/admin/admin.dto.js.map +1 -0
  153. package/dist/features/admin/admin.service.d.ts +142 -0
  154. package/dist/features/admin/admin.service.js +227 -0
  155. package/dist/features/admin/admin.service.js.map +1 -0
  156. package/dist/features/api-keys/api-keys.service.d.ts +67 -0
  157. package/dist/features/api-keys/api-keys.service.js +144 -0
  158. package/dist/features/api-keys/api-keys.service.js.map +1 -0
  159. package/dist/features/email-change/email-change.controller.d.ts +38 -0
  160. package/dist/features/email-change/email-change.controller.js +85 -0
  161. package/dist/features/email-change/email-change.controller.js.map +1 -0
  162. package/dist/features/email-change/email-change.dto.d.ts +10 -0
  163. package/dist/features/email-change/email-change.dto.js +43 -0
  164. package/dist/features/email-change/email-change.dto.js.map +1 -0
  165. package/dist/features/email-change/email-change.service.d.ts +74 -0
  166. package/dist/features/email-change/email-change.service.js +179 -0
  167. package/dist/features/email-change/email-change.service.js.map +1 -0
  168. package/dist/features/email-links/email-verification.service.d.ts +46 -0
  169. package/dist/features/email-links/email-verification.service.js +94 -0
  170. package/dist/features/email-links/email-verification.service.js.map +1 -0
  171. package/dist/features/email-links/link-tokens.service.d.ts +44 -0
  172. package/dist/features/email-links/link-tokens.service.js +122 -0
  173. package/dist/features/email-links/link-tokens.service.js.map +1 -0
  174. package/dist/features/events/auth-events.service.d.ts +52 -0
  175. package/dist/features/events/auth-events.service.js +117 -0
  176. package/dist/features/events/auth-events.service.js.map +1 -0
  177. package/dist/features/maintenance/data-retention.service.d.ts +60 -0
  178. package/dist/features/maintenance/data-retention.service.js +182 -0
  179. package/dist/features/maintenance/data-retention.service.js.map +1 -0
  180. package/dist/features/notifications/notifications.service.d.ts +40 -0
  181. package/dist/features/notifications/notifications.service.js +94 -0
  182. package/dist/features/notifications/notifications.service.js.map +1 -0
  183. package/dist/features/one-time-codes/one-time-codes.service.d.ts +40 -0
  184. package/dist/features/one-time-codes/one-time-codes.service.js +102 -0
  185. package/dist/features/one-time-codes/one-time-codes.service.js.map +1 -0
  186. package/dist/features/organizations/organizations.controller.d.ts +220 -0
  187. package/dist/features/organizations/organizations.controller.js +337 -0
  188. package/dist/features/organizations/organizations.controller.js.map +1 -0
  189. package/dist/features/organizations/organizations.dto.d.ts +31 -0
  190. package/dist/features/organizations/organizations.dto.js +100 -0
  191. package/dist/features/organizations/organizations.dto.js.map +1 -0
  192. package/dist/features/organizations/organizations.service.d.ts +274 -0
  193. package/dist/features/organizations/organizations.service.js +481 -0
  194. package/dist/features/organizations/organizations.service.js.map +1 -0
  195. package/dist/features/passkeys/passkeys.controller.d.ts +92 -0
  196. package/dist/features/passkeys/passkeys.controller.js +183 -0
  197. package/dist/features/passkeys/passkeys.controller.js.map +1 -0
  198. package/dist/features/passkeys/passkeys.dto.d.ts +13 -0
  199. package/dist/features/passkeys/passkeys.dto.js +50 -0
  200. package/dist/features/passkeys/passkeys.dto.js.map +1 -0
  201. package/dist/features/passkeys/passkeys.service.d.ts +159 -0
  202. package/dist/features/passkeys/passkeys.service.js +350 -0
  203. package/dist/features/passkeys/passkeys.service.js.map +1 -0
  204. package/dist/features/passwordless/passwordless-auth.service.d.ts +152 -0
  205. package/dist/features/passwordless/passwordless-auth.service.js +304 -0
  206. package/dist/features/passwordless/passwordless-auth.service.js.map +1 -0
  207. package/dist/features/passwordless/passwordless.controller.d.ts +75 -0
  208. package/dist/features/passwordless/passwordless.controller.js +163 -0
  209. package/dist/features/passwordless/passwordless.controller.js.map +1 -0
  210. package/dist/features/passwordless/passwordless.dto.d.ts +29 -0
  211. package/dist/features/passwordless/passwordless.dto.js +101 -0
  212. package/dist/features/passwordless/passwordless.dto.js.map +1 -0
  213. package/dist/features/passwords/password-auth.service.d.ts +154 -0
  214. package/dist/features/passwords/password-auth.service.js +317 -0
  215. package/dist/features/passwords/password-auth.service.js.map +1 -0
  216. package/dist/features/passwords/password-policy.service.d.ts +63 -0
  217. package/dist/features/passwords/password-policy.service.js +175 -0
  218. package/dist/features/passwords/password-policy.service.js.map +1 -0
  219. package/dist/features/passwords/password.controller.d.ts +95 -0
  220. package/dist/features/passwords/password.controller.js +193 -0
  221. package/dist/features/passwords/password.controller.js.map +1 -0
  222. package/dist/features/passwords/password.dto.d.ts +36 -0
  223. package/dist/features/passwords/password.dto.js +140 -0
  224. package/dist/features/passwords/password.dto.js.map +1 -0
  225. package/dist/features/sessions/session.service.d.ts +132 -0
  226. package/dist/features/sessions/session.service.js +308 -0
  227. package/dist/features/sessions/session.service.js.map +1 -0
  228. package/dist/features/sessions/session.types.d.ts +34 -0
  229. package/dist/features/sessions/session.types.js +3 -0
  230. package/dist/features/sessions/session.types.js.map +1 -0
  231. package/dist/features/settings/settings.defaults.d.ts +2 -0
  232. package/dist/features/settings/settings.defaults.js +7 -0
  233. package/dist/features/settings/settings.defaults.js.map +1 -0
  234. package/dist/features/settings/settings.service.d.ts +44 -0
  235. package/dist/features/settings/settings.service.js +112 -0
  236. package/dist/features/settings/settings.service.js.map +1 -0
  237. package/dist/features/settings/settings.types.d.ts +133 -0
  238. package/dist/features/settings/settings.types.js +3 -0
  239. package/dist/features/settings/settings.types.js.map +1 -0
  240. package/dist/features/settings/settings.validation.d.ts +33 -0
  241. package/dist/features/settings/settings.validation.js +614 -0
  242. package/dist/features/settings/settings.validation.js.map +1 -0
  243. package/dist/features/sign-in/sign-in-challenges.service.d.ts +54 -0
  244. package/dist/features/sign-in/sign-in-challenges.service.js +104 -0
  245. package/dist/features/sign-in/sign-in-challenges.service.js.map +1 -0
  246. package/dist/features/sign-in/sign-in.service.d.ts +127 -0
  247. package/dist/features/sign-in/sign-in.service.js +248 -0
  248. package/dist/features/sign-in/sign-in.service.js.map +1 -0
  249. package/dist/features/sign-in/sign-in.types.d.ts +22 -0
  250. package/dist/features/sign-in/sign-in.types.js +3 -0
  251. package/dist/features/sign-in/sign-in.types.js.map +1 -0
  252. package/dist/features/signing-keys/jwks.controller.d.ts +17 -0
  253. package/dist/features/signing-keys/jwks.controller.js +51 -0
  254. package/dist/features/signing-keys/jwks.controller.js.map +1 -0
  255. package/dist/features/signing-keys/signing-keys.service.d.ts +67 -0
  256. package/dist/features/signing-keys/signing-keys.service.js +142 -0
  257. package/dist/features/signing-keys/signing-keys.service.js.map +1 -0
  258. package/dist/features/social/social-auth.service.d.ts +100 -0
  259. package/dist/features/social/social-auth.service.js +232 -0
  260. package/dist/features/social/social-auth.service.js.map +1 -0
  261. package/dist/features/social/social-providers.service.d.ts +97 -0
  262. package/dist/features/social/social-providers.service.js +214 -0
  263. package/dist/features/social/social-providers.service.js.map +1 -0
  264. package/dist/features/social/social.controller.d.ts +54 -0
  265. package/dist/features/social/social.controller.js +124 -0
  266. package/dist/features/social/social.controller.js.map +1 -0
  267. package/dist/features/social/social.dto.d.ts +11 -0
  268. package/dist/features/social/social.dto.js +38 -0
  269. package/dist/features/social/social.dto.js.map +1 -0
  270. package/dist/features/two-factor/two-factor.controller.d.ts +84 -0
  271. package/dist/features/two-factor/two-factor.controller.js +174 -0
  272. package/dist/features/two-factor/two-factor.controller.js.map +1 -0
  273. package/dist/features/two-factor/two-factor.dto.d.ts +10 -0
  274. package/dist/features/two-factor/two-factor.dto.js +37 -0
  275. package/dist/features/two-factor/two-factor.dto.js.map +1 -0
  276. package/dist/features/two-factor/two-factor.service.d.ts +171 -0
  277. package/dist/features/two-factor/two-factor.service.js +348 -0
  278. package/dist/features/two-factor/two-factor.service.js.map +1 -0
  279. package/dist/features/users/sign-in-methods.service.d.ts +40 -0
  280. package/dist/features/users/sign-in-methods.service.js +81 -0
  281. package/dist/features/users/sign-in-methods.service.js.map +1 -0
  282. package/dist/features/users/sign-up-rules.d.ts +12 -0
  283. package/dist/features/users/sign-up-rules.js +29 -0
  284. package/dist/features/users/sign-up-rules.js.map +1 -0
  285. package/dist/features/users/users.service.d.ts +246 -0
  286. package/dist/features/users/users.service.js +509 -0
  287. package/dist/features/users/users.service.js.map +1 -0
  288. package/dist/features/users/users.types.d.ts +24 -0
  289. package/dist/features/users/users.types.js +3 -0
  290. package/dist/features/users/users.types.js.map +1 -0
  291. package/dist/features/webhooks/webhook-delivery.worker.d.ts +55 -0
  292. package/dist/features/webhooks/webhook-delivery.worker.js +175 -0
  293. package/dist/features/webhooks/webhook-delivery.worker.js.map +1 -0
  294. package/dist/features/webhooks/webhook-signature.d.ts +28 -0
  295. package/dist/features/webhooks/webhook-signature.js +85 -0
  296. package/dist/features/webhooks/webhook-signature.js.map +1 -0
  297. package/dist/features/webhooks/webhooks.service.d.ts +144 -0
  298. package/dist/features/webhooks/webhooks.service.js +238 -0
  299. package/dist/features/webhooks/webhooks.service.js.map +1 -0
  300. package/dist/guards/auth.decorators.d.ts +65 -0
  301. package/dist/guards/auth.decorators.js +68 -0
  302. package/dist/guards/auth.decorators.js.map +1 -0
  303. package/dist/guards/auth.guard.d.ts +47 -0
  304. package/dist/guards/auth.guard.js +132 -0
  305. package/dist/guards/auth.guard.js.map +1 -0
  306. package/dist/index.d.ts +38 -0
  307. package/dist/index.js +95 -0
  308. package/dist/index.js.map +1 -0
  309. package/dist/integrations/console-email-sender.d.ts +15 -0
  310. package/dist/integrations/console-email-sender.js +26 -0
  311. package/dist/integrations/console-email-sender.js.map +1 -0
  312. package/dist/integrations/msg91-sms-sender.d.ts +28 -0
  313. package/dist/integrations/msg91-sms-sender.js +46 -0
  314. package/dist/integrations/msg91-sms-sender.js.map +1 -0
  315. package/docs/README.md +39 -0
  316. package/docs/admin-api-keys-webhooks.md +147 -0
  317. package/docs/api-reference.md +175 -0
  318. package/docs/architecture.md +119 -0
  319. package/docs/client-integration.md +192 -0
  320. package/docs/code-walkthrough.md +273 -0
  321. package/docs/configuration.md +229 -0
  322. package/docs/endpoints/README.md +151 -0
  323. package/docs/endpoints/account.md +363 -0
  324. package/docs/endpoints/admin.md +422 -0
  325. package/docs/endpoints/email-password.md +261 -0
  326. package/docs/endpoints/organizations.md +192 -0
  327. package/docs/endpoints/passkeys.md +195 -0
  328. package/docs/endpoints/passwordless.md +214 -0
  329. package/docs/endpoints/social.md +116 -0
  330. package/docs/endpoints/two-factor.md +146 -0
  331. package/docs/error-codes.md +100 -0
  332. package/docs/events.md +83 -0
  333. package/docs/getting-started.md +139 -0
  334. package/docs/manual-testing.md +215 -0
  335. package/docs/organizations.md +86 -0
  336. package/docs/production-checklist.md +60 -0
  337. package/docs/protecting-routes.md +147 -0
  338. package/docs/security.md +61 -0
  339. package/docs/sign-in-flows.md +294 -0
  340. package/package.json +92 -4
package/dist/index.js ADDED
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ /**
3
+ * @techelusive/nest-auth: reusable authentication for NestJS apps.
4
+ * Everything an app needs is exported from here.
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
18
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
19
+ };
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.verifyWebhookSignature = exports.ConsoleEmailSender = exports.Msg91SmsSender = exports.SOCIAL_PROVIDER = exports.SIGN_IN_STATUS = exports.SIGN_IN_METHOD = exports.ROUTES = exports.PENDING_VERIFICATION = exports.ORGANIZATION_ROLES = exports.ORGANIZATION_ROLE = exports.AUTH_EVENTS = exports.AUTH_ERRORS = exports.ACCOUNT_STATUSES = exports.ACCOUNT_STATUS = exports.AuthError = exports.DEFAULT_SETTINGS = exports.WebhooksService = exports.SigningKeysService = exports.TwoFactorService = exports.OrganizationsService = exports.ApiKeysService = exports.AuthEventsService = exports.SettingsService = exports.SignInService = exports.SessionService = exports.DataRetentionService = exports.UsersService = exports.EmailChangeAndRetention1792700000000 = exports.CreateAuthTables1792600000000 = exports.AUTH_MIGRATIONS = exports.SYSTEM_REQUEST = exports.CurrentRequest = exports.Roles = exports.Public = exports.CurrentUserId = exports.CurrentUser = exports.CurrentCaller = exports.CheckSession = exports.ApiKeyScopes = exports.AdminOnly = exports.AuthGuard = exports.AuthModule = void 0;
22
+ // The module and its options
23
+ var auth_module_1 = require("./auth.module");
24
+ Object.defineProperty(exports, "AuthModule", { enumerable: true, get: function () { return auth_module_1.AuthModule; } });
25
+ // Protecting routes
26
+ var auth_guard_1 = require("./guards/auth.guard");
27
+ Object.defineProperty(exports, "AuthGuard", { enumerable: true, get: function () { return auth_guard_1.AuthGuard; } });
28
+ var auth_decorators_1 = require("./guards/auth.decorators");
29
+ Object.defineProperty(exports, "AdminOnly", { enumerable: true, get: function () { return auth_decorators_1.AdminOnly; } });
30
+ Object.defineProperty(exports, "ApiKeyScopes", { enumerable: true, get: function () { return auth_decorators_1.ApiKeyScopes; } });
31
+ Object.defineProperty(exports, "CheckSession", { enumerable: true, get: function () { return auth_decorators_1.CheckSession; } });
32
+ Object.defineProperty(exports, "CurrentCaller", { enumerable: true, get: function () { return auth_decorators_1.CurrentCaller; } });
33
+ Object.defineProperty(exports, "CurrentUser", { enumerable: true, get: function () { return auth_decorators_1.CurrentUser; } });
34
+ Object.defineProperty(exports, "CurrentUserId", { enumerable: true, get: function () { return auth_decorators_1.CurrentUserId; } });
35
+ Object.defineProperty(exports, "Public", { enumerable: true, get: function () { return auth_decorators_1.Public; } });
36
+ Object.defineProperty(exports, "Roles", { enumerable: true, get: function () { return auth_decorators_1.Roles; } });
37
+ var request_context_1 = require("./common/request-context");
38
+ Object.defineProperty(exports, "CurrentRequest", { enumerable: true, get: function () { return request_context_1.CurrentRequest; } });
39
+ Object.defineProperty(exports, "SYSTEM_REQUEST", { enumerable: true, get: function () { return request_context_1.SYSTEM_REQUEST; } });
40
+ // Database: add AUTH_ENTITIES to your DataSource and AUTH_MIGRATIONS to its migrations
41
+ __exportStar(require("./database/entities"), exports);
42
+ var create_auth_tables_migration_1 = require("./database/create-auth-tables.migration");
43
+ Object.defineProperty(exports, "AUTH_MIGRATIONS", { enumerable: true, get: function () { return create_auth_tables_migration_1.AUTH_MIGRATIONS; } });
44
+ Object.defineProperty(exports, "CreateAuthTables1792600000000", { enumerable: true, get: function () { return create_auth_tables_migration_1.CreateAuthTables1792600000000; } });
45
+ var email_change_and_retention_migration_1 = require("./database/email-change-and-retention.migration");
46
+ Object.defineProperty(exports, "EmailChangeAndRetention1792700000000", { enumerable: true, get: function () { return email_change_and_retention_migration_1.EmailChangeAndRetention1792700000000; } });
47
+ // Services your app can use
48
+ var users_service_1 = require("./features/users/users.service");
49
+ Object.defineProperty(exports, "UsersService", { enumerable: true, get: function () { return users_service_1.UsersService; } });
50
+ var data_retention_service_1 = require("./features/maintenance/data-retention.service");
51
+ Object.defineProperty(exports, "DataRetentionService", { enumerable: true, get: function () { return data_retention_service_1.DataRetentionService; } });
52
+ var session_service_1 = require("./features/sessions/session.service");
53
+ Object.defineProperty(exports, "SessionService", { enumerable: true, get: function () { return session_service_1.SessionService; } });
54
+ var sign_in_service_1 = require("./features/sign-in/sign-in.service");
55
+ Object.defineProperty(exports, "SignInService", { enumerable: true, get: function () { return sign_in_service_1.SignInService; } });
56
+ var settings_service_1 = require("./features/settings/settings.service");
57
+ Object.defineProperty(exports, "SettingsService", { enumerable: true, get: function () { return settings_service_1.SettingsService; } });
58
+ var auth_events_service_1 = require("./features/events/auth-events.service");
59
+ Object.defineProperty(exports, "AuthEventsService", { enumerable: true, get: function () { return auth_events_service_1.AuthEventsService; } });
60
+ var api_keys_service_1 = require("./features/api-keys/api-keys.service");
61
+ Object.defineProperty(exports, "ApiKeysService", { enumerable: true, get: function () { return api_keys_service_1.ApiKeysService; } });
62
+ var organizations_service_1 = require("./features/organizations/organizations.service");
63
+ Object.defineProperty(exports, "OrganizationsService", { enumerable: true, get: function () { return organizations_service_1.OrganizationsService; } });
64
+ var two_factor_service_1 = require("./features/two-factor/two-factor.service");
65
+ Object.defineProperty(exports, "TwoFactorService", { enumerable: true, get: function () { return two_factor_service_1.TwoFactorService; } });
66
+ var signing_keys_service_1 = require("./features/signing-keys/signing-keys.service");
67
+ Object.defineProperty(exports, "SigningKeysService", { enumerable: true, get: function () { return signing_keys_service_1.SigningKeysService; } });
68
+ var webhooks_service_1 = require("./features/webhooks/webhooks.service");
69
+ Object.defineProperty(exports, "WebhooksService", { enumerable: true, get: function () { return webhooks_service_1.WebhooksService; } });
70
+ var settings_defaults_1 = require("./features/settings/settings.defaults");
71
+ Object.defineProperty(exports, "DEFAULT_SETTINGS", { enumerable: true, get: function () { return settings_defaults_1.DEFAULT_SETTINGS; } });
72
+ // Errors and constants (stable error codes apps can check)
73
+ var auth_error_1 = require("./common/auth-error");
74
+ Object.defineProperty(exports, "AuthError", { enumerable: true, get: function () { return auth_error_1.AuthError; } });
75
+ var constants_1 = require("./constants");
76
+ Object.defineProperty(exports, "ACCOUNT_STATUS", { enumerable: true, get: function () { return constants_1.ACCOUNT_STATUS; } });
77
+ Object.defineProperty(exports, "ACCOUNT_STATUSES", { enumerable: true, get: function () { return constants_1.ACCOUNT_STATUSES; } });
78
+ Object.defineProperty(exports, "AUTH_ERRORS", { enumerable: true, get: function () { return constants_1.AUTH_ERRORS; } });
79
+ Object.defineProperty(exports, "AUTH_EVENTS", { enumerable: true, get: function () { return constants_1.AUTH_EVENTS; } });
80
+ Object.defineProperty(exports, "ORGANIZATION_ROLE", { enumerable: true, get: function () { return constants_1.ORGANIZATION_ROLE; } });
81
+ Object.defineProperty(exports, "ORGANIZATION_ROLES", { enumerable: true, get: function () { return constants_1.ORGANIZATION_ROLES; } });
82
+ Object.defineProperty(exports, "PENDING_VERIFICATION", { enumerable: true, get: function () { return constants_1.PENDING_VERIFICATION; } });
83
+ Object.defineProperty(exports, "ROUTES", { enumerable: true, get: function () { return constants_1.ROUTES; } });
84
+ Object.defineProperty(exports, "SIGN_IN_METHOD", { enumerable: true, get: function () { return constants_1.SIGN_IN_METHOD; } });
85
+ Object.defineProperty(exports, "SIGN_IN_STATUS", { enumerable: true, get: function () { return constants_1.SIGN_IN_STATUS; } });
86
+ Object.defineProperty(exports, "SOCIAL_PROVIDER", { enumerable: true, get: function () { return constants_1.SOCIAL_PROVIDER; } });
87
+ // Ready-made senders
88
+ var msg91_sms_sender_1 = require("./integrations/msg91-sms-sender");
89
+ Object.defineProperty(exports, "Msg91SmsSender", { enumerable: true, get: function () { return msg91_sms_sender_1.Msg91SmsSender; } });
90
+ var console_email_sender_1 = require("./integrations/console-email-sender");
91
+ Object.defineProperty(exports, "ConsoleEmailSender", { enumerable: true, get: function () { return console_email_sender_1.ConsoleEmailSender; } });
92
+ // For services that RECEIVE webhooks
93
+ var webhook_signature_1 = require("./features/webhooks/webhook-signature");
94
+ Object.defineProperty(exports, "verifyWebhookSignature", { enumerable: true, get: function () { return webhook_signature_1.verifyWebhookSignature; } });
95
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;AAEH,6BAA6B;AAC7B,6CAA2C;AAAlC,yGAAA,UAAU,OAAA;AAYnB,oBAAoB;AACpB,kDAAgD;AAAvC,uGAAA,SAAS,OAAA;AAClB,4DASkC;AARhC,4GAAA,SAAS,OAAA;AACT,+GAAA,YAAY,OAAA;AACZ,+GAAA,YAAY,OAAA;AACZ,gHAAA,aAAa,OAAA;AACb,8GAAA,WAAW,OAAA;AACX,gHAAA,aAAa,OAAA;AACb,yGAAA,MAAM,OAAA;AACN,wGAAA,KAAK,OAAA;AAGP,4DAA0E;AAAjE,iHAAA,cAAc,OAAA;AAAE,iHAAA,cAAc,OAAA;AAGvC,uFAAuF;AACvF,sDAAoC;AACpC,wFAAyG;AAAhG,+HAAA,eAAe,OAAA;AAAE,6IAAA,6BAA6B,OAAA;AACvD,wGAAuG;AAA9F,4JAAA,oCAAoC,OAAA;AAE7C,4BAA4B;AAC5B,gEAA8D;AAArD,6GAAA,YAAY,OAAA;AACrB,wFAAqF;AAA5E,8HAAA,oBAAoB,OAAA;AAE7B,uEAAqE;AAA5D,iHAAA,cAAc,OAAA;AACvB,sEAAmE;AAA1D,gHAAA,aAAa,OAAA;AACtB,yEAAuE;AAA9D,mHAAA,eAAe,OAAA;AACxB,6EAA0E;AAAjE,wHAAA,iBAAiB,OAAA;AAC1B,yEAAsE;AAA7D,kHAAA,cAAc,OAAA;AACvB,wFAAsF;AAA7E,6HAAA,oBAAoB,OAAA;AAC7B,+EAA4E;AAAnE,sHAAA,gBAAgB,OAAA;AACzB,qFAAkF;AAAzE,0HAAA,kBAAkB,OAAA;AAC3B,yEAAuE;AAA9D,mHAAA,eAAe,OAAA;AAOxB,2EAAyE;AAAhE,qHAAA,gBAAgB,OAAA;AAEzB,2DAA2D;AAC3D,kDAAgD;AAAvC,uGAAA,SAAS,OAAA;AAClB,yCAYqB;AAXnB,2GAAA,cAAc,OAAA;AACd,6GAAA,gBAAgB,OAAA;AAChB,wGAAA,WAAW,OAAA;AACX,wGAAA,WAAW,OAAA;AACX,8GAAA,iBAAiB,OAAA;AACjB,+GAAA,kBAAkB,OAAA;AAClB,iHAAA,oBAAoB,OAAA;AACpB,mGAAA,MAAM,OAAA;AACN,2GAAA,cAAc,OAAA;AACd,2GAAA,cAAc,OAAA;AACd,4GAAA,eAAe,OAAA;AAIjB,qBAAqB;AACrB,oEAAiE;AAAxD,kHAAA,cAAc,OAAA;AAEvB,4EAAyE;AAAhE,0HAAA,kBAAkB,OAAA;AAE3B,qCAAqC;AACrC,2EAA+E;AAAtE,2HAAA,sBAAsB,OAAA"}
@@ -0,0 +1,15 @@
1
+ import { AuthEmail, EmailSender } from '../auth-options.js';
2
+ /**
3
+ * Development only: prints emails to the console instead of sending them, so you can copy
4
+ * codes and links while building your app. Use a real sender (SES, Resend, SMTP...) in production.
5
+ */
6
+ export declare class ConsoleEmailSender implements EmailSender {
7
+ private readonly logger;
8
+ /**
9
+ * Prints the email to the console.
10
+ *
11
+ * @param email - The email the library wants to send.
12
+ * @throws When NODE_ENV is "production", so it can't be shipped by accident.
13
+ */
14
+ send(email: AuthEmail): Promise<void>;
15
+ }
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConsoleEmailSender = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ const constants_1 = require("../constants.js");
6
+ /**
7
+ * Development only: prints emails to the console instead of sending them, so you can copy
8
+ * codes and links while building your app. Use a real sender (SES, Resend, SMTP...) in production.
9
+ */
10
+ class ConsoleEmailSender {
11
+ logger = new common_1.Logger(constants_1.LOG_CONTEXT.consoleEmailSender);
12
+ /**
13
+ * Prints the email to the console.
14
+ *
15
+ * @param email - The email the library wants to send.
16
+ * @throws When NODE_ENV is "production", so it can't be shipped by accident.
17
+ */
18
+ async send(email) {
19
+ if (process.env.NODE_ENV === constants_1.PRODUCTION_ENVIRONMENT) {
20
+ throw new Error('ConsoleEmailSender must not be used in production');
21
+ }
22
+ this.logger.log(`[${email.type}] to ${email.to}: ${JSON.stringify(email)}`);
23
+ }
24
+ }
25
+ exports.ConsoleEmailSender = ConsoleEmailSender;
26
+ //# sourceMappingURL=console-email-sender.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console-email-sender.js","sourceRoot":"","sources":["../../src/integrations/console-email-sender.ts"],"names":[],"mappings":";;;AAAA,2CAAwC;AAExC,2CAAkE;AAElE;;;GAGG;AACH,MAAa,kBAAkB;IACZ,MAAM,GAAG,IAAI,eAAM,CAAC,uBAAW,CAAC,kBAAkB,CAAC,CAAC;IAErE;;;;;OAKG;IACH,KAAK,CAAC,IAAI,CAAC,KAAgB;QACzB,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,kCAAsB,EAAE,CAAC;YACpD,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;QACvE,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,QAAQ,KAAK,CAAC,EAAE,KAAK,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC9E,CAAC;CACF;AAfD,gDAeC"}
@@ -0,0 +1,28 @@
1
+ import { SmsSender } from '../auth-options.js';
2
+ export interface Msg91Options {
3
+ /** Your MSG91 auth key (Dashboard -> API -> Configure). Keep it in an environment variable. */
4
+ authKey: string;
5
+ /** The DLT-approved SMS template id from MSG91 (Flow / template id). */
6
+ templateId: string;
7
+ /** The variable your template uses for the code, e.g. "otp" for "Your code is ##otp##". Default "otp". */
8
+ codeVariableName?: string;
9
+ }
10
+ /**
11
+ * Ready-made SMS sender for MSG91 (cheapest for Indian numbers). Plug it in with:
12
+ *
13
+ * smsSender: new Msg91SmsSender({ authKey: process.env.MSG91_AUTH_KEY!, templateId: '...' })
14
+ *
15
+ * For any other provider (Twilio, AWS SNS...), write a class with the same `sendCode` method.
16
+ */
17
+ export declare class Msg91SmsSender implements SmsSender {
18
+ private readonly msg91;
19
+ constructor(msg91: Msg91Options);
20
+ /**
21
+ * Sends a one-time code through MSG91's Flow API.
22
+ *
23
+ * @param phoneNumber - The E.164 phone number, e.g. "+919876543210".
24
+ * @param code - The code to send.
25
+ * @throws When MSG91 refuses the request or doesn't answer in time.
26
+ */
27
+ sendCode(phoneNumber: string, code: string): Promise<void>;
28
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Msg91SmsSender = void 0;
4
+ const constants_1 = require("../constants.js");
5
+ /**
6
+ * Ready-made SMS sender for MSG91 (cheapest for Indian numbers). Plug it in with:
7
+ *
8
+ * smsSender: new Msg91SmsSender({ authKey: process.env.MSG91_AUTH_KEY!, templateId: '...' })
9
+ *
10
+ * For any other provider (Twilio, AWS SNS...), write a class with the same `sendCode` method.
11
+ */
12
+ class Msg91SmsSender {
13
+ msg91;
14
+ constructor(msg91) {
15
+ this.msg91 = msg91;
16
+ }
17
+ /**
18
+ * Sends a one-time code through MSG91's Flow API.
19
+ *
20
+ * @param phoneNumber - The E.164 phone number, e.g. "+919876543210".
21
+ * @param code - The code to send.
22
+ * @throws When MSG91 refuses the request or doesn't answer in time.
23
+ */
24
+ async sendCode(phoneNumber, code) {
25
+ const response = await fetch(constants_1.MSG91_FLOW_API_URL, {
26
+ method: constants_1.HTTP_METHOD.post,
27
+ signal: AbortSignal.timeout(constants_1.MSG91_REQUEST_TIMEOUT_MS),
28
+ headers: {
29
+ [constants_1.MSG91_API.authKeyHeader]: this.msg91.authKey,
30
+ [constants_1.HTTP_HEADER.contentType]: constants_1.JSON_CONTENT_TYPE,
31
+ [constants_1.HTTP_HEADER.accept]: constants_1.JSON_CONTENT_TYPE,
32
+ },
33
+ body: JSON.stringify({
34
+ template_id: this.msg91.templateId,
35
+ // MSG91 wants the number with country code but without "+", e.g. 919876543210.
36
+ recipients: [{ mobiles: phoneNumber.replace(constants_1.LEADING_PLUS_PATTERN, ''), [this.msg91.codeVariableName ?? constants_1.MSG91_API.defaultCodeVariableName]: code }],
37
+ }),
38
+ });
39
+ const result = (await response.json().catch(() => ({})));
40
+ if (!response.ok || result.type === constants_1.MSG91_API.errorResponseType) {
41
+ throw new Error(`MSG91 refused the SMS: ${result.message ?? `HTTP ${response.status}`}`);
42
+ }
43
+ }
44
+ }
45
+ exports.Msg91SmsSender = Msg91SmsSender;
46
+ //# sourceMappingURL=msg91-sms-sender.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"msg91-sms-sender.js","sourceRoot":"","sources":["../../src/integrations/msg91-sms-sender.ts"],"names":[],"mappings":";;;AACA,2CAQqB;AAWrB;;;;;;GAMG;AACH,MAAa,cAAc;IACI;IAA7B,YAA6B,KAAmB;QAAnB,UAAK,GAAL,KAAK,CAAc;IAAG,CAAC;IAEpD;;;;;;OAMG;IACH,KAAK,CAAC,QAAQ,CAAC,WAAmB,EAAE,IAAY;QAC9C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,8BAAkB,EAAE;YAC/C,MAAM,EAAE,uBAAW,CAAC,IAAI;YACxB,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,oCAAwB,CAAC;YACrD,OAAO,EAAE;gBACP,CAAC,qBAAS,CAAC,aAAa,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO;gBAC7C,CAAC,uBAAW,CAAC,WAAW,CAAC,EAAE,6BAAiB;gBAC5C,CAAC,uBAAW,CAAC,MAAM,CAAC,EAAE,6BAAiB;aACxC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU;gBAClC,+EAA+E;gBAC/E,UAAU,EAAE,CAAC,EAAE,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC,gCAAoB,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,IAAI,qBAAS,CAAC,uBAAuB,CAAC,EAAE,IAAI,EAAE,CAAC;aACnJ,CAAC;SACH,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAwC,CAAC;QAChG,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,MAAM,CAAC,IAAI,KAAK,qBAAS,CAAC,iBAAiB,EAAE,CAAC;YAChE,MAAM,IAAI,KAAK,CAAC,0BAA0B,MAAM,CAAC,OAAO,IAAI,QAAQ,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC3F,CAAC;IACH,CAAC;CACF;AA9BD,wCA8BC"}
package/docs/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # Documentation
2
+
3
+ @techelusive/nest-auth is a NestJS module that gives any backend a complete, secure authentication system: sign-up, sign-in (eight methods), two-factor, sessions, roles, organizations, API keys, webhooks and an admin API. It stores everything in **your app's own PostgreSQL database**, and your apps build their own UI on top of its JSON API.
4
+
5
+ ## Start here
6
+
7
+ | If you want to... | Read |
8
+ |---|---|
9
+ | Add auth to a NestJS app in 15 minutes | [Getting started](getting-started.md) |
10
+ | See every option and setting | [Configuration](configuration.md) |
11
+ | Build the sign-up / sign-in screens | [Sign-in flows](sign-in-flows.md) and [Client integration](client-integration.md) |
12
+ | See every endpoint's exact request and response JSON | [Endpoints](endpoints/README.md) |
13
+ | Look up an endpoint at a glance | [API reference](api-reference.md) |
14
+ | Handle an error code | [Error codes](error-codes.md) |
15
+ | Protect your own routes | [Protecting routes](protecting-routes.md) |
16
+ | Add teams / workspaces | [Organizations](organizations.md) |
17
+ | Manage users, API keys and webhooks | [Admin, API keys and webhooks](admin-api-keys-webhooks.md) |
18
+ | React to sign-ups and other events | [Events](events.md) |
19
+ | Test every flow by hand (Postman, Swagger, dashboard) | [Manual testing](manual-testing.md) |
20
+ | Learn how the code works, flow by flow (for contributors) | [Code walkthrough](code-walkthrough.md) |
21
+ | Go live | [Production checklist](production-checklist.md) |
22
+ | Understand the security design | [Security](security.md) |
23
+ | Understand the internals or contribute | [Architecture](architecture.md) |
24
+
25
+ ## Concepts in one minute
26
+
27
+ - **User.** One row per person. Has an email and/or phone number, roles (e.g. `user`, `admin`) and a status (`PENDING_VERIFICATION`, `ACTIVE`, `SUSPENDED`, `DEACTIVATED`, `DELETED`).
28
+ - **Session.** One per signed-in device. Signing out ends the session.
29
+ - **Access token.** A short-lived signed JWT (15 minutes by default) sent as `Authorization: Bearer ...` on every request. Any service can verify it with the public keys at `/.well-known/jwks.json`.
30
+ - **Refresh token.** A long-lived single-use token (`rt_...`). It gets a new access token when the old one expires. Reusing an old one ends the session, because reuse means it was stolen.
31
+ - **Settings.** Which features are on and how they behave. Defaults ship with the library, your code overrides them, and an admin can override both at runtime without a deploy.
32
+ - **Events.** Every important action (sign-up, password change...) is written to the audit log. It is also passed to your `onEvent` handler and sent to any webhooks.
33
+
34
+ ## Requirements
35
+
36
+ - Node.js 22+
37
+ - NestJS 11 with the Express platform
38
+ - TypeORM 0.3 and PostgreSQL 13+
39
+ - Optional: Redis (recommended with more than one server), AWS KMS (recommended in production)
@@ -0,0 +1,147 @@
1
+ # Admin, API keys and webhooks
2
+
3
+ Everything under `/auth/admin` needs a user holding one of `settings.admin.adminRoles` (default `["admin"]`). The session is checked live, so a removed admin loses access at once.
4
+
5
+ ## The first admin
6
+
7
+ No one is an admin after installation. Make the first one from a one-off script or a database console:
8
+
9
+ ```ts
10
+ // scripts/make-admin.ts
11
+ const users = app.get(UsersService);
12
+ const user = await users.findUserByEmail('founder@myapp.com');
13
+ await users.setRoles(user!.id, [...user!.roles, 'admin'], user!.id, SYSTEM_REQUEST);
14
+ ```
15
+
16
+ ```sql
17
+ -- or directly in SQL
18
+ UPDATE auth_users SET roles = array_append(roles, 'admin') WHERE email = 'founder@myapp.com';
19
+ ```
20
+
21
+ The role appears in the user's next access token, so sign in again or wait for a refresh. From then on, admins manage roles through `PUT /auth/admin/users/:id/roles`.
22
+
23
+ ## Managing users
24
+
25
+ | Task | Request |
26
+ |---|---|
27
+ | Find users | `GET /auth/admin/users?search=asha&status=ACTIVE&role=seller&page=1&pageSize=50` (search matches email, phone and names; deleted users are hidden unless `status=DELETED`) |
28
+ | See one user | `GET /auth/admin/users/:id` returns profile, suspension reason, consent times, sign-in methods and active devices |
29
+ | Change roles | `PUT /auth/admin/users/:id/roles { "roles": ["user", "seller"] }` (replaces the list) |
30
+ | Suspend | `POST /auth/admin/users/:id/suspend { "reason": "Chargeback fraud, ticket 4411" }` signs them out everywhere |
31
+ | Lift suspension | `POST /auth/admin/users/:id/unsuspend` |
32
+ | Verify email by hand | `POST /auth/admin/users/:id/verify-email` |
33
+ | Reset 2FA | `POST /auth/admin/users/:id/reset-2fa`, only after confirming identity through support |
34
+ | Sign out everywhere | `POST /auth/admin/users/:id/logout-all` |
35
+ | Delete | `DELETE /auth/admin/users/:id` wipes personal data, permanently |
36
+
37
+ Every admin action is written to the audit log with `performedBy: "admin:<adminUserId>"`.
38
+
39
+ ## Audit log
40
+
41
+ ```http
42
+ GET /auth/admin/audit-log?userId=5f0c...&eventName=user.sign_in_failed&page=1
43
+ ```
44
+
45
+ Entries: `eventName`, `userId`, `performedBy`, `ipAddress`, `userAgent`, `details`, `createdAt`. The log never contains passwords, tokens or codes. It records sign-ins, failures (with a reason), password changes, 2FA changes, admin actions, settings changes and refresh-token reuse. See [Events](events.md) for the list.
46
+
47
+ The table grows forever. Prune it on a schedule that matches your retention policy, for example:
48
+
49
+ ```sql
50
+ DELETE FROM auth_audit_logs WHERE created_at < now() - interval '1 year';
51
+ ```
52
+
53
+ ## Runtime settings
54
+
55
+ ```http
56
+ GET /auth/admin/settings → settings in force
57
+ PATCH /auth/admin/settings { "emailOtp": { "enabled": true } } → change some
58
+ DELETE /auth/admin/settings → back to the code settings
59
+ ```
60
+
61
+ See [Configuration](configuration.md#settings) for every setting and its limits.
62
+
63
+ ## Signing keys
64
+
65
+ Access tokens are signed with an ES256 key that the library creates on first start, encrypts and stores. To rotate (every few months, or immediately if you suspect a leak):
66
+
67
+ ```http
68
+ POST /auth/admin/signing-keys/rotate
69
+ ```
70
+
71
+ New tokens use the new key right away. The old public key stays in `/.well-known/jwks.json` for 2 days, so tokens it signed keep working until they expire. Every server picks up the change within a minute.
72
+
73
+ ## API keys
74
+
75
+ API keys let other servers call routes marked `@ApiKeyScopes(...)`.
76
+
77
+ ```http
78
+ POST /auth/admin/api-keys
79
+ { "name": "Partner: QuickBooks sync", "scopes": ["orders:read", "invoices:write"], "expiresAt": "2027-06-30T00:00:00Z" }
80
+ → { "apiKey": "ak_3Fx9...", "details": { "id": "...", "keyPreview": "ak_3Fx9Lm", ... } }
81
+ ```
82
+
83
+ - **Shown once:** `apiKey` appears only in this response. Store it in the calling server's secret manager. Only its hash is kept.
84
+ - **Scopes:** lowercase, like `orders:read`, `invoices:write` or `admin`. Define your own vocabulary.
85
+ - **`organizationId`** (optional) ties the key to one organization.
86
+ - **Listing and revoking:** `GET /auth/admin/api-keys` lists keys (never the secret). `DELETE /auth/admin/api-keys/:id` revokes immediately.
87
+ - **Usage:** `lastUsedAt` shows recent use (updated at most once a minute).
88
+
89
+ ## Webhooks
90
+
91
+ Webhooks send auth [events](events.md) to other systems as HTTP POSTs: your CRM, analytics, a Slack bot, a separate service.
92
+
93
+ ### Register
94
+
95
+ ```http
96
+ POST /auth/admin/webhooks
97
+ { "url": "https://hooks.myapp.com/auth", "eventNames": ["user.created", "user.deleted"], "description": "CRM sync" }
98
+ → { "webhook": { "id": "..." }, "signingSecret": "whsec_..." }
99
+ ```
100
+
101
+ - **`eventNames`:** an empty list means every event.
102
+ - **`signingSecret`:** shown once. `POST .../rotate-secret` issues a new one, and the old one stops working immediately.
103
+ - **URL rules:** the URL must be **public https**. Addresses on private networks, loopback, link-local (including cloud metadata `169.254.169.254`) and similar are refused, both when saving and before every delivery. In development, `http://localhost` is allowed.
104
+
105
+ ### Delivery
106
+
107
+ ```http
108
+ POST https://hooks.myapp.com/auth
109
+ Content-Type: application/json
110
+ X-Techelusive-Event: user.created
111
+ X-Techelusive-Delivery: 7d0b...
112
+ X-Techelusive-Signature: t=1792600000,v1=5257a869e7ec...
113
+
114
+ { "id": "7d0b...", "name": "user.created", "userId": "5f0c...", "data": { "status": "ACTIVE" }, "occurredAt": "2026-10-20T05:00:00.000Z" }
115
+ ```
116
+
117
+ - **Success:** reply with any 2xx status within 10 seconds. Redirects are not followed.
118
+ - **Retries:** other answers and timeouts are retried after 1 min, 5 min, 30 min, 2 h, 6 h, 12 h and 24 h. After that the delivery is marked `failed`.
119
+ - **Duplicates:** deliveries can arrive more than once (e.g. after a timeout), so use the `id` / `X-Techelusive-Delivery` value to ignore duplicates.
120
+ - **Order:** not guaranteed. Use `occurredAt` if order matters.
121
+
122
+ ### Verifying the signature (receiving side)
123
+
124
+ ```ts
125
+ import express from 'express';
126
+ import { verifyWebhookSignature } from '@techelusive/nest-auth';
127
+
128
+ app.post('/auth', express.raw({ type: 'application/json' }), (req, res) => {
129
+ const rawBody = req.body.toString('utf8'); // the exact bytes received
130
+ const isGenuine = verifyWebhookSignature(process.env.WEBHOOK_SECRET!, rawBody, req.header('X-Techelusive-Signature'));
131
+ if (!isGenuine) return res.status(400).end();
132
+ const event = JSON.parse(rawBody);
133
+ // ... handle event ...
134
+ res.status(204).end();
135
+ });
136
+ ```
137
+
138
+ The check rejects bodies that were changed, the wrong secret, and deliveries older than 5 minutes (replays). In another language, compute `HMAC-SHA256(secret, "<t>.<rawBody>")` in hex, compare it with `v1` in constant time, and check that `t` is recent.
139
+
140
+ ### Debugging
141
+
142
+ | Request | Purpose |
143
+ |---|---|
144
+ | `POST /auth/admin/webhooks/:id/test` | Queue a `webhook.test` delivery |
145
+ | `GET /auth/admin/webhooks/:id/deliveries` | Recent deliveries with `status`, `attemptCount`, `lastResponseStatus`, `lastError` |
146
+ | `POST /auth/admin/webhooks/:id/deliveries/:deliveryId/retry` | Send again now |
147
+ | `PATCH /auth/admin/webhooks/:id { "isEnabled": false }` | Pause |
@@ -0,0 +1,175 @@
1
+ # API reference
2
+
3
+ A one-page overview of every endpoint. For the **exact request and response JSON** of each one, see [Endpoints](endpoints/README.md).
4
+
5
+ ## Conventions
6
+
7
+ - **Base path:** all routes are under `/auth`, except `GET /.well-known/jwks.json`.
8
+ - **Content type:** request and response bodies are JSON. Unknown body fields are **rejected** (`VALIDATION_ERROR`), which stops clients from sneaking in fields such as `roles`.
9
+ - **Success:** every success response has `"success": true`.
10
+ - **Errors:** every error looks like `{ "success": false, "code": "...", "message": "..." }`, sometimes with extra fields. See [Error codes](error-codes.md).
11
+ - **Auth column:**
12
+ - *Public:* no token needed.
13
+ - *User:* `Authorization: Bearer <accessToken>`.
14
+ - *User + live:* also checks in the database that the session is still active (sensitive actions).
15
+ - *Admin:* a user with a role in `settings.admin.adminRoles`, checked live.
16
+ - **Rate limits:** a limited request returns `429 TOO_MANY_REQUESTS` with `retryAfterSeconds` and a `Retry-After` header.
17
+ - **Sign-in result:** "→ sign-in result" means the response is `signed_in` or `two_factor_required`, see [Sign-in flows](sign-in-flows.md#every-sign-in-ends-the-same-way).
18
+
19
+ ## Email + password
20
+
21
+ | Method | Path | Auth | Body | Response |
22
+ |---|---|---|---|---|
23
+ | POST | `/auth/register` | Public | `email`, `password`, `firstName?`, `lastName?`, `phoneNumber?`, `acceptTerms?`, `acceptPrivacyPolicy?` | `201` `{ status: "verification_required", message, pendingVerifications }` or sign-in result |
24
+ | POST | `/auth/login` | Public | `email`, `password` | sign-in result |
25
+ | POST | `/auth/email/send-verification` | Public | `email` | `{ message }`, always |
26
+ | POST | `/auth/email/verify` | Public | `token` | `{ message, status, pendingVerifications }` |
27
+ | POST | `/auth/password/forgot` | Public | `email` | `{ message }`, always |
28
+ | POST | `/auth/password/reset` | Public | `token`, `newPassword` | `{ message }` |
29
+ | POST | `/auth/password/change` | User | `currentPassword?`, `newPassword` | `{ message }` |
30
+
31
+ ## Passwordless
32
+
33
+ | Method | Path | Auth | Body | Response |
34
+ |---|---|---|---|---|
35
+ | POST | `/auth/email/send-otp` | Public | `email` | `{ message }`, always |
36
+ | POST | `/auth/email/verify-otp` | Public | `email`, `code`, sign-up details\* | sign-in result |
37
+ | POST | `/auth/magic-link/send` | Public | `email` | `{ message }`, always |
38
+ | POST | `/auth/magic-link/verify` | Public | `token`, sign-up details\* | sign-in result |
39
+ | POST | `/auth/phone/send-otp` | Public | `phoneNumber` | `{ message }`, always |
40
+ | POST | `/auth/phone/verify-otp` | Public | `phoneNumber`, `code`, sign-up details\* | sign-in result |
41
+
42
+ \* Sign-up details: `firstName?`, `lastName?`, `acceptTerms?`, `acceptPrivacyPolicy?`. They are only used when the request creates a new account.
43
+
44
+ ## Social
45
+
46
+ `:provider` is `google`, `apple` or `facebook`.
47
+
48
+ | Method | Path | Auth | Body | Response |
49
+ |---|---|---|---|---|
50
+ | POST | `/auth/social/:provider` | Public | `token`, `nonce?`, sign-up details\* | sign-in result |
51
+ | POST | `/auth/social/:provider/link` | User + live | `token`, `nonce?` | `{}` |
52
+ | DELETE | `/auth/social/:provider` | User + live | none | `{}` |
53
+
54
+ ## Passkeys
55
+
56
+ | Method | Path | Auth | Body | Response |
57
+ |---|---|---|---|---|
58
+ | POST | `/auth/passkeys/register/options` | User + live | none | `{ challengeToken, options }` |
59
+ | POST | `/auth/passkeys/register/verify` | User + live | `challengeToken`, `response`, `name?` | `{ passkey }` |
60
+ | POST | `/auth/passkeys/sign-in/options` | Public | none | `{ challengeToken, options }` |
61
+ | POST | `/auth/passkeys/sign-in/verify` | Public | `challengeToken`, `response` | sign-in result |
62
+ | GET | `/auth/passkeys` | User | none | `{ passkeys: [{ id, name, isBackedUp, createdAt, lastUsedAt }] }` |
63
+ | PATCH | `/auth/passkeys/:id` | User | `name` | `{}` |
64
+ | DELETE | `/auth/passkeys/:id` | User + live | none | `{}` |
65
+
66
+ ## Two-factor
67
+
68
+ | Method | Path | Auth | Body | Response |
69
+ |---|---|---|---|---|
70
+ | GET | `/auth/2fa` | User | none | `{ isEnabled, remainingBackupCodes }` |
71
+ | POST | `/auth/2fa/setup` | User + live | none | `{ secret, authenticatorAppUrl }` |
72
+ | POST | `/auth/2fa/enable` | User + live | `code` | `{ backupCodes }` |
73
+ | POST | `/auth/2fa/disable` | User + live | `code` | `{}` |
74
+ | POST | `/auth/2fa/backup-codes` | User + live | `code` | `{ backupCodes }` |
75
+ | POST | `/auth/2fa/verify` | Public | `challengeToken`, `code` | `signed_in` result |
76
+
77
+ ## Account and sessions
78
+
79
+ | Method | Path | Auth | Body | Response |
80
+ |---|---|---|---|---|
81
+ | POST | `/auth/refresh` | Public | `refreshToken` (omit in cookie mode) | `{ accessToken, expiresIn, refreshToken, refreshTokenExpiresAt, sessionId }` |
82
+ | POST | `/auth/logout` | User | none | `{ message }` |
83
+ | POST | `/auth/logout-all` | User | none | `{ message, endedSessions }` |
84
+ | GET | `/auth/me` | User + live | none | `{ user }` |
85
+ | PATCH | `/auth/me` | User + live | `firstName?`, `lastName?`, `metadata?` | `{ user }` |
86
+ | DELETE | `/auth/me` | User + live | none | `{ message }` |
87
+ | GET | `/auth/me/export` | User + live | none | `{ exportedAt, profile, signInMethods, linkedAccounts, passkeys, devices, organizations, securityHistory }` |
88
+ | POST | `/auth/email/change` | User + live | `newEmail`, `currentPassword?` | `{ message }` |
89
+ | POST | `/auth/email/change/confirm` | Public | `token` | `{ message, user }` |
90
+ | GET | `/auth/health` | Public | none | `{ status, checks: { database, redis } }` (503 when unhealthy) |
91
+ | GET | `/auth/sign-in-methods` | User | none | `{ signInMethods: { hasPassword, canUseEmailCode, canUsePhoneCode, socialAccounts, passkeyCount } }` |
92
+ | GET | `/auth/sessions` | User | none | `{ sessions: [{ id, isCurrentDevice, signInMethod, ipAddress, userAgent, createdAt, lastUsedAt }] }` |
93
+ | DELETE | `/auth/sessions/:id` | User | none | `{}` |
94
+ | POST | `/auth/deactivate` | User + live | none | `{ message }` |
95
+ | POST | `/auth/reactivate` | Public | `reactivationToken` | sign-in result |
96
+
97
+ ### The user object
98
+
99
+ ```jsonc
100
+ {
101
+ "id": "5f0c...",
102
+ "email": "asha@example.com", // null for phone-only users
103
+ "isEmailVerified": true,
104
+ "phoneNumber": "+919876543210", // null if none
105
+ "isPhoneVerified": false,
106
+ "firstName": "Asha",
107
+ "lastName": "Rao",
108
+ "roles": ["user"],
109
+ "status": "ACTIVE", // PENDING_VERIFICATION | ACTIVE | SUSPENDED | DEACTIVATED | DELETED
110
+ "pendingVerifications": [], // ["email"] / ["phone"] when not yet active
111
+ "onboardingCompleted": false,
112
+ "isTwoFactorEnabled": false,
113
+ "metadata": {}, // your app's own fields
114
+ "lastSignedInAt": "2026-10-20T05:00:00.000Z",
115
+ "createdAt": "2026-10-01T09:00:00.000Z"
116
+ }
117
+ ```
118
+
119
+ ## Organizations
120
+
121
+ All need a signed-in user, and roles are checked per organization. See [Organizations](organizations.md).
122
+
123
+ | Method | Path | Minimum role | Body |
124
+ |---|---|---|---|
125
+ | GET | `/auth/organizations` | none | none |
126
+ | POST | `/auth/organizations` | none | `name`, `slug` |
127
+ | POST | `/auth/organizations/switch` | member | `organizationId` (or `null`) → `{ accessToken, expiresIn, organizationId }` |
128
+ | POST | `/auth/organizations/invitations/accept` | none | `token` |
129
+ | GET | `/auth/organizations/:id` | member | none |
130
+ | PATCH | `/auth/organizations/:id` | admin | `name?`, `slug?`, `metadata?` |
131
+ | DELETE | `/auth/organizations/:id` | owner | none |
132
+ | GET | `/auth/organizations/:id/members` | member | none |
133
+ | PATCH | `/auth/organizations/:id/members/:userId` | admin\*\* | `role` |
134
+ | DELETE | `/auth/organizations/:id/members/:userId` | admin\*\*, or self | none |
135
+ | GET | `/auth/organizations/:id/invitations` | admin | none |
136
+ | POST | `/auth/organizations/:id/invitations` | admin\*\* | `email`, `role` |
137
+ | DELETE | `/auth/organizations/:id/invitations/:invitationId` | admin | none |
138
+
139
+ \*\* Anything that makes, changes or removes an **owner** needs an owner.
140
+
141
+ ## Admin
142
+
143
+ All need an admin. See [Admin, API keys and webhooks](admin-api-keys-webhooks.md).
144
+
145
+ | Method | Path | Body / query |
146
+ |---|---|---|
147
+ | GET | `/auth/admin/users` | `?search=&status=&role=&page=&pageSize=` |
148
+ | GET | `/auth/admin/users/:id` | none |
149
+ | PATCH | `/auth/admin/users/:id` | `firstName?`, `lastName?`, `metadata?` |
150
+ | PUT | `/auth/admin/users/:id/roles` | `roles` |
151
+ | POST | `/auth/admin/users/:id/suspend` | `reason` |
152
+ | POST | `/auth/admin/users/:id/unsuspend` | none |
153
+ | POST | `/auth/admin/users/:id/verify-email` | none |
154
+ | POST | `/auth/admin/users/:id/reset-2fa` | none |
155
+ | POST | `/auth/admin/users/:id/logout-all` | none |
156
+ | DELETE | `/auth/admin/users/:id` | none |
157
+ | GET / PATCH / DELETE | `/auth/admin/settings` | PATCH: partial settings |
158
+ | GET | `/auth/admin/audit-log` | `?userId=&eventName=&page=&pageSize=` |
159
+ | GET | `/auth/admin/stats` | none |
160
+ | POST | `/auth/admin/maintenance/cleanup` | none |
161
+ | POST | `/auth/admin/signing-keys/rotate` | none |
162
+ | GET / POST | `/auth/admin/api-keys` | POST: `name`, `scopes`, `organizationId?`, `expiresAt?` |
163
+ | DELETE | `/auth/admin/api-keys/:id` | none |
164
+ | GET / POST | `/auth/admin/webhooks` | POST: `url`, `eventNames?`, `description?`, `isEnabled?` |
165
+ | PATCH / DELETE | `/auth/admin/webhooks/:id` | PATCH: same fields, all optional |
166
+ | POST | `/auth/admin/webhooks/:id/rotate-secret` | none |
167
+ | POST | `/auth/admin/webhooks/:id/test` | none |
168
+ | GET | `/auth/admin/webhooks/:id/deliveries` | `?page=&pageSize=` |
169
+ | POST | `/auth/admin/webhooks/:id/deliveries/:deliveryId/retry` | none |
170
+
171
+ ## Public keys
172
+
173
+ | Method | Path | Auth | Response |
174
+ |---|---|---|---|
175
+ | GET | `/.well-known/jwks.json` | Public | `{ keys: [...] }`, the ES256 public keys that verify access tokens. Cached 5 minutes. |