@techelusive/nest-auth 0.0.0-stage → 0.2.1

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 +71 -0
  2. package/LICENSE +21 -0
  3. package/README.md +204 -2
  4. package/api/openapi.json +4399 -0
  5. package/api/techelusive-authentication.postman_collection.json +3178 -0
  6. package/dist/auth-options.d.ts +156 -0
  7. package/dist/auth-options.js +3 -0
  8. package/dist/auth-options.js.map +1 -0
  9. package/dist/auth-options.validation.d.ts +9 -0
  10. package/dist/auth-options.validation.js +74 -0
  11. package/dist/auth-options.validation.js.map +1 -0
  12. package/dist/auth.module.d.ts +38 -0
  13. package/dist/auth.module.js +173 -0
  14. package/dist/auth.module.js.map +1 -0
  15. package/dist/common/auth-error.d.ts +16 -0
  16. package/dist/common/auth-error.js +23 -0
  17. package/dist/common/auth-error.js.map +1 -0
  18. package/dist/common/auth-exception.filter.d.ts +24 -0
  19. package/dist/common/auth-exception.filter.js +66 -0
  20. package/dist/common/auth-exception.filter.js.map +1 -0
  21. package/dist/common/crypto/jwt.d.ts +89 -0
  22. package/dist/common/crypto/jwt.js +144 -0
  23. package/dist/common/crypto/jwt.js.map +1 -0
  24. package/dist/common/crypto/random-secrets.d.ts +78 -0
  25. package/dist/common/crypto/random-secrets.js +113 -0
  26. package/dist/common/crypto/random-secrets.js.map +1 -0
  27. package/dist/common/crypto/remote-public-keys.d.ts +49 -0
  28. package/dist/common/crypto/remote-public-keys.js +105 -0
  29. package/dist/common/crypto/remote-public-keys.js.map +1 -0
  30. package/dist/common/crypto/totp.d.ts +68 -0
  31. package/dist/common/crypto/totp.js +148 -0
  32. package/dist/common/crypto/totp.js.map +1 -0
  33. package/dist/common/encryption.service.d.ts +36 -0
  34. package/dist/common/encryption.service.js +111 -0
  35. package/dist/common/encryption.service.js.map +1 -0
  36. package/dist/common/identifiers.d.ts +48 -0
  37. package/dist/common/identifiers.js +89 -0
  38. package/dist/common/identifiers.js.map +1 -0
  39. package/dist/common/network-safety.d.ts +19 -0
  40. package/dist/common/network-safety.js +72 -0
  41. package/dist/common/network-safety.js.map +1 -0
  42. package/dist/common/rate-limiter.service.d.ts +63 -0
  43. package/dist/common/rate-limiter.service.js +158 -0
  44. package/dist/common/rate-limiter.service.js.map +1 -0
  45. package/dist/common/refresh-token-cookie.d.ts +78 -0
  46. package/dist/common/refresh-token-cookie.js +185 -0
  47. package/dist/common/refresh-token-cookie.js.map +1 -0
  48. package/dist/common/request-context.d.ts +14 -0
  49. package/dist/common/request-context.js +22 -0
  50. package/dist/common/request-context.js.map +1 -0
  51. package/dist/common/strict-validation.pipe.d.ts +8 -0
  52. package/dist/common/strict-validation.pipe.js +16 -0
  53. package/dist/common/strict-validation.pipe.js.map +1 -0
  54. package/dist/common/time.d.ts +15 -0
  55. package/dist/common/time.js +34 -0
  56. package/dist/common/time.js.map +1 -0
  57. package/dist/constants.d.ts +1326 -0
  58. package/dist/constants.js +1142 -0
  59. package/dist/constants.js.map +1 -0
  60. package/dist/database/create-auth-tables.migration.d.ts +26 -0
  61. package/dist/database/create-auth-tables.migration.js +291 -0
  62. package/dist/database/create-auth-tables.migration.js.map +1 -0
  63. package/dist/database/email-change-and-retention.migration.d.ts +25 -0
  64. package/dist/database/email-change-and-retention.migration.js +54 -0
  65. package/dist/database/email-change-and-retention.migration.js.map +1 -0
  66. package/dist/database/entities/api-key.entity.d.ts +17 -0
  67. package/dist/database/entities/api-key.entity.js +80 -0
  68. package/dist/database/entities/api-key.entity.js.map +1 -0
  69. package/dist/database/entities/audit-log.entity.d.ts +13 -0
  70. package/dist/database/entities/audit-log.entity.js +64 -0
  71. package/dist/database/entities/audit-log.entity.js.map +1 -0
  72. package/dist/database/entities/backup-code.entity.d.ts +9 -0
  73. package/dist/database/entities/backup-code.entity.js +52 -0
  74. package/dist/database/entities/backup-code.entity.js.map +1 -0
  75. package/dist/database/entities/index.d.ts +43 -0
  76. package/dist/database/entities/index.js +82 -0
  77. package/dist/database/entities/index.js.map +1 -0
  78. package/dist/database/entities/json-object.d.ts +12 -0
  79. package/dist/database/entities/json-object.js +3 -0
  80. package/dist/database/entities/json-object.js.map +1 -0
  81. package/dist/database/entities/link-token.entity.d.ts +15 -0
  82. package/dist/database/entities/link-token.entity.js +64 -0
  83. package/dist/database/entities/link-token.entity.js.map +1 -0
  84. package/dist/database/entities/one-time-code.entity.d.ts +16 -0
  85. package/dist/database/entities/one-time-code.entity.js +69 -0
  86. package/dist/database/entities/one-time-code.entity.js.map +1 -0
  87. package/dist/database/entities/organization-invitation.entity.d.ts +14 -0
  88. package/dist/database/entities/organization-invitation.entity.js +73 -0
  89. package/dist/database/entities/organization-invitation.entity.js.map +1 -0
  90. package/dist/database/entities/organization-member.entity.d.ts +9 -0
  91. package/dist/database/entities/organization-member.entity.js +48 -0
  92. package/dist/database/entities/organization-member.entity.js.map +1 -0
  93. package/dist/database/entities/organization.entity.d.ts +12 -0
  94. package/dist/database/entities/organization.entity.js +58 -0
  95. package/dist/database/entities/organization.entity.js.map +1 -0
  96. package/dist/database/entities/passkey.entity.d.ts +19 -0
  97. package/dist/database/entities/passkey.entity.js +78 -0
  98. package/dist/database/entities/passkey.entity.js.map +1 -0
  99. package/dist/database/entities/password.entity.d.ts +6 -0
  100. package/dist/database/entities/password.entity.js +36 -0
  101. package/dist/database/entities/password.entity.js.map +1 -0
  102. package/dist/database/entities/refresh-token.entity.d.ts +9 -0
  103. package/dist/database/entities/refresh-token.entity.js +53 -0
  104. package/dist/database/entities/refresh-token.entity.js.map +1 -0
  105. package/dist/database/entities/session.entity.d.ts +20 -0
  106. package/dist/database/entities/session.entity.js +87 -0
  107. package/dist/database/entities/session.entity.js.map +1 -0
  108. package/dist/database/entities/settings.entity.d.ts +7 -0
  109. package/dist/database/entities/settings.entity.js +41 -0
  110. package/dist/database/entities/settings.entity.js.map +1 -0
  111. package/dist/database/entities/sign-in-challenge.entity.d.ts +23 -0
  112. package/dist/database/entities/sign-in-challenge.entity.js +80 -0
  113. package/dist/database/entities/sign-in-challenge.entity.js.map +1 -0
  114. package/dist/database/entities/signing-key.entity.d.ts +11 -0
  115. package/dist/database/entities/signing-key.entity.js +54 -0
  116. package/dist/database/entities/signing-key.entity.js.map +1 -0
  117. package/dist/database/entities/social-account.entity.d.ts +13 -0
  118. package/dist/database/entities/social-account.entity.js +54 -0
  119. package/dist/database/entities/social-account.entity.js.map +1 -0
  120. package/dist/database/entities/two-factor-secret.entity.d.ts +10 -0
  121. package/dist/database/entities/two-factor-secret.entity.js +48 -0
  122. package/dist/database/entities/two-factor-secret.entity.js.map +1 -0
  123. package/dist/database/entities/user.entity.d.ts +34 -0
  124. package/dist/database/entities/user.entity.js +129 -0
  125. package/dist/database/entities/user.entity.js.map +1 -0
  126. package/dist/database/entities/webhook-delivery.entity.d.ts +17 -0
  127. package/dist/database/entities/webhook-delivery.entity.js +79 -0
  128. package/dist/database/entities/webhook-delivery.entity.js.map +1 -0
  129. package/dist/database/entities/webhook.entity.d.ts +12 -0
  130. package/dist/database/entities/webhook.entity.js +58 -0
  131. package/dist/database/entities/webhook.entity.js.map +1 -0
  132. package/dist/database/typeorm-row.d.ts +21 -0
  133. package/dist/database/typeorm-row.js +29 -0
  134. package/dist/database/typeorm-row.js.map +1 -0
  135. package/dist/features/account/account.controller.d.ts +259 -0
  136. package/dist/features/account/account.controller.js +372 -0
  137. package/dist/features/account/account.controller.js.map +1 -0
  138. package/dist/features/account/account.dto.d.ts +16 -0
  139. package/dist/features/account/account.dto.js +61 -0
  140. package/dist/features/account/account.dto.js.map +1 -0
  141. package/dist/features/account/data-export.service.d.ts +85 -0
  142. package/dist/features/account/data-export.service.js +125 -0
  143. package/dist/features/account/data-export.service.js.map +1 -0
  144. package/dist/features/account/health.service.d.ts +30 -0
  145. package/dist/features/account/health.service.js +59 -0
  146. package/dist/features/account/health.service.js.map +1 -0
  147. package/dist/features/admin/admin.controller.d.ts +382 -0
  148. package/dist/features/admin/admin.controller.js +623 -0
  149. package/dist/features/admin/admin.controller.js.map +1 -0
  150. package/dist/features/admin/admin.dto.d.ts +61 -0
  151. package/dist/features/admin/admin.dto.js +253 -0
  152. package/dist/features/admin/admin.dto.js.map +1 -0
  153. package/dist/features/admin/admin.service.d.ts +142 -0
  154. package/dist/features/admin/admin.service.js +227 -0
  155. package/dist/features/admin/admin.service.js.map +1 -0
  156. package/dist/features/api-keys/api-keys.service.d.ts +67 -0
  157. package/dist/features/api-keys/api-keys.service.js +144 -0
  158. package/dist/features/api-keys/api-keys.service.js.map +1 -0
  159. package/dist/features/email-change/email-change.controller.d.ts +38 -0
  160. package/dist/features/email-change/email-change.controller.js +85 -0
  161. package/dist/features/email-change/email-change.controller.js.map +1 -0
  162. package/dist/features/email-change/email-change.dto.d.ts +10 -0
  163. package/dist/features/email-change/email-change.dto.js +43 -0
  164. package/dist/features/email-change/email-change.dto.js.map +1 -0
  165. package/dist/features/email-change/email-change.service.d.ts +74 -0
  166. package/dist/features/email-change/email-change.service.js +179 -0
  167. package/dist/features/email-change/email-change.service.js.map +1 -0
  168. package/dist/features/email-links/email-verification.service.d.ts +46 -0
  169. package/dist/features/email-links/email-verification.service.js +94 -0
  170. package/dist/features/email-links/email-verification.service.js.map +1 -0
  171. package/dist/features/email-links/link-tokens.service.d.ts +44 -0
  172. package/dist/features/email-links/link-tokens.service.js +122 -0
  173. package/dist/features/email-links/link-tokens.service.js.map +1 -0
  174. package/dist/features/events/auth-events.service.d.ts +52 -0
  175. package/dist/features/events/auth-events.service.js +117 -0
  176. package/dist/features/events/auth-events.service.js.map +1 -0
  177. package/dist/features/maintenance/data-retention.service.d.ts +60 -0
  178. package/dist/features/maintenance/data-retention.service.js +182 -0
  179. package/dist/features/maintenance/data-retention.service.js.map +1 -0
  180. package/dist/features/notifications/notifications.service.d.ts +40 -0
  181. package/dist/features/notifications/notifications.service.js +94 -0
  182. package/dist/features/notifications/notifications.service.js.map +1 -0
  183. package/dist/features/one-time-codes/one-time-codes.service.d.ts +40 -0
  184. package/dist/features/one-time-codes/one-time-codes.service.js +102 -0
  185. package/dist/features/one-time-codes/one-time-codes.service.js.map +1 -0
  186. package/dist/features/organizations/organizations.controller.d.ts +220 -0
  187. package/dist/features/organizations/organizations.controller.js +337 -0
  188. package/dist/features/organizations/organizations.controller.js.map +1 -0
  189. package/dist/features/organizations/organizations.dto.d.ts +31 -0
  190. package/dist/features/organizations/organizations.dto.js +100 -0
  191. package/dist/features/organizations/organizations.dto.js.map +1 -0
  192. package/dist/features/organizations/organizations.service.d.ts +274 -0
  193. package/dist/features/organizations/organizations.service.js +481 -0
  194. package/dist/features/organizations/organizations.service.js.map +1 -0
  195. package/dist/features/passkeys/passkeys.controller.d.ts +92 -0
  196. package/dist/features/passkeys/passkeys.controller.js +183 -0
  197. package/dist/features/passkeys/passkeys.controller.js.map +1 -0
  198. package/dist/features/passkeys/passkeys.dto.d.ts +13 -0
  199. package/dist/features/passkeys/passkeys.dto.js +50 -0
  200. package/dist/features/passkeys/passkeys.dto.js.map +1 -0
  201. package/dist/features/passkeys/passkeys.service.d.ts +159 -0
  202. package/dist/features/passkeys/passkeys.service.js +350 -0
  203. package/dist/features/passkeys/passkeys.service.js.map +1 -0
  204. package/dist/features/passwordless/passwordless-auth.service.d.ts +152 -0
  205. package/dist/features/passwordless/passwordless-auth.service.js +304 -0
  206. package/dist/features/passwordless/passwordless-auth.service.js.map +1 -0
  207. package/dist/features/passwordless/passwordless.controller.d.ts +75 -0
  208. package/dist/features/passwordless/passwordless.controller.js +163 -0
  209. package/dist/features/passwordless/passwordless.controller.js.map +1 -0
  210. package/dist/features/passwordless/passwordless.dto.d.ts +29 -0
  211. package/dist/features/passwordless/passwordless.dto.js +101 -0
  212. package/dist/features/passwordless/passwordless.dto.js.map +1 -0
  213. package/dist/features/passwords/password-auth.service.d.ts +154 -0
  214. package/dist/features/passwords/password-auth.service.js +317 -0
  215. package/dist/features/passwords/password-auth.service.js.map +1 -0
  216. package/dist/features/passwords/password-policy.service.d.ts +63 -0
  217. package/dist/features/passwords/password-policy.service.js +175 -0
  218. package/dist/features/passwords/password-policy.service.js.map +1 -0
  219. package/dist/features/passwords/password.controller.d.ts +95 -0
  220. package/dist/features/passwords/password.controller.js +193 -0
  221. package/dist/features/passwords/password.controller.js.map +1 -0
  222. package/dist/features/passwords/password.dto.d.ts +36 -0
  223. package/dist/features/passwords/password.dto.js +140 -0
  224. package/dist/features/passwords/password.dto.js.map +1 -0
  225. package/dist/features/sessions/session.service.d.ts +132 -0
  226. package/dist/features/sessions/session.service.js +308 -0
  227. package/dist/features/sessions/session.service.js.map +1 -0
  228. package/dist/features/sessions/session.types.d.ts +34 -0
  229. package/dist/features/sessions/session.types.js +3 -0
  230. package/dist/features/sessions/session.types.js.map +1 -0
  231. package/dist/features/settings/settings.defaults.d.ts +2 -0
  232. package/dist/features/settings/settings.defaults.js +7 -0
  233. package/dist/features/settings/settings.defaults.js.map +1 -0
  234. package/dist/features/settings/settings.service.d.ts +44 -0
  235. package/dist/features/settings/settings.service.js +112 -0
  236. package/dist/features/settings/settings.service.js.map +1 -0
  237. package/dist/features/settings/settings.types.d.ts +133 -0
  238. package/dist/features/settings/settings.types.js +3 -0
  239. package/dist/features/settings/settings.types.js.map +1 -0
  240. package/dist/features/settings/settings.validation.d.ts +33 -0
  241. package/dist/features/settings/settings.validation.js +614 -0
  242. package/dist/features/settings/settings.validation.js.map +1 -0
  243. package/dist/features/sign-in/sign-in-challenges.service.d.ts +54 -0
  244. package/dist/features/sign-in/sign-in-challenges.service.js +104 -0
  245. package/dist/features/sign-in/sign-in-challenges.service.js.map +1 -0
  246. package/dist/features/sign-in/sign-in.service.d.ts +127 -0
  247. package/dist/features/sign-in/sign-in.service.js +248 -0
  248. package/dist/features/sign-in/sign-in.service.js.map +1 -0
  249. package/dist/features/sign-in/sign-in.types.d.ts +22 -0
  250. package/dist/features/sign-in/sign-in.types.js +3 -0
  251. package/dist/features/sign-in/sign-in.types.js.map +1 -0
  252. package/dist/features/signing-keys/jwks.controller.d.ts +17 -0
  253. package/dist/features/signing-keys/jwks.controller.js +51 -0
  254. package/dist/features/signing-keys/jwks.controller.js.map +1 -0
  255. package/dist/features/signing-keys/signing-keys.service.d.ts +67 -0
  256. package/dist/features/signing-keys/signing-keys.service.js +142 -0
  257. package/dist/features/signing-keys/signing-keys.service.js.map +1 -0
  258. package/dist/features/social/social-auth.service.d.ts +100 -0
  259. package/dist/features/social/social-auth.service.js +232 -0
  260. package/dist/features/social/social-auth.service.js.map +1 -0
  261. package/dist/features/social/social-providers.service.d.ts +97 -0
  262. package/dist/features/social/social-providers.service.js +214 -0
  263. package/dist/features/social/social-providers.service.js.map +1 -0
  264. package/dist/features/social/social.controller.d.ts +54 -0
  265. package/dist/features/social/social.controller.js +124 -0
  266. package/dist/features/social/social.controller.js.map +1 -0
  267. package/dist/features/social/social.dto.d.ts +11 -0
  268. package/dist/features/social/social.dto.js +38 -0
  269. package/dist/features/social/social.dto.js.map +1 -0
  270. package/dist/features/two-factor/two-factor.controller.d.ts +84 -0
  271. package/dist/features/two-factor/two-factor.controller.js +174 -0
  272. package/dist/features/two-factor/two-factor.controller.js.map +1 -0
  273. package/dist/features/two-factor/two-factor.dto.d.ts +10 -0
  274. package/dist/features/two-factor/two-factor.dto.js +37 -0
  275. package/dist/features/two-factor/two-factor.dto.js.map +1 -0
  276. package/dist/features/two-factor/two-factor.service.d.ts +171 -0
  277. package/dist/features/two-factor/two-factor.service.js +348 -0
  278. package/dist/features/two-factor/two-factor.service.js.map +1 -0
  279. package/dist/features/users/sign-in-methods.service.d.ts +40 -0
  280. package/dist/features/users/sign-in-methods.service.js +81 -0
  281. package/dist/features/users/sign-in-methods.service.js.map +1 -0
  282. package/dist/features/users/sign-up-rules.d.ts +12 -0
  283. package/dist/features/users/sign-up-rules.js +29 -0
  284. package/dist/features/users/sign-up-rules.js.map +1 -0
  285. package/dist/features/users/users.service.d.ts +246 -0
  286. package/dist/features/users/users.service.js +509 -0
  287. package/dist/features/users/users.service.js.map +1 -0
  288. package/dist/features/users/users.types.d.ts +24 -0
  289. package/dist/features/users/users.types.js +3 -0
  290. package/dist/features/users/users.types.js.map +1 -0
  291. package/dist/features/webhooks/webhook-delivery.worker.d.ts +55 -0
  292. package/dist/features/webhooks/webhook-delivery.worker.js +175 -0
  293. package/dist/features/webhooks/webhook-delivery.worker.js.map +1 -0
  294. package/dist/features/webhooks/webhook-signature.d.ts +28 -0
  295. package/dist/features/webhooks/webhook-signature.js +85 -0
  296. package/dist/features/webhooks/webhook-signature.js.map +1 -0
  297. package/dist/features/webhooks/webhooks.service.d.ts +144 -0
  298. package/dist/features/webhooks/webhooks.service.js +238 -0
  299. package/dist/features/webhooks/webhooks.service.js.map +1 -0
  300. package/dist/guards/auth.decorators.d.ts +65 -0
  301. package/dist/guards/auth.decorators.js +68 -0
  302. package/dist/guards/auth.decorators.js.map +1 -0
  303. package/dist/guards/auth.guard.d.ts +47 -0
  304. package/dist/guards/auth.guard.js +132 -0
  305. package/dist/guards/auth.guard.js.map +1 -0
  306. package/dist/index.d.ts +38 -0
  307. package/dist/index.js +95 -0
  308. package/dist/index.js.map +1 -0
  309. package/dist/integrations/console-email-sender.d.ts +15 -0
  310. package/dist/integrations/console-email-sender.js +26 -0
  311. package/dist/integrations/console-email-sender.js.map +1 -0
  312. package/dist/integrations/msg91-sms-sender.d.ts +28 -0
  313. package/dist/integrations/msg91-sms-sender.js +46 -0
  314. package/dist/integrations/msg91-sms-sender.js.map +1 -0
  315. package/docs/README.md +39 -0
  316. package/docs/admin-api-keys-webhooks.md +147 -0
  317. package/docs/api-reference.md +175 -0
  318. package/docs/architecture.md +119 -0
  319. package/docs/client-integration.md +192 -0
  320. package/docs/code-walkthrough.md +273 -0
  321. package/docs/configuration.md +229 -0
  322. package/docs/endpoints/README.md +151 -0
  323. package/docs/endpoints/account.md +363 -0
  324. package/docs/endpoints/admin.md +422 -0
  325. package/docs/endpoints/email-password.md +261 -0
  326. package/docs/endpoints/organizations.md +192 -0
  327. package/docs/endpoints/passkeys.md +195 -0
  328. package/docs/endpoints/passwordless.md +214 -0
  329. package/docs/endpoints/social.md +116 -0
  330. package/docs/endpoints/two-factor.md +146 -0
  331. package/docs/error-codes.md +100 -0
  332. package/docs/events.md +83 -0
  333. package/docs/getting-started.md +139 -0
  334. package/docs/manual-testing.md +215 -0
  335. package/docs/organizations.md +86 -0
  336. package/docs/production-checklist.md +60 -0
  337. package/docs/protecting-routes.md +147 -0
  338. package/docs/security.md +61 -0
  339. package/docs/sign-in-flows.md +294 -0
  340. package/package.json +92 -4
