@baseplate-dev/plugin-auth 0.6.17 → 0.6.18

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 (197) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/better-auth/admin/generators/admin-crud-manage-roles-action/admin-crud-manage-roles-action.generator.d.ts +12 -0
  3. package/dist/better-auth/admin/generators/admin-crud-manage-roles-action/generated/index.d.ts +12 -0
  4. package/dist/better-auth/admin/generators/admin-crud-manage-roles-action/generated/template-renderers.d.ts +6 -0
  5. package/dist/better-auth/admin/generators/admin-crud-manage-roles-action/generated/typed-templates.d.ts +6 -0
  6. package/dist/better-auth/admin/generators/admin-crud-reset-password-action/admin-crud-reset-password-action.generator.d.ts +12 -0
  7. package/dist/better-auth/admin/generators/admin-crud-reset-password-action/generated/index.d.ts +12 -0
  8. package/dist/better-auth/admin/generators/admin-crud-reset-password-action/generated/template-renderers.d.ts +6 -0
  9. package/dist/better-auth/admin/generators/admin-crud-reset-password-action/generated/typed-templates.d.ts +12 -0
  10. package/dist/better-auth/admin/generators/admin-crud-roles-column/admin-crud-roles-column.generator.d.ts +6 -0
  11. package/dist/better-auth/generators/react/better-auth-pages/better-auth-pages.generator.d.ts +6 -0
  12. package/dist/better-auth/generators/react/better-auth-pages/generated/index.d.ts +36 -0
  13. package/dist/better-auth/generators/react/better-auth-pages/generated/template-renderers.d.ts +6 -0
  14. package/dist/better-auth/generators/react/better-auth-pages/generated/typed-templates.d.ts +60 -0
  15. package/dist/better-auth/generators/react/react-better-auth/generated/index.d.ts +12 -0
  16. package/dist/better-auth/generators/react/react-better-auth/generated/template-renderers.d.ts +6 -0
  17. package/dist/better-auth/generators/react/react-better-auth/generated/typed-templates.d.ts +6 -0
  18. package/dist/better-auth/generators/react/react-better-auth/react-better-auth.generator.d.ts +6 -0
  19. package/dist/local-auth/admin/common.js +6 -0
  20. package/dist/local-auth/admin/generators/admin-crud-invite-user-action/admin-crud-invite-user-action.generator.d.ts +531 -0
  21. package/dist/local-auth/admin/generators/admin-crud-invite-user-action/admin-crud-invite-user-action.generator.js +119 -0
  22. package/dist/local-auth/admin/generators/admin-crud-invite-user-action/generated/index.d.ts +540 -0
  23. package/dist/local-auth/admin/generators/admin-crud-invite-user-action/generated/index.js +11 -0
  24. package/dist/local-auth/admin/generators/admin-crud-invite-user-action/generated/template-paths.d.ts +12 -0
  25. package/dist/local-auth/admin/generators/admin-crud-invite-user-action/generated/template-paths.js +24 -0
  26. package/dist/local-auth/admin/generators/admin-crud-invite-user-action/generated/template-renderers.d.ts +276 -0
  27. package/dist/local-auth/admin/generators/admin-crud-invite-user-action/generated/template-renderers.js +45 -0
  28. package/dist/local-auth/admin/generators/admin-crud-invite-user-action/generated/typed-templates.d.ts +263 -0
  29. package/dist/local-auth/admin/generators/admin-crud-invite-user-action/generated/typed-templates.js +21 -0
  30. package/dist/local-auth/admin/generators/admin-crud-invite-user-action/index.d.ts +2 -0
  31. package/dist/local-auth/admin/generators/admin-crud-invite-user-action/index.js +2 -0
  32. package/dist/local-auth/admin/generators/admin-crud-invite-user-action/templates/routes/-components/invite-user-dialog.d.ts +21 -0
  33. package/dist/local-auth/admin/generators/admin-crud-invite-user-action/templates/routes/-components/invite-user-dialog.js +69 -0
  34. package/dist/local-auth/admin/generators/admin-crud-invite-user-action/templates/routes/-components/invite-user-dialog.tsx +122 -0
  35. package/dist/local-auth/admin/generators/admin-crud-manage-roles-action/admin-crud-manage-roles-action.generator.d.ts +12 -0
  36. package/dist/local-auth/admin/generators/admin-crud-manage-roles-action/generated/index.d.ts +12 -0
  37. package/dist/local-auth/admin/generators/admin-crud-manage-roles-action/generated/template-renderers.d.ts +6 -0
  38. package/dist/local-auth/admin/generators/admin-crud-manage-roles-action/generated/typed-templates.d.ts +6 -0
  39. package/dist/local-auth/admin/generators/admin-crud-reset-password-action/admin-crud-reset-password-action.generator.d.ts +12 -0
  40. package/dist/local-auth/admin/generators/admin-crud-reset-password-action/generated/index.d.ts +12 -0
  41. package/dist/local-auth/admin/generators/admin-crud-reset-password-action/generated/template-renderers.d.ts +6 -0
  42. package/dist/local-auth/admin/generators/admin-crud-reset-password-action/generated/typed-templates.d.ts +12 -0
  43. package/dist/local-auth/admin/generators/admin-crud-roles-column/admin-crud-roles-column.generator.d.ts +6 -0
  44. package/dist/local-auth/admin/node.js +13 -0
  45. package/dist/local-auth/admin/schema/invite-user-action.d.ts +12 -0
  46. package/dist/local-auth/admin/schema/invite-user-action.js +6 -0
  47. package/dist/local-auth/admin/web.js +8 -0
  48. package/dist/local-auth/core/common.js +7 -2
  49. package/dist/local-auth/core/components/local-auth-definition-editor.js +2 -1
  50. package/dist/local-auth/core/components/local-auth-web-app-settings-form.d.ts +9 -0
  51. package/dist/local-auth/core/components/local-auth-web-app-settings-form.js +11 -0
  52. package/dist/local-auth/core/generators/auth-email-password/auth-email-password.generator.d.ts +6 -0
  53. package/dist/local-auth/core/generators/auth-email-password/auth-email-password.generator.js +66 -6
  54. package/dist/local-auth/core/generators/auth-email-password/generated/index.d.ts +188 -0
  55. package/dist/local-auth/core/generators/auth-email-password/generated/template-paths.d.ts +5 -0
  56. package/dist/local-auth/core/generators/auth-email-password/generated/template-paths.js +5 -0
  57. package/dist/local-auth/core/generators/auth-email-password/generated/template-renderers.d.ts +18 -0
  58. package/dist/local-auth/core/generators/auth-email-password/generated/template-renderers.js +66 -0
  59. package/dist/local-auth/core/generators/auth-email-password/generated/typed-templates.d.ts +192 -0
  60. package/dist/local-auth/core/generators/auth-email-password/generated/typed-templates.js +82 -1
  61. package/dist/local-auth/core/generators/auth-email-password/templates/module/constants/otp.constants.d.ts +19 -0
  62. package/dist/local-auth/core/generators/auth-email-password/templates/module/constants/otp.constants.js +20 -0
  63. package/dist/local-auth/core/generators/auth-email-password/templates/module/constants/otp.constants.ts +22 -0
  64. package/dist/local-auth/core/generators/auth-email-password/templates/module/constants/password.constants.d.ts +12 -0
  65. package/dist/local-auth/core/generators/auth-email-password/templates/module/constants/password.constants.js +12 -0
  66. package/dist/local-auth/core/generators/auth-email-password/templates/module/constants/password.constants.ts +14 -0
  67. package/dist/local-auth/core/generators/auth-email-password/templates/module/schema/email-otp.mutations.d.ts +2 -0
  68. package/dist/local-auth/core/generators/auth-email-password/templates/module/schema/email-otp.mutations.js +30 -0
  69. package/dist/local-auth/core/generators/auth-email-password/templates/module/schema/email-otp.mutations.ts +38 -0
  70. package/dist/local-auth/core/generators/auth-email-password/templates/module/schema/invite.mutations.d.ts +2 -0
  71. package/dist/local-auth/core/generators/auth-email-password/templates/module/schema/invite.mutations.js +42 -0
  72. package/dist/local-auth/core/generators/auth-email-password/templates/module/schema/invite.mutations.ts +54 -0
  73. package/dist/local-auth/core/generators/auth-email-password/templates/module/schema/user-password.mutations.js +2 -19
  74. package/dist/local-auth/core/generators/auth-email-password/templates/module/schema/user-password.mutations.ts +1 -22
  75. package/dist/local-auth/core/generators/auth-email-password/templates/module/services/email-otp.service.d.ts +37 -0
  76. package/dist/local-auth/core/generators/auth-email-password/templates/module/services/email-otp.service.js +225 -0
  77. package/dist/local-auth/core/generators/auth-email-password/templates/module/services/email-otp.service.ts +333 -0
  78. package/dist/local-auth/core/generators/auth-email-password/templates/module/services/invite.service.d.ts +39 -0
  79. package/dist/local-auth/core/generators/auth-email-password/templates/module/services/invite.service.js +138 -0
  80. package/dist/local-auth/core/generators/auth-email-password/templates/module/services/invite.service.ts +209 -0
  81. package/dist/local-auth/core/generators/auth-email-password/templates/module/services/password-reset.service.js +3 -3
  82. package/dist/local-auth/core/generators/auth-email-password/templates/module/services/password-reset.service.ts +3 -2
  83. package/dist/local-auth/core/generators/auth-email-templates/auth-email-templates.generator.d.ts +3 -1
  84. package/dist/local-auth/core/generators/auth-email-templates/auth-email-templates.generator.js +18 -3
  85. package/dist/local-auth/core/generators/auth-email-templates/generated/index.d.ts +40 -0
  86. package/dist/local-auth/core/generators/auth-email-templates/generated/template-paths.d.ts +2 -0
  87. package/dist/local-auth/core/generators/auth-email-templates/generated/template-paths.js +2 -0
  88. package/dist/local-auth/core/generators/auth-email-templates/generated/template-renderers.d.ts +6 -0
  89. package/dist/local-auth/core/generators/auth-email-templates/generated/template-renderers.js +20 -0
  90. package/dist/local-auth/core/generators/auth-email-templates/generated/typed-templates.d.ts +40 -0
  91. package/dist/local-auth/core/generators/auth-email-templates/generated/typed-templates.js +24 -0
  92. package/dist/local-auth/core/generators/auth-email-templates/templates/src/emails/auth/email-otp.email.d.ts +3 -0
  93. package/dist/local-auth/core/generators/auth-email-templates/templates/src/emails/auth/email-otp.email.js +18 -0
  94. package/dist/local-auth/core/generators/auth-email-templates/templates/src/emails/auth/email-otp.email.tsx +57 -0
  95. package/dist/local-auth/core/generators/auth-email-templates/templates/src/emails/auth/invite.email.d.ts +3 -0
  96. package/dist/local-auth/core/generators/auth-email-templates/templates/src/emails/auth/invite.email.js +14 -0
  97. package/dist/local-auth/core/generators/auth-email-templates/templates/src/emails/auth/invite.email.tsx +47 -0
  98. package/dist/local-auth/core/generators/auth-module/auth-module.generator.d.ts +4 -0
  99. package/dist/local-auth/core/generators/auth-module/auth-module.generator.js +5 -1
  100. package/dist/local-auth/core/generators/auth-module/generated/index.d.ts +20 -0
  101. package/dist/local-auth/core/generators/auth-module/generated/template-paths.d.ts +1 -0
  102. package/dist/local-auth/core/generators/auth-module/generated/template-paths.js +1 -0
  103. package/dist/local-auth/core/generators/auth-module/generated/template-renderers.d.ts +3 -0
  104. package/dist/local-auth/core/generators/auth-module/generated/template-renderers.js +13 -0
  105. package/dist/local-auth/core/generators/auth-module/generated/ts-import-providers.d.ts +9 -0
  106. package/dist/local-auth/core/generators/auth-module/generated/ts-import-providers.js +6 -0
  107. package/dist/local-auth/core/generators/auth-module/generated/typed-templates.d.ts +17 -0
  108. package/dist/local-auth/core/generators/auth-module/generated/typed-templates.js +20 -0
  109. package/dist/local-auth/core/generators/auth-module/templates/module/services/auth-verification.service.d.ts +4 -0
  110. package/dist/local-auth/core/generators/auth-module/templates/module/services/auth-verification.service.js +1 -1
  111. package/dist/local-auth/core/generators/auth-module/templates/module/services/auth-verification.service.ts +1 -1
  112. package/dist/local-auth/core/generators/auth-module/templates/module/services/code-verification.service.d.ts +66 -0
  113. package/dist/local-auth/core/generators/auth-module/templates/module/services/code-verification.service.js +134 -0
  114. package/dist/local-auth/core/generators/auth-module/templates/module/services/code-verification.service.ts +184 -0
  115. package/dist/local-auth/core/generators/auth-routes/auth-routes.generator.d.ts +8 -0
  116. package/dist/local-auth/core/generators/auth-routes/auth-routes.generator.js +38 -5
  117. package/dist/local-auth/core/generators/auth-routes/generated/index.d.ts +840 -268
  118. package/dist/local-auth/core/generators/auth-routes/generated/template-paths.d.ts +3 -0
  119. package/dist/local-auth/core/generators/auth-routes/generated/template-paths.js +3 -0
  120. package/dist/local-auth/core/generators/auth-routes/generated/template-renderers.d.ts +18 -0
  121. package/dist/local-auth/core/generators/auth-routes/generated/template-renderers.js +51 -0
  122. package/dist/local-auth/core/generators/auth-routes/generated/typed-templates.d.ts +608 -283
  123. package/dist/local-auth/core/generators/auth-routes/generated/typed-templates.js +69 -23
  124. package/dist/local-auth/core/generators/auth-routes/templates/routes/auth_/-otp-constants.d.ts +9 -0
  125. package/dist/local-auth/core/generators/auth-routes/templates/routes/auth_/-otp-constants.js +10 -0
  126. package/dist/local-auth/core/generators/auth-routes/templates/routes/auth_/-otp-constants.ts +11 -0
  127. package/dist/local-auth/core/generators/auth-routes/templates/routes/auth_/accept-invite.d.ts +7 -0
  128. package/dist/local-auth/core/generators/auth-routes/templates/routes/auth_/accept-invite.js +148 -0
  129. package/dist/local-auth/core/generators/auth-routes/templates/routes/auth_/accept-invite.tsx +264 -0
  130. package/dist/local-auth/core/generators/auth-routes/templates/routes/auth_/login-otp.d.ts +7 -0
  131. package/dist/local-auth/core/generators/auth-routes/templates/routes/auth_/login-otp.js +184 -0
  132. package/dist/local-auth/core/generators/auth-routes/templates/routes/auth_/login-otp.tsx +311 -0
  133. package/dist/local-auth/core/generators/auth-routes/templates/routes/auth_/login.js +1 -1
  134. package/dist/local-auth/core/generators/auth-routes/templates/routes/auth_/login.tsx +2 -9
  135. package/dist/local-auth/core/generators/react-session/generated/index.d.ts +12 -0
  136. package/dist/local-auth/core/generators/react-session/generated/template-renderers.d.ts +6 -0
  137. package/dist/local-auth/core/generators/react-session/generated/typed-templates.d.ts +12 -0
  138. package/dist/local-auth/core/generators/react-session/react-session.generator.d.ts +6 -0
  139. package/dist/local-auth/core/node.js +24 -6
  140. package/dist/local-auth/core/schema/migrations.d.ts +3 -0
  141. package/dist/local-auth/core/schema/migrations.js +36 -0
  142. package/dist/local-auth/core/schema/models.js +8 -0
  143. package/dist/local-auth/core/schema/plugin-definition.d.ts +1 -0
  144. package/dist/local-auth/core/schema/plugin-definition.js +1 -0
  145. package/dist/local-auth/core/schema/web-app-schema.d.ts +15 -0
  146. package/dist/local-auth/core/schema/web-app-schema.js +16 -0
  147. package/dist/local-auth/core/web.js +8 -1
  148. package/dist/web/assets/{_virtual_mf-localSharedImportMap___mfe_internal__plugin_mf_2_auth-ChkXxpXe.js → _virtual_mf-localSharedImportMap___mfe_internal__plugin_mf_2_auth__mf_owner__1-CKKmnLep.js} +42 -34
  149. package/dist/web/assets/{dist-DY7ZXvq4.js → _virtual_mf___mfe_internal__plugin_mf_2_auth__mf_owner__1__loadShare___mf_0_baseplate_mf_2_dev_mf_1_project_mf_2_builder_mf_2_lib__loadShare__.js-Cx7TvZ_H.js} +16717 -373
  150. package/dist/web/assets/{_virtual_mf___mfe_internal__plugin_mf_2_auth__loadShare___mf_0_baseplate_mf_2_dev_mf_1_project_mf_2_builder_mf_2_lib_mf_1_web__loadShare__.js-37vlYRxk.js → _virtual_mf___mfe_internal__plugin_mf_2_auth__mf_owner__1__loadShare___mf_0_baseplate_mf_2_dev_mf_1_project_mf_2_builder_mf_2_lib_mf_1_web__loadShare__.js-D3Nvasea.js} +90 -38
  151. package/dist/web/assets/{_virtual_mf___mfe_internal__plugin_mf_2_auth__loadShare___mf_0_baseplate_mf_2_dev_mf_1_ui_mf_2_components__loadShare__.js-DRSNXPPo.js → _virtual_mf___mfe_internal__plugin_mf_2_auth__mf_owner__1__loadShare___mf_0_baseplate_mf_2_dev_mf_1_ui_mf_2_components__loadShare__.js-C2GDE8Py.js} +1645 -921
  152. package/dist/web/assets/{_virtual_mf___mfe_internal__plugin_mf_2_auth__loadShare___mf_0_tanstack_mf_1_react_mf_2_router__loadShare__.js-DfiQqvVC.js → _virtual_mf___mfe_internal__plugin_mf_2_auth__mf_owner__1__loadShare___mf_0_tanstack_mf_1_react_mf_2_router__loadShare__.js-CiccpWjh.js} +212 -57
  153. package/dist/web/assets/auth-CsHp2bQi.js +1 -0
  154. package/dist/web/assets/common-BGTuTgx7.js +43 -0
  155. package/dist/web/assets/common-C8_sC5pp.js +70 -0
  156. package/dist/web/assets/{common-ByxS61u8.js → common-Co5lW_TK.js} +10 -10
  157. package/dist/web/assets/{common-iHaemino.js → common-CoLuMS7U.js} +6 -6
  158. package/dist/web/assets/common-Dueu_1NG.js +36 -0
  159. package/dist/web/assets/{common-TDf_PrjX.js → common-N3skPbzk.js} +10 -10
  160. package/dist/web/assets/{dist-CrLSslv6.js → dist-DQd1TAJX.js} +273 -132
  161. package/dist/web/assets/{get-auth-plugin-definition-kDCtXq_6.js → get-auth-plugin-definition-DyokUVjX.js} +3 -3
  162. package/dist/web/assets/{hostInit-Cruek6c6.js → hostInit-BCYmw0H5.js} +32 -5
  163. package/dist/web/assets/{mf-entry-bootstrap-0-dfed0275.js → mf-entry-bootstrap-0-3ede9334.js} +2 -1
  164. package/dist/web/assets/{mf-entry-bootstrap-1-5275674a.js → mf-entry-bootstrap-1-3da85eea.js} +3 -2
  165. package/dist/web/assets/{mf-entry-bootstrap-2-39fb9255.js → mf-entry-bootstrap-2-32e24e11.js} +3 -2
  166. package/dist/web/assets/{mf-entry-bootstrap-3-49e64336.js → mf-entry-bootstrap-3-a3cfea9d.js} +3 -2
  167. package/dist/web/assets/{models-DSvs_3bA.js → models-BcPOQC5p.js} +4 -5
  168. package/dist/web/assets/{models-BZmCbizK.js → models-BcUgOGGn.js} +11 -6
  169. package/dist/web/assets/{plugin-definition-CYj29S3q.js → plugin-definition-D1EImXIf.js} +9 -10
  170. package/dist/web/assets/plugin-definition-lw-gB4hU.js +10 -0
  171. package/dist/web/assets/{styles-yjbHBTlw.js → styles-EOyEbGA4.js} +9 -10
  172. package/dist/web/assets/{virtualExposes-CbPBmicF.js → virtualExposes-DWORnjyA.js} +1 -1
  173. package/dist/web/assets/virtual_mf-REMOTE_ENTRY_ID___mfe_internal__plugin-auth__remoteEntry_js-t-KnBiUh.js +747 -0
  174. package/dist/web/assets/{virtual_mf-exposes___mfe_internal__plugin-auth__remoteEntry_js-B6BXIeF1.js → virtual_mf-exposes___mfe_internal__plugin-auth__remoteEntry_js-DZfE3QCR.js} +13 -13
  175. package/dist/web/assets/{web-VqBA3jxZ.js → web-CBVepebK.js} +22 -22
  176. package/dist/web/assets/{web-D0MSKfyv.js → web-Dgb85jhs.js} +47 -47
  177. package/dist/web/assets/{web-CXAHKjIY.js → web-EDeSquSP.js} +28 -28
  178. package/dist/web/assets/{web-1eTcxMhf.js → web-PqAcfBSy.js} +9 -9
  179. package/dist/web/assets/{web-CDAKPPK9.js → web-RhChfBw_.js} +21 -21
  180. package/dist/web/assets/web-kaD9AzNS.js +59 -0
  181. package/dist/web/assets/web-xJ-GnSkC.js +148 -0
  182. package/dist/web/index.html +5 -5
  183. package/dist/web/remoteEntry.js +1 -1
  184. package/package.json +14 -14
  185. package/dist/web/assets/_virtual_mf___mfe_internal__plugin_mf_2_auth__loadShare___mf_0_baseplate_mf_2_dev_mf_1_project_mf_2_builder_mf_2_lib__loadShare__.js-CO5Pvo0y.js +0 -384
  186. package/dist/web/assets/_virtual_mf___mfe_internal__plugin_mf_2_auth__loadShare__zod__loadShare__.js-BEZ7A-cz.js +0 -13566
  187. package/dist/web/assets/auth-BxAE0rgh.js +0 -1
  188. package/dist/web/assets/common-CKl_XlvH.js +0 -37
  189. package/dist/web/assets/common-UpVCKZeW.js +0 -41
  190. package/dist/web/assets/common-crSwCD36.js +0 -37
  191. package/dist/web/assets/model-utils-C0WDb_Ec.js +0 -1599
  192. package/dist/web/assets/plugin-definition-DOMmPL2Z.js +0 -11
  193. package/dist/web/assets/virtual_mf-REMOTE_ENTRY_ID___mfe_internal__plugin-auth__remoteEntry_js-XM6iYVxf.js +0 -259
  194. package/dist/web/assets/virtual_mf-exposes-ssr___mfe_internal__plugin-auth__remoteEntry_js-DGjg7Brm.js +0 -129
  195. package/dist/web/assets/web-DbeAaDTV.js +0 -118
  196. package/dist/web/assets/web-miDovYk_.js +0 -46
  197. package/dist/web/remoteEntry.ssr.js +0 -43