@@ -0,0 +1,192 @@
1
+ # Organizations
2
+
3
+ Needs `organizations.enabled`; otherwise `403 FEATURE_DISABLED`. Every route needs a signed-in user, and roles (`owner`, `admin`, `member`) are checked per organization. If you're not a member, the organization's routes return `404 NOT_FOUND`. Concepts are explained in [Organizations](../organizations.md).
4
+
5
+ ## Organization object
6
+
7
+ ```json
8
+ {
9
+ "id": "a1b2c3d4-0000-4000-8000-000000000001",
10
+ "name": "Acme Travels",
11
+ "slug": "acme-travels",
12
+ "metadata": {},
13
+ "createdByUserId": "5f0c8a2e-1d3b-4c5a-9e7f-0a1b2c3d4e5f",
14
+ "createdAt": "2026-10-20T06:30:00.000Z",
15
+ "updatedAt": "2026-10-20T06:30:00.000Z"
16
+ }
17
+ ```
18
+
19
+ ---
20
+
21
+ ## GET /auth/organizations
22
+
23
+ The organizations the user belongs to.
24
+
25
+ **Response `200`**
26
+
27
+ ```json
28
+ {
29
+ "success": true,
30
+ "organizations": [
31
+ { "id": "a1b2...", "name": "Acme Travels", "slug": "acme-travels", "metadata": {}, "role": "owner", "joinedAt": "2026-10-20T06:30:00.000Z" }
32
+ ]
33
+ }
34
+ ```
35
+
36
+ ## POST /auth/organizations
37
+
38
+ Creates an organization; the caller becomes its owner. Session checked live. When `organizations.allowUsersToCreate` is off, only app admins can create.
39
+
40
+ **Request**
41
+
42
+ ```json
43
+ { "name": "Acme Travels", "slug": "acme-travels" }
44
+ ```
45
+
46
+ | Field | Type | Required | Rules |
47
+ |---|---|---|---|
48
+ | `name` | string | yes | up to 100 characters |
49
+ | `slug` | string | yes | 3–50 lowercase letters, digits and dashes; can't start or end with a dash |
50
+
51
+ **Response `201`:** `{ "success": true, "organization": { ...organization object } }`
52
+
53
+ **Errors:** `409 ORGANIZATION_SLUG_TAKEN`, `403 FORBIDDEN` (users may not create), `400 VALIDATION_ERROR` (`problems: ["too many organizations"]`, 100 per user).
54
+
55
+ ## POST /auth/organizations/switch
56
+
57
+ Picks the organization this device works in. **Replace the stored access token** with the returned one; refreshes keep the organization. Session checked live.
58
+
59
+ **Request**
60
+
61
+ ```json
62
+ { "organizationId": "a1b2c3d4-0000-4000-8000-000000000001" }
63
+ ```
64
+
65
+ Send `{ "organizationId": null }` to leave organization mode.
66
+
67
+ **Response `200`**
68
+
69
+ ```json
70
+ { "success": true, "accessToken": "eyJhbGciOiJFUzI1NiIs...", "expiresIn": 900, "organizationId": "a1b2c3d4-0000-4000-8000-000000000001" }
71
+ ```
72
+
73
+ The new token carries `"org_id"` and `"org_role"`.
74
+
75
+ ## POST /auth/organizations/invitations/accept
76
+
77
+ Accepts an emailed invitation. The signed-in user's **verified** email must match the invited email. Session checked live.
78
+
79
+ **Request**
80
+
81
+ ```json
82
+ { "token": "oi_aW52aXRhdGlvbmV4YW1wbGV0b2tlbjEyMzQ1Njc4OTAxMjM" }
83
+ ```
84
+
85
+ **Response `200`**
86
+
87
+ ```json
88
+ { "success": true, "organizationId": "a1b2c3d4-0000-4000-8000-000000000001", "role": "member" }
89
+ ```
90
+
91
+ **Errors:** `400 INVALID_TOKEN` (unknown, used, expired (`organizations.invitationExpiresInDays`, 7 by default), cancelled, or a different / unverified email), `409 ALREADY_MEMBER`.
92
+
93
+ ---
94
+
95
+ ## GET /auth/organizations/:organizationId
96
+
97
+ Any member. **Response `200`:** `{ "success": true, "organization": { ...organization object, "myRole": "admin" } }`
98
+
99
+ ## PATCH /auth/organizations/:organizationId
100
+
101
+ Admin or owner. Session checked live.
102
+
103
+ **Request** (all optional):
104
+
105
+ ```json
106
+ { "name": "Acme Travels India", "slug": "acme-india", "metadata": { "gstNumber": "29ABCDE1234F1Z5" } }
107
+ ```
108
+
109
+ **Response `200`:** `{ "success": true, "organization": { ... } }`. Errors: `409 ORGANIZATION_SLUG_TAKEN`, `403 FORBIDDEN`.
110
+
111
+ ## DELETE /auth/organizations/:organizationId
112
+
113
+ Owner only. Removes members, invitations and the organization's API keys. Session checked live. **Response `200`:** `{ "success": true }`
114
+
115
+ ---
116
+
117
+ ## GET /auth/organizations/:organizationId/members
118
+
119
+ Any member.
120
+
121
+ **Response `200`**
122
+
123
+ ```json
124
+ {
125
+ "success": true,
126
+ "members": [
127
+ { "userId": "5f0c...", "email": "asha@example.com", "firstName": "Asha", "lastName": "Rao", "role": "owner", "joinedAt": "2026-10-20T06:30:00.000Z" },
128
+ { "userId": "9d2e...", "email": "ravi@example.com", "firstName": "Ravi", "lastName": "Kumar", "role": "member", "joinedAt": "2026-10-21T09:00:00.000Z" }
129
+ ]
130
+ }
131
+ ```
132
+
133
+ ## PATCH /auth/organizations/:organizationId/members/:memberUserId
134
+
135
+ Changes a member's role. Admins manage members and admins; **only owners** can make or unmake owners. Session checked live.
136
+
137
+ **Request**
138
+
139
+ ```json
140
+ { "role": "admin" }
141
+ ```
142
+
143
+ `role` is one of `"owner"`, `"admin"`, `"member"`.
144
+
145
+ **Response `200`:** `{ "success": true }`. Errors: `403 FORBIDDEN`, `404 NOT_FOUND`, `409 LAST_OWNER`.
146
+
147
+ ## DELETE /auth/organizations/:organizationId/members/:memberUserId
148
+
149
+ Removes a member. Use your own user id to **leave**. Session checked live. **Response `200`:** `{ "success": true }`. Errors: `403 FORBIDDEN`, `404 NOT_FOUND`, `409 LAST_OWNER`.
150
+
151
+ ---
152
+
153
+ ## GET /auth/organizations/:organizationId/invitations
154
+
155
+ Admin or owner. Open (not accepted, not cancelled) invitations.
156
+
157
+ **Response `200`**
158
+
159
+ ```json
160
+ {
161
+ "success": true,
162
+ "invitations": [
163
+ {
164
+ "id": "c3d4...",
165
+ "organizationId": "a1b2...",
166
+ "email": "ravi@example.com",
167
+ "role": "member",
168
+ "invitedByUserId": "5f0c...",
169
+ "expiresAt": "2026-10-27T06:30:00.000Z",
170
+ "acceptedAt": null,
171
+ "revokedAt": null,
172
+ "createdAt": "2026-10-20T06:30:00.000Z"
173
+ }
174
+ ]
175
+ }
176
+ ```
177
+
178
+ ## POST /auth/organizations/:organizationId/invitations
179
+
180
+ Admin or owner (inviting an `owner` needs an owner). Sends an `organization_invitation` email; a new invitation to the same email replaces the old one. Session checked live.
181
+
182
+ **Request**
183
+
184
+ ```json
185
+ { "email": "ravi@example.com", "role": "member" }
186
+ ```
187
+
188
+ **Response `201`:** `{ "success": true }`. Errors: `400 INVALID_EMAIL`, `403 FORBIDDEN`.
189
+
190
+ ## DELETE /auth/organizations/:organizationId/invitations/:invitationId
191
+
192
+ Admin or owner. Cancels an open invitation. Session checked live. **Response `200`:** `{ "success": true }`. Errors: `404 NOT_FOUND`.
@@ -0,0 +1,195 @@
1
+ # Passkeys
2
+
3
+ Needs `passkeys.enabled` and the `passkeys` option on the server; otherwise `403 SIGN_IN_METHOD_DISABLED` / `501 NOT_CONFIGURED`. Each ceremony is two calls: **options** (the server creates a challenge) and **verify** (the device signed it). Browser code is in [Sign-in flows](../sign-in-flows.md#passkeys). Shared formats, the sign-in result and the user object are described in [Endpoints](README.md).
4
+
5
+ ---
6
+
7
+ ## POST /auth/passkeys/register/options
8
+
9
+ Starts adding a passkey for the signed-in user.
10
+
11
+ | | |
12
+ |---|---|
13
+ | Auth | User, session checked live |
14
+
15
+ **Request:** no body.
16
+
17
+ **Response `200`**
18
+
19
+ ```json
20
+ {
21
+ "success": true,
22
+ "challengeToken": "ch_Zm9vYmFyZXhhbXBsZWNoYWxsZW5nZXRva2VuMTIzNDU2Nzg",
23
+ "options": {
24
+ "challenge": "lB3yW9kQ2x...",
25
+ "rp": { "name": "MyApp", "id": "myapp.com" },
26
+ "user": { "id": "NWYwYzhhMmUt...", "name": "asha@example.com", "displayName": "Asha Rao" },
27
+ "pubKeyCredParams": [{ "alg": -8, "type": "public-key" }, { "alg": -7, "type": "public-key" }, { "alg": -257, "type": "public-key" }],
28
+ "timeout": 60000,
29
+ "attestation": "none",
30
+ "excludeCredentials": [],
31
+ "authenticatorSelection": { "residentKey": "required", "userVerification": "required", "requireResidentKey": true }
32
+ }
33
+ }
34
+ ```
35
+
36
+ Pass `options` unchanged to `startRegistration({ optionsJSON: options })` (browser) or your platform's passkey API. The challenge expires after 5 minutes.
37
+
38
+ **Errors**
39
+
40
+ | Status | `code` | When |
41
+ |---|---|---|
42
+ | 400 | `VALIDATION_ERROR` | `problems: ["too many passkeys"]` (20 per user) |
43
+
44
+ ---
45
+
46
+ ## POST /auth/passkeys/register/verify
47
+
48
+ Saves the new passkey.
49
+
50
+ | | |
51
+ |---|---|
52
+ | Auth | User, session checked live |
53
+
54
+ **Request**
55
+
56
+ ```json
57
+ {
58
+ "challengeToken": "ch_Zm9vYmFyZXhhbXBsZWNoYWxsZW5nZXRva2VuMTIzNDU2Nzg",
59
+ "name": "My laptop",
60
+ "response": {
61
+ "id": "Q2xpZW50Q3JlZGVudGlhbElk",
62
+ "rawId": "Q2xpZW50Q3JlZGVudGlhbElk",
63
+ "type": "public-key",
64
+ "response": {
65
+ "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIi...",
66
+ "attestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YV...",
67
+ "transports": ["internal", "hybrid"]
68
+ },
69
+ "clientExtensionResults": {},
70
+ "authenticatorAttachment": "platform"
71
+ }
72
+ }
73
+ ```
74
+
75
+ | Field | Type | Required | Notes |
76
+ |---|---|---|---|
77
+ | `challengeToken` | string | yes | from `register/options` |
78
+ | `response` | object | yes | exactly what the browser / platform API returned, as JSON |
79
+ | `name` | string | no | up to 60 characters; default `"Passkey"` |
80
+
81
+ **Response `200`**
82
+
83
+ ```json
84
+ {
85
+ "success": true,
86
+ "passkey": { "id": "a7c1...", "name": "My laptop", "isBackedUp": true, "createdAt": "2026-10-20T06:30:00.000Z", "lastUsedAt": null }
87
+ }
88
+ ```
89
+
90
+ **Errors**
91
+
92
+ | Status | `code` | When |
93
+ |---|---|---|
94
+ | 400 | `INVALID_TOKEN` | Challenge unknown, used or expired |
95
+ | 401 | `INVALID_PASSKEY` | Verification failed (wrong origin, no fingerprint/PIN, tampered response) |
96
+
97
+ ---
98
+
99
+ ## POST /auth/passkeys/sign-in/options
100
+
101
+ Starts a passkey sign-in. No email is needed: the device offers the user's passkeys for your site.
102
+
103
+ | | |
104
+ |---|---|
105
+ | Auth | Public |
106
+ | Rate limit | 30 per IP per 15 minutes |
107
+
108
+ **Request:** no body.
109
+
110
+ **Response `200`**
111
+
112
+ ```json
113
+ {
114
+ "success": true,
115
+ "challengeToken": "ch_YW5vdGhlcmV4YW1wbGVjaGFsbGVuZ2V0b2tlbjEyMzQ1Njc",
116
+ "options": { "challenge": "pX9...", "timeout": 60000, "rpId": "myapp.com", "userVerification": "required" }
117
+ }
118
+ ```
119
+
120
+ ---
121
+
122
+ ## POST /auth/passkeys/sign-in/verify
123
+
124
+ Finishes the sign-in. No 2FA step follows: a passkey counts as two factors.
125
+
126
+ | | |
127
+ |---|---|
128
+ | Auth | Public |
129
+
130
+ **Request**
131
+
132
+ ```json
133
+ {
134
+ "challengeToken": "ch_YW5vdGhlcmV4YW1wbGVjaGFsbGVuZ2V0b2tlbjEyMzQ1Njc",
135
+ "response": {
136
+ "id": "Q2xpZW50Q3JlZGVudGlhbElk",
137
+ "rawId": "Q2xpZW50Q3JlZGVudGlhbElk",
138
+ "type": "public-key",
139
+ "response": {
140
+ "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0Ii...",
141
+ "authenticatorData": "SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MFAAAAAQ",
142
+ "signature": "MEUCIQDf...",
143
+ "userHandle": "NWYwYzhhMmUt..."
144
+ },
145
+ "clientExtensionResults": {}
146
+ }
147
+ }
148
+ ```
149
+
150
+ **Response `200`:** the [sign-in result](README.md#sign-in-result) (always `signed_in` when successful).
151
+
152
+ **Errors**
153
+
154
+ | Status | `code` | When |
155
+ |---|---|---|
156
+ | 400 | `INVALID_TOKEN` | Challenge unknown, used or expired |
157
+ | 401 | `INVALID_PASSKEY` | Unknown passkey or bad signature |
158
+ | 403 | `ACCOUNT_*` | See [sign-in result](README.md#sign-in-result) |
159
+
160
+ ---
161
+
162
+ ## GET /auth/passkeys
163
+
164
+ | | |
165
+ |---|---|
166
+ | Auth | User |
167
+
168
+ **Response `200`**
169
+
170
+ ```json
171
+ {
172
+ "success": true,
173
+ "passkeys": [
174
+ { "id": "a7c1...", "name": "My laptop", "isBackedUp": true, "createdAt": "2026-10-20T06:30:00.000Z", "lastUsedAt": "2026-10-21T08:00:00.000Z" }
175
+ ]
176
+ }
177
+ ```
178
+
179
+ ## PATCH /auth/passkeys/:passkeyId
180
+
181
+ Renames a passkey. Auth: User.
182
+
183
+ **Request**
184
+
185
+ ```json
186
+ { "name": "Work phone" }
187
+ ```
188
+
189
+ **Response `200`:** `{ "success": true }`. Errors: `404 NOT_FOUND`.
190
+
191
+ ## DELETE /auth/passkeys/:passkeyId
192
+
193
+ Removes a passkey. Auth: User, session checked live. No body.
194
+
195
+ **Response `200`:** `{ "success": true }`. Errors: `404 NOT_FOUND`, `409 LAST_SIGN_IN_METHOD`.
@@ -0,0 +1,214 @@
1
+ # Passwordless: email code, magic link, phone code
2
+
3
+ The same endpoints **sign in**, **sign up** (when `allowSignUp` is on) and **verify** the email or phone, because receiving the code proves ownership. Shared formats, the sign-in result and the user object are described in [Endpoints](README.md).
4
+
5
+ ## Sign-up details
6
+
7
+ The verify endpoints accept these optional fields. They are used **only when the request creates a new account**:
8
+
9
+ | Field | Type | Rules |
10
+ |---|---|---|
11
+ | `firstName` | string | up to 100 characters |
12
+ | `lastName` | string | up to 100 characters |
13
+ | `acceptTerms` | boolean | |
14
+ | `acceptPrivacyPolicy` | boolean | |
15
+
16
+ If your settings require them and they are missing, the response is:
17
+
18
+ ```json
19
+ {
20
+ "success": false,
21
+ "code": "VALIDATION_ERROR",
22
+ "message": "Some fields are missing or invalid.",
23
+ "missingSignUpDetails": ["firstName", "lastName", "acceptTerms"]
24
+ }
25
+ ```
26
+
27
+ For codes, the code is **not used up** by this error: show a form for the missing details and send the same code again with them.
28
+
29
+ ---
30
+
31
+ ## POST /auth/email/send-otp
32
+
33
+ Emails a sign-in code. Needs `emailOtp.enabled`.
34
+
35
+ | | |
36
+ |---|---|
37
+ | Auth | Public |
38
+ | Rate limit | 10 per IP and 5 per email per hour; one code per minute per email |
39
+
40
+ **Request**
41
+
42
+ ```json
43
+ { "email": "asha@example.com" }
44
+ ```
45
+
46
+ **Response `200`** (always the same, whether or not the email has an account):
47
+
48
+ ```json
49
+ { "success": true, "message": "If this destination can receive codes, a code is on its way." }
50
+ ```
51
+
52
+ **Errors**
53
+
54
+ | Status | `code` | When |
55
+ |---|---|---|
56
+ | 400 | `INVALID_EMAIL` | |
57
+ | 403 | `SIGN_IN_METHOD_DISABLED` | `emailOtp.enabled` is off |
58
+ | 429 | `TOO_MANY_REQUESTS` | A code was sent less than `emailOtp.resendAfterSeconds` ago (60 by default, returned as `retryAfterSeconds`), or a rate limit was hit |
59
+
60
+ ---
61
+
62
+ ## POST /auth/email/verify-otp
63
+
64
+ Signs in with the emailed code. Marks the email verified. Creates the account if the email is new and sign-up is allowed.
65
+
66
+ | | |
67
+ |---|---|
68
+ | Auth | Public |
69
+ | Rate limit | 30 per IP per 15 minutes |
70
+
71
+ **Request**
72
+
73
+ ```json
74
+ {
75
+ "email": "asha@example.com",
76
+ "code": "482913",
77
+ "firstName": "Asha",
78
+ "lastName": "Rao",
79
+ "acceptTerms": true,
80
+ "acceptPrivacyPolicy": true
81
+ }
82
+ ```
83
+
84
+ | Field | Type | Required |
85
+ |---|---|---|
86
+ | `email` | string | yes |
87
+ | `code` | string | yes |
88
+ | sign-up details | | only for new accounts, see above |
89
+
90
+ **Response `200`:** the [sign-in result](README.md#sign-in-result).
91
+
92
+ **Errors**
93
+
94
+ | Status | `code` | When | Extra |
95
+ |---|---|---|---|
96
+ | 400 | `INVALID_OTP` | Wrong code | `attemptsLeft` |
97
+ | 400 | `OTP_EXPIRED` | Expired (10 min), used, 5 wrong tries, or never sent | |
98
+ | 400 | `VALIDATION_ERROR` | New account and details missing | `missingSignUpDetails` |
99
+ | 400 | `EMAIL_DOMAIN_NOT_ALLOWED` | New account outside `allowedEmailDomains` | |
100
+ | 403 | `SIGN_UP_CLOSED` | New email and sign-up is off | |
101
+
102
+ ```json
103
+ { "success": false, "code": "INVALID_OTP", "message": "This code is incorrect.", "attemptsLeft": 3 }
104
+ ```
105
+
106
+ ---
107
+
108
+ ## POST /auth/magic-link/send
109
+
110
+ Emails a one-click sign-in link (valid `magicLink.expiresInMinutes`, 15 by default). Needs `magicLink.enabled`.
111
+
112
+ | | |
113
+ |---|---|
114
+ | Auth | Public |
115
+ | Rate limit | 10 per IP and 3 per email per hour |
116
+
117
+ **Request**
118
+
119
+ ```json
120
+ { "email": "asha@example.com" }
121
+ ```
122
+
123
+ **Response `200`** (always the same):
124
+
125
+ ```json
126
+ { "success": true, "message": "If this email can sign in, a sign-in link is on its way." }
127
+ ```
128
+
129
+ ---
130
+
131
+ ## POST /auth/magic-link/verify
132
+
133
+ Signs in with the token from the link. The link works **once**, so for new users collect the sign-up details on the page before calling this.
134
+
135
+ | | |
136
+ |---|---|
137
+ | Auth | Public |
138
+ | Rate limit | 30 per IP per 15 minutes |
139
+
140
+ **Request**
141
+
142
+ ```json
143
+ {
144
+ "token": "ml_Q2x4bWZkY2V0ZXN0dG9rZW5leGFtcGxlMTIzNDU2Nzg5MDE",
145
+ "firstName": "Asha",
146
+ "lastName": "Rao",
147
+ "acceptTerms": true,
148
+ "acceptPrivacyPolicy": true
149
+ }
150
+ ```
151
+
152
+ **Response `200`:** the [sign-in result](README.md#sign-in-result).
153
+
154
+ **Errors**
155
+
156
+ | Status | `code` | When |
157
+ |---|---|---|
158
+ | 400 | `INVALID_TOKEN` | Unknown, used or expired link |
159
+ | 400 | `VALIDATION_ERROR` | New account and `missingSignUpDetails` |
160
+ | 403 | `SIGN_UP_CLOSED` / `SIGN_IN_METHOD_DISABLED` | |
161
+
162
+ ---
163
+
164
+ ## POST /auth/phone/send-otp
165
+
166
+ Sends a sign-in code by SMS. Needs `phoneOtp.enabled` and an `smsSender`.
167
+
168
+ | | |
169
+ |---|---|
170
+ | Auth | Public |
171
+ | Rate limit | 10 per IP and 5 per number per hour; one code per minute per number |
172
+
173
+ **Request**
174
+
175
+ ```json
176
+ { "phoneNumber": "+91 98765 43210" }
177
+ ```
178
+
179
+ **Response `200`** (always the same):
180
+
181
+ ```json
182
+ { "success": true, "message": "If this destination can receive codes, a code is on its way." }
183
+ ```
184
+
185
+ **Errors**
186
+
187
+ | Status | `code` | When |
188
+ |---|---|---|
189
+ | 400 | `INVALID_PHONE` | No country code, or not a phone number |
190
+ | 400 | `PHONE_COUNTRY_NOT_ALLOWED` | Country not in `phoneOtp.allowedCountryCodes` |
191
+ | 403 | `SIGN_IN_METHOD_DISABLED` | Phone sign-in is off |
192
+ | 501 | `NOT_CONFIGURED` | No `smsSender` set up on the server |
193
+ | 429 | `TOO_MANY_REQUESTS` | Within `phoneOtp.resendAfterSeconds` (60 by default) of the last code, or a rate limit |
194
+
195
+ ---
196
+
197
+ ## POST /auth/phone/verify-otp
198
+
199
+ Signs in with the SMS code. Marks the phone verified, which is also how an account with `pendingVerifications: ["phone"]` finishes activation.
200
+
201
+ | | |
202
+ |---|---|
203
+ | Auth | Public |
204
+ | Rate limit | 30 per IP per 15 minutes |
205
+
206
+ **Request**
207
+
208
+ ```json
209
+ { "phoneNumber": "+919876543210", "code": "482913", "firstName": "Asha", "lastName": "Rao", "acceptTerms": true, "acceptPrivacyPolicy": true }
210
+ ```
211
+
212
+ **Response `200`:** the [sign-in result](README.md#sign-in-result).
213
+
214
+ **Errors:** same as [email verify-otp](#post-authemailverify-otp), plus `INVALID_PHONE`.