@@ -0,0 +1,184 @@
1
+ // @ts-nocheck
2
+
3
+ import type { AuthVerification, Prisma } from '%prismaGeneratedImports';
4
+
5
+ import { safeCompare } from '$servicesAuthVerification';
6
+ import { getConfig } from '%configServiceImports';
7
+ import { prisma } from '%prismaImports';
8
+ import * as crypto from 'node:crypto';
9
+
10
+ /**
11
+ * Short code verifications, for flows that email a handful of digits rather
12
+ * than a link.
13
+ *
14
+ * These share the `AuthVerification` table with the split-token flows in
15
+ * {@link ./auth-verification.service.js} but not their security model: the
16
+ * secret is short enough to guess, so it is keyed rather than hashed, carries
17
+ * its own attempt budget, and is addressed by a caller-supplied identifier
18
+ * instead of a random selector.
19
+ */
20
+
21
+ /**
22
+ * Derives the stored value for a short code.
23
+ *
24
+ * Short codes occupy a keyspace small enough to invert a plain digest by
25
+ * exhaustive search, so they are keyed with the server secret rather than
26
+ * hashed: an attacker holding only the database cannot recover them. The type
27
+ * and identifier are mixed in so a stored value is valid solely for the flow
28
+ * and address it was issued for.
29
+ */
30
+ function hashCode({
31
+ type,
32
+ identifier,
33
+ code,
34
+ }: {
35
+ type: string;
36
+ identifier: string;
37
+ code: string;
38
+ }): string {
39
+ return crypto
40
+ .createHmac('sha256', getConfig().AUTH_SECRET)
41
+ .update(`${type}:${identifier}:${code}`)
42
+ .digest('hex');
43
+ }
44
+
45
+ /**
46
+ * Creates or replaces a short code verification (e.g. an emailed OTP).
47
+ *
48
+ * The identifier is caller-supplied (typically an email) rather than a random
49
+ * selector, so the code cannot be folded into a single token the way a
50
+ * split-token flow does. Only one code may be outstanding per
51
+ * `type`/`identifier` pair, so requesting a new one replaces any existing code
52
+ * and resets the attempt counter.
53
+ *
54
+ * The identifier rather than a user reference is the subject here, since a
55
+ * code may be issued for an address that has no account yet.
56
+ *
57
+ * The returned id identifies this particular issuance, so a caller that binds
58
+ * it to the requester (e.g. in a cookie) can tell one request apart from the
59
+ * next. It is regenerated on every call for that reason: reusing it would let
60
+ * whoever requested an earlier code redeem a later one requested by someone
61
+ * else.
62
+ *
63
+ * @param code - The plaintext code sent to the user; only its hash is stored
64
+ */
65
+ export async function createCodeVerification({
66
+ type,
67
+ identifier,
68
+ code,
69
+ expiresInSec,
70
+ }: {
71
+ type: string;
72
+ identifier: string;
73
+ code: string;
74
+ expiresInSec: number;
75
+ }): Promise<{ id: string }> {
76
+ const value = hashCode({ type, identifier, code });
77
+ const expiresAt = new Date(Date.now() + expiresInSec * 1000);
78
+ const id = crypto.randomUUID();
79
+
80
+ await prisma.authVerification.upsert({
81
+ where: { type_identifier: { type, identifier } },
82
+ create: {
83
+ id,
84
+ type,
85
+ identifier,
86
+ value,
87
+ expiresAt,
88
+ },
89
+ // Resetting `attempts` is what gives the replacement code a fresh budget;
90
+ // without it a reissued code would inherit the old code's failed guesses.
91
+ update: {
92
+ id,
93
+ value,
94
+ attempts: 0,
95
+ expiresAt,
96
+ },
97
+ select: { id: true },
98
+ });
99
+
100
+ return { id };
101
+ }
102
+
103
+ /**
104
+ * Validates a short code verification without consuming it, so the caller can
105
+ * gather any further input it needs before committing.
106
+ *
107
+ * Security: a short numeric code has far less entropy than a random token, so
108
+ * each code carries its own attempt counter alongside the endpoint rate limits.
109
+ * The record is deleted when the code has expired or the attempt budget is
110
+ * exhausted. Pass the returned record to {@link consumeCodeVerification} to
111
+ * complete the flow.
112
+ *
113
+ * Both cleanup paths delete by filter rather than by primary key: simultaneous
114
+ * callers can each decide the record should go, and only one of them removes a
115
+ * row. A keyed delete would raise on the others instead of returning null.
116
+ */
117
+ export async function validateCodeVerification({
118
+ type,
119
+ identifier,
120
+ code,
121
+ maxAttempts,
122
+ }: {
123
+ type: string;
124
+ identifier: string;
125
+ code: string;
126
+ maxAttempts: number;
127
+ }): Promise<AuthVerification | null> {
128
+ const record = await prisma.authVerification.findUnique({
129
+ where: { type_identifier: { type, identifier } },
130
+ });
131
+
132
+ if (!record) {
133
+ return null;
134
+ }
135
+
136
+ if (record.expiresAt < new Date()) {
137
+ await prisma.authVerification.deleteMany({ where: { id: record.id } });
138
+ return null;
139
+ }
140
+
141
+ if (safeCompare(record.value, hashCode({ type, identifier, code }))) {
142
+ return record;
143
+ }
144
+
145
+ // Incremented in the database rather than read-modify-written here, so
146
+ // simultaneous guesses each cost a point instead of sharing one.
147
+ const { attempts } = await prisma.authVerification.update({
148
+ where: { id: record.id },
149
+ data: { attempts: { increment: 1 } },
150
+ select: { attempts: true },
151
+ });
152
+
153
+ if (attempts >= maxAttempts) {
154
+ await prisma.authVerification.deleteMany({ where: { id: record.id } });
155
+ }
156
+
157
+ return null;
158
+ }
159
+
160
+ /**
161
+ * Consumes a previously validated verification, returning whether this call is
162
+ * the one that claimed it.
163
+ *
164
+ * The conditional delete is the authorization step: concurrent requests
165
+ * carrying the same code race here, and only the request that removes the row
166
+ * may proceed. Reading the row and deleting it in separate statements would
167
+ * let both win.
168
+ *
169
+ * @param client - Transaction client, so consuming the code can be committed
170
+ * together with whatever the code authorized rather than ahead of it
171
+ */
172
+ export async function consumeCodeVerification({
173
+ id,
174
+ client = prisma,
175
+ }: {
176
+ id: string;
177
+ client?: Prisma.TransactionClient;
178
+ }): Promise<boolean> {
179
+ const { count } = await client.authVerification.deleteMany({
180
+ where: { id },
181
+ });
182
+
183
+ return count === 1;
184
+ }
@@ -3,6 +3,8 @@
3
3
  */
4
4
  export declare const authRoutesGenerator: import("@baseplate-dev/sync").GeneratorBundleCreator<{
5
5
  requireNameOnRegistration: boolean;
6
+ emailOtp?: boolean | undefined;
7
+ disableRegistration?: boolean | undefined;
6
8
  }, {
7
9
  paths: import("@baseplate-dev/sync").GeneratorTask<{
8
10
  authCoreAuthRoutesPaths: import("@baseplate-dev/sync").ProviderExport<import("./generated/template-paths.js").AuthCoreAuthRoutesPaths>;
@@ -144,6 +146,12 @@ export declare const authRoutesGenerator: import("@baseplate-dev/sync").Generato
144
146
  InputGroupInput: {};
145
147
  InputGroupText: {};
146
148
  InputGroupTextarea: {};
149
+ InputOtp: {};
150
+ InputOtpField: {};
151
+ InputOtpFieldController: {};
152
+ InputOtpGroup: {};
153
+ InputOtpSeparator: {};
154
+ InputOtpSlot: {};
147
155
  inputVariants: {};
148
156
  Item: {};
149
157
  ItemActions: {};
@@ -4,6 +4,8 @@ import { z } from 'zod';
4
4
  import { AUTH_CORE_AUTH_ROUTES_GENERATED as GENERATED_TEMPLATES } from './generated/index.js';
5
5
  const descriptorSchema = z.object({
6
6
  requireNameOnRegistration: z.boolean(),
7
+ emailOtp: z.boolean().default(false),
8
+ disableRegistration: z.boolean().default(false),
7
9
  });
8
10
  /**
9
11
  * Generator for auth routes for logging in and registering
@@ -12,7 +14,7 @@ export const authRoutesGenerator = createGenerator({
12
14
  name: 'auth/core/auth-routes',
13
15
  generatorFileUrl: import.meta.url,
14
16
  descriptorSchema,
15
- buildTasks: ({ requireNameOnRegistration }) => ({
17
+ buildTasks: ({ requireNameOnRegistration, emailOtp, disableRegistration, }) => ({
16
18
  paths: GENERATED_TEMPLATES.paths.task,
17
19
  renderers: GENERATED_TEMPLATES.renderers.task,
18
20
  main: createGeneratorTask({
@@ -39,7 +41,39 @@ export const authRoutesGenerator = createGenerator({
39
41
  build: async (builder) => {
40
42
  await builder.apply(renderers.mainGroup.render({
41
43
  variables: {
42
- register: {
44
+ login: {
45
+ TPL_OTP_LOGIN_LINK: emailOtp
46
+ ? `<Link
47
+ to="/auth/login-otp"
48
+ search={{ return_to }}
49
+ className="text-muted-foreground underline-offset-4 hover:underline"
50
+ >
51
+ Sign in with a code instead
52
+ </Link>`
53
+ : '',
54
+ TPL_REGISTER_LINK: disableRegistration
55
+ ? ''
56
+ : `<div>
57
+ Don&apos;t have an account?{' '}
58
+ <Link
59
+ to="/auth/register"
60
+ className="underline underline-offset-4"
61
+ >
62
+ Sign up
63
+ </Link>
64
+ </div>`,
65
+ },
66
+ },
67
+ }));
68
+ await builder.apply(renderers.verifyEmail.render({}));
69
+ await builder.apply(renderers.acceptInvite.render({}));
70
+ if (emailOtp) {
71
+ await builder.apply(renderers.otpConstants.render({}));
72
+ await builder.apply(renderers.loginOtp.render({}));
73
+ }
74
+ if (!disableRegistration) {
75
+ await builder.apply(renderers.register.render({
76
+ variables: {
43
77
  TPL_REGISTER_SCHEMA: registerSchema,
44
78
  TPL_REGISTER_INPUT: registerInput,
45
79
  TPL_NAME_FORM_CONTROL: requireNameOnRegistration
@@ -53,9 +87,8 @@ export const authRoutesGenerator = createGenerator({
53
87
  />`
54
88
  : '',
55
89
  },
56
- },
57
- }));
58
- await builder.apply(renderers.verifyEmail.render({}));
90
+ }));
91
+ }
59
92
  },
60
93
  };
61
94
  },