@robelest/convex-auth 0.0.4-preview.25 → 0.0.4-preview.28

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 (666) hide show
  1. package/README.md +43 -36
  2. package/dist/bin.js +5765 -4880
  3. package/dist/browser/index.d.ts +30 -0
  4. package/dist/browser/index.js +93 -0
  5. package/dist/browser/locks.js +11 -0
  6. package/dist/browser/navigation.js +14 -0
  7. package/dist/{factors → browser}/passkey.js +23 -32
  8. package/dist/browser/runtime.js +92 -0
  9. package/dist/client/core/types.d.ts +452 -5
  10. package/dist/client/core/types.js +17 -0
  11. package/dist/client/errors.js +19 -0
  12. package/dist/client/factors/device.js +94 -0
  13. package/dist/{factors → client/factors}/totp.js +12 -4
  14. package/dist/client/index.d.ts +47 -1
  15. package/dist/client/index.js +269 -232
  16. package/dist/client/runtime/mutex.js +24 -0
  17. package/dist/client/runtime/proxy.js +30 -0
  18. package/dist/client/runtime/storage.js +45 -0
  19. package/dist/client/services/adapters.js +7 -0
  20. package/dist/client/services/http.js +6 -0
  21. package/dist/client/services/resolve.js +13 -0
  22. package/dist/client/services/runtime.js +6 -0
  23. package/dist/component/_generated/component.d.ts +1355 -1399
  24. package/dist/component/convex.config.d.ts +2 -2
  25. package/dist/component/index.d.ts +4 -26
  26. package/dist/component/index.js +1 -1
  27. package/dist/component/model.d.ts +26 -112
  28. package/dist/component/model.js +76 -54
  29. package/dist/component/modules.js +38 -0
  30. package/dist/component/public/factors/devices.js +1 -1
  31. package/dist/component/public/factors/passkeys.js +1 -1
  32. package/dist/component/public/factors/totp.js +1 -1
  33. package/dist/component/public/groups/core.js +2 -2
  34. package/dist/component/public/groups/invites.js +1 -1
  35. package/dist/component/public/groups/members.js +1 -1
  36. package/dist/component/public/identity/accounts.js +1 -1
  37. package/dist/component/public/identity/codes.js +1 -1
  38. package/dist/component/public/identity/sessions.js +39 -2
  39. package/dist/component/public/identity/tokens.js +82 -4
  40. package/dist/component/public/identity/users.js +1 -1
  41. package/dist/component/public/identity/verifiers.js +10 -4
  42. package/dist/component/public/security/keys.js +1 -1
  43. package/dist/component/public/security/limits.js +1 -1
  44. package/dist/component/public/{enterprise → sso}/audit.js +26 -26
  45. package/dist/component/public/sso/core.js +263 -0
  46. package/dist/component/public/sso/domains.js +280 -0
  47. package/dist/component/public/{enterprise → sso}/scim.js +87 -87
  48. package/dist/component/public/sso/secrets.js +125 -0
  49. package/dist/component/public/{enterprise → sso}/webhooks.js +59 -59
  50. package/dist/component/public.js +9 -9
  51. package/dist/component/schema.d.ts +472 -393
  52. package/dist/component/schema.js +36 -35
  53. package/dist/core/index.d.ts +380 -0
  54. package/dist/core/index.js +83 -0
  55. package/dist/otel.d.ts +69 -0
  56. package/dist/otel.js +82 -0
  57. package/dist/providers/anonymous.d.ts +15 -34
  58. package/dist/providers/anonymous.js +27 -35
  59. package/dist/providers/apple.d.ts +59 -0
  60. package/dist/providers/apple.js +58 -0
  61. package/dist/providers/credentials.d.ts +18 -34
  62. package/dist/providers/credentials.js +16 -27
  63. package/dist/providers/custom.d.ts +94 -0
  64. package/dist/providers/custom.js +119 -0
  65. package/dist/providers/device.d.ts +15 -49
  66. package/dist/providers/device.js +17 -34
  67. package/dist/providers/email.d.ts +21 -38
  68. package/dist/providers/email.js +36 -55
  69. package/dist/providers/github.d.ts +54 -0
  70. package/dist/providers/github.js +75 -0
  71. package/dist/providers/google.d.ts +54 -0
  72. package/dist/providers/google.js +61 -0
  73. package/dist/providers/index.d.ts +16 -12
  74. package/dist/providers/index.js +15 -11
  75. package/dist/providers/microsoft.d.ts +57 -0
  76. package/dist/providers/microsoft.js +101 -0
  77. package/dist/providers/passkey.d.ts +19 -35
  78. package/dist/providers/passkey.js +20 -30
  79. package/dist/providers/password.d.ts +17 -18
  80. package/dist/providers/password.js +121 -143
  81. package/dist/providers/phone.d.ts +13 -28
  82. package/dist/providers/phone.js +21 -46
  83. package/dist/providers/sso.d.ts +16 -36
  84. package/dist/providers/sso.js +21 -22
  85. package/dist/providers/totp.d.ts +13 -29
  86. package/dist/providers/totp.js +17 -27
  87. package/dist/server/auth-context.d.ts +204 -0
  88. package/dist/server/auth-context.js +76 -0
  89. package/dist/server/auth.d.ts +99 -244
  90. package/dist/server/auth.js +56 -152
  91. package/dist/server/componentContext.d.ts +12 -0
  92. package/dist/server/componentContext.js +1 -0
  93. package/dist/server/config.js +6 -67
  94. package/dist/server/constants.js +6 -0
  95. package/dist/server/contract.d.ts +105 -0
  96. package/dist/server/contract.js +43 -0
  97. package/dist/server/cookies.js +3 -2
  98. package/dist/server/core.js +31 -36
  99. package/dist/server/crypto.js +34 -44
  100. package/dist/server/db.js +6 -1
  101. package/dist/server/device.js +96 -130
  102. package/dist/server/env.js +48 -0
  103. package/dist/server/errors.js +20 -0
  104. package/dist/server/http.d.ts +15 -59
  105. package/dist/server/http.js +136 -120
  106. package/dist/server/identity.js +2 -2
  107. package/dist/server/index.d.ts +5 -4
  108. package/dist/server/index.js +3 -3
  109. package/dist/server/keys.js +10 -1
  110. package/dist/server/limits.js +26 -26
  111. package/dist/server/log.js +28 -0
  112. package/dist/server/mounts.d.ts +1107 -296
  113. package/dist/server/mounts.js +315 -196
  114. package/dist/server/mutations/account.js +11 -14
  115. package/dist/server/mutations/code.js +6 -5
  116. package/dist/server/mutations/invalidate.js +9 -11
  117. package/dist/server/mutations/oauth.js +112 -73
  118. package/dist/server/mutations/refresh.js +47 -97
  119. package/dist/server/mutations/register.js +37 -35
  120. package/dist/server/mutations/retrieve.js +16 -16
  121. package/dist/server/mutations/signature.js +15 -18
  122. package/dist/server/mutations/signin.js +10 -5
  123. package/dist/server/mutations/signout.js +11 -14
  124. package/dist/server/mutations/store.js +25 -18
  125. package/dist/server/mutations/verifier.js +11 -8
  126. package/dist/server/mutations/verify.js +53 -41
  127. package/dist/server/oauth/factory.js +44 -0
  128. package/dist/server/oauth/index.js +12 -0
  129. package/dist/server/oauth/runtime.js +248 -0
  130. package/dist/server/passkey.js +331 -365
  131. package/dist/server/payloads.d.ts +16 -0
  132. package/dist/server/payloads.js +30 -0
  133. package/dist/server/{ssr.d.ts → prefetch.d.ts} +2 -2
  134. package/dist/server/prefetch.js +635 -0
  135. package/dist/server/random.js +19 -0
  136. package/dist/server/redirects.js +10 -5
  137. package/dist/server/refresh.js +14 -86
  138. package/dist/server/runtime.d.ts +531 -31
  139. package/dist/server/runtime.js +106 -267
  140. package/dist/server/secret.js +44 -0
  141. package/dist/server/services/config.js +10 -0
  142. package/dist/server/services/group.js +211 -0
  143. package/dist/server/services/logger.js +8 -0
  144. package/dist/server/services/providers.js +22 -0
  145. package/dist/server/services/refresh.js +8 -0
  146. package/dist/server/services/resolve.js +27 -0
  147. package/dist/server/services/signin.js +8 -0
  148. package/dist/server/sessions.js +35 -34
  149. package/dist/server/signin.js +229 -140
  150. package/dist/server/{enterprise → sso}/config.js +10 -3
  151. package/dist/server/sso/domain.d.ts +614 -0
  152. package/dist/server/sso/domain.js +1175 -0
  153. package/dist/server/sso/http.js +1060 -0
  154. package/dist/server/sso/oidc.js +324 -0
  155. package/dist/server/sso/policies.js +59 -0
  156. package/dist/server/sso/policy.js +139 -0
  157. package/dist/server/sso/profile.js +22 -0
  158. package/dist/server/sso/provision.js +179 -0
  159. package/dist/{component/server/enterprise → server/sso}/saml.js +142 -56
  160. package/dist/{component/server/enterprise → server/sso}/scim.js +13 -7
  161. package/dist/server/sso/shared.js +74 -0
  162. package/dist/server/sso/validators.js +88 -0
  163. package/dist/server/sso/webhook.js +94 -0
  164. package/dist/server/tokens.js +16 -4
  165. package/dist/server/totp.js +155 -164
  166. package/dist/server/types.d.ts +306 -296
  167. package/dist/server/types.js +1 -30
  168. package/dist/server/url.js +32 -0
  169. package/dist/server/users.js +74 -40
  170. package/dist/server/utils/cache.js +51 -0
  171. package/dist/server/utils/dispatch.js +36 -0
  172. package/dist/server/utils/retry.js +24 -0
  173. package/dist/server/utils/span.js +32 -0
  174. package/dist/shared/errors.js +19 -0
  175. package/dist/shared/log.js +45 -0
  176. package/{src/test.ts → dist/test.d.ts} +21 -22
  177. package/dist/test.js +51 -0
  178. package/package.json +70 -42
  179. package/dist/authorization/index.d.ts.map +0 -1
  180. package/dist/authorization/index.js.map +0 -1
  181. package/dist/client/core/types.d.ts.map +0 -1
  182. package/dist/client/index.d.ts.map +0 -1
  183. package/dist/client/index.js.map +0 -1
  184. package/dist/component/_generated/api.d.ts +0 -75
  185. package/dist/component/_generated/api.d.ts.map +0 -1
  186. package/dist/component/_generated/api.js.map +0 -1
  187. package/dist/component/_generated/component.d.ts.map +0 -1
  188. package/dist/component/_generated/dataModel.d.ts +0 -42
  189. package/dist/component/_generated/dataModel.d.ts.map +0 -1
  190. package/dist/component/_generated/server.d.ts +0 -117
  191. package/dist/component/_generated/server.d.ts.map +0 -1
  192. package/dist/component/_generated/server.js.map +0 -1
  193. package/dist/component/_virtual/rolldown_runtime.js +0 -18
  194. package/dist/component/client/core/types.d.ts +0 -2
  195. package/dist/component/client/index.d.ts +0 -1
  196. package/dist/component/convex.config.d.ts.map +0 -1
  197. package/dist/component/convex.config.js.map +0 -1
  198. package/dist/component/functions.d.ts +0 -25
  199. package/dist/component/functions.d.ts.map +0 -1
  200. package/dist/component/functions.js.map +0 -1
  201. package/dist/component/index.d.ts.map +0 -1
  202. package/dist/component/model.d.ts.map +0 -1
  203. package/dist/component/model.js.map +0 -1
  204. package/dist/component/providers/anonymous.d.ts +0 -54
  205. package/dist/component/providers/anonymous.d.ts.map +0 -1
  206. package/dist/component/providers/credentials.d.ts +0 -38
  207. package/dist/component/providers/credentials.d.ts.map +0 -1
  208. package/dist/component/providers/device.d.ts +0 -67
  209. package/dist/component/providers/device.d.ts.map +0 -1
  210. package/dist/component/providers/email.d.ts +0 -62
  211. package/dist/component/providers/email.d.ts.map +0 -1
  212. package/dist/component/providers/oauth.d.ts +0 -25
  213. package/dist/component/providers/oauth.d.ts.map +0 -1
  214. package/dist/component/providers/oauth.js +0 -13
  215. package/dist/component/providers/oauth.js.map +0 -1
  216. package/dist/component/providers/passkey.d.ts +0 -57
  217. package/dist/component/providers/passkey.d.ts.map +0 -1
  218. package/dist/component/providers/password.d.ts +0 -88
  219. package/dist/component/providers/password.d.ts.map +0 -1
  220. package/dist/component/providers/phone.d.ts +0 -48
  221. package/dist/component/providers/phone.d.ts.map +0 -1
  222. package/dist/component/providers/sso.d.ts +0 -50
  223. package/dist/component/providers/sso.d.ts.map +0 -1
  224. package/dist/component/providers/totp.d.ts +0 -45
  225. package/dist/component/providers/totp.d.ts.map +0 -1
  226. package/dist/component/public/enterprise/audit.d.ts +0 -73
  227. package/dist/component/public/enterprise/audit.d.ts.map +0 -1
  228. package/dist/component/public/enterprise/audit.js.map +0 -1
  229. package/dist/component/public/enterprise/core.d.ts +0 -176
  230. package/dist/component/public/enterprise/core.d.ts.map +0 -1
  231. package/dist/component/public/enterprise/core.js +0 -292
  232. package/dist/component/public/enterprise/core.js.map +0 -1
  233. package/dist/component/public/enterprise/domains.d.ts +0 -174
  234. package/dist/component/public/enterprise/domains.d.ts.map +0 -1
  235. package/dist/component/public/enterprise/domains.js +0 -271
  236. package/dist/component/public/enterprise/domains.js.map +0 -1
  237. package/dist/component/public/enterprise/scim.d.ts +0 -245
  238. package/dist/component/public/enterprise/scim.d.ts.map +0 -1
  239. package/dist/component/public/enterprise/scim.js.map +0 -1
  240. package/dist/component/public/enterprise/secrets.d.ts +0 -78
  241. package/dist/component/public/enterprise/secrets.d.ts.map +0 -1
  242. package/dist/component/public/enterprise/secrets.js +0 -118
  243. package/dist/component/public/enterprise/secrets.js.map +0 -1
  244. package/dist/component/public/enterprise/webhooks.d.ts +0 -211
  245. package/dist/component/public/enterprise/webhooks.d.ts.map +0 -1
  246. package/dist/component/public/enterprise/webhooks.js.map +0 -1
  247. package/dist/component/public/factors/devices.d.ts +0 -157
  248. package/dist/component/public/factors/devices.d.ts.map +0 -1
  249. package/dist/component/public/factors/devices.js.map +0 -1
  250. package/dist/component/public/factors/passkeys.d.ts +0 -175
  251. package/dist/component/public/factors/passkeys.d.ts.map +0 -1
  252. package/dist/component/public/factors/passkeys.js.map +0 -1
  253. package/dist/component/public/factors/totp.d.ts +0 -189
  254. package/dist/component/public/factors/totp.d.ts.map +0 -1
  255. package/dist/component/public/factors/totp.js.map +0 -1
  256. package/dist/component/public/groups/core.d.ts +0 -137
  257. package/dist/component/public/groups/core.d.ts.map +0 -1
  258. package/dist/component/public/groups/core.js.map +0 -1
  259. package/dist/component/public/groups/invites.d.ts +0 -217
  260. package/dist/component/public/groups/invites.d.ts.map +0 -1
  261. package/dist/component/public/groups/invites.js.map +0 -1
  262. package/dist/component/public/groups/members.d.ts +0 -204
  263. package/dist/component/public/groups/members.d.ts.map +0 -1
  264. package/dist/component/public/groups/members.js.map +0 -1
  265. package/dist/component/public/identity/accounts.d.ts +0 -147
  266. package/dist/component/public/identity/accounts.d.ts.map +0 -1
  267. package/dist/component/public/identity/accounts.js.map +0 -1
  268. package/dist/component/public/identity/codes.d.ts +0 -104
  269. package/dist/component/public/identity/codes.d.ts.map +0 -1
  270. package/dist/component/public/identity/codes.js.map +0 -1
  271. package/dist/component/public/identity/sessions.d.ts +0 -128
  272. package/dist/component/public/identity/sessions.d.ts.map +0 -1
  273. package/dist/component/public/identity/sessions.js.map +0 -1
  274. package/dist/component/public/identity/tokens.d.ts +0 -169
  275. package/dist/component/public/identity/tokens.d.ts.map +0 -1
  276. package/dist/component/public/identity/tokens.js.map +0 -1
  277. package/dist/component/public/identity/users.d.ts +0 -212
  278. package/dist/component/public/identity/users.d.ts.map +0 -1
  279. package/dist/component/public/identity/users.js.map +0 -1
  280. package/dist/component/public/identity/verifiers.d.ts +0 -116
  281. package/dist/component/public/identity/verifiers.d.ts.map +0 -1
  282. package/dist/component/public/identity/verifiers.js.map +0 -1
  283. package/dist/component/public/security/keys.d.ts +0 -209
  284. package/dist/component/public/security/keys.d.ts.map +0 -1
  285. package/dist/component/public/security/keys.js.map +0 -1
  286. package/dist/component/public/security/limits.d.ts +0 -114
  287. package/dist/component/public/security/limits.d.ts.map +0 -1
  288. package/dist/component/public/security/limits.js.map +0 -1
  289. package/dist/component/public.d.ts +0 -28
  290. package/dist/component/public.d.ts.map +0 -1
  291. package/dist/component/schema.d.ts.map +0 -1
  292. package/dist/component/schema.js.map +0 -1
  293. package/dist/component/server/auth.d.ts +0 -447
  294. package/dist/component/server/auth.d.ts.map +0 -1
  295. package/dist/component/server/auth.js +0 -254
  296. package/dist/component/server/auth.js.map +0 -1
  297. package/dist/component/server/config.js +0 -121
  298. package/dist/component/server/config.js.map +0 -1
  299. package/dist/component/server/context.js +0 -53
  300. package/dist/component/server/context.js.map +0 -1
  301. package/dist/component/server/cookies.js +0 -47
  302. package/dist/component/server/cookies.js.map +0 -1
  303. package/dist/component/server/core.js +0 -576
  304. package/dist/component/server/core.js.map +0 -1
  305. package/dist/component/server/crypto.js +0 -56
  306. package/dist/component/server/crypto.js.map +0 -1
  307. package/dist/component/server/db.js +0 -87
  308. package/dist/component/server/db.js.map +0 -1
  309. package/dist/component/server/device.js +0 -152
  310. package/dist/component/server/device.js.map +0 -1
  311. package/dist/component/server/enterprise/config.js +0 -46
  312. package/dist/component/server/enterprise/config.js.map +0 -1
  313. package/dist/component/server/enterprise/domain.js +0 -974
  314. package/dist/component/server/enterprise/domain.js.map +0 -1
  315. package/dist/component/server/enterprise/http.js +0 -787
  316. package/dist/component/server/enterprise/http.js.map +0 -1
  317. package/dist/component/server/enterprise/oidc.js +0 -248
  318. package/dist/component/server/enterprise/oidc.js.map +0 -1
  319. package/dist/component/server/enterprise/policy.js +0 -85
  320. package/dist/component/server/enterprise/policy.js.map +0 -1
  321. package/dist/component/server/enterprise/saml.js.map +0 -1
  322. package/dist/component/server/enterprise/scim.js.map +0 -1
  323. package/dist/component/server/enterprise/shared.js +0 -51
  324. package/dist/component/server/enterprise/shared.js.map +0 -1
  325. package/dist/component/server/http.d.ts +0 -85
  326. package/dist/component/server/http.d.ts.map +0 -1
  327. package/dist/component/server/http.js +0 -351
  328. package/dist/component/server/http.js.map +0 -1
  329. package/dist/component/server/identity.js +0 -16
  330. package/dist/component/server/identity.js.map +0 -1
  331. package/dist/component/server/keys.js +0 -96
  332. package/dist/component/server/keys.js.map +0 -1
  333. package/dist/component/server/limits.js +0 -52
  334. package/dist/component/server/limits.js.map +0 -1
  335. package/dist/component/server/mutations/account.js +0 -46
  336. package/dist/component/server/mutations/account.js.map +0 -1
  337. package/dist/component/server/mutations/code.js +0 -68
  338. package/dist/component/server/mutations/code.js.map +0 -1
  339. package/dist/component/server/mutations/invalidate.js +0 -32
  340. package/dist/component/server/mutations/invalidate.js.map +0 -1
  341. package/dist/component/server/mutations/oauth.js +0 -116
  342. package/dist/component/server/mutations/oauth.js.map +0 -1
  343. package/dist/component/server/mutations/refresh.js +0 -119
  344. package/dist/component/server/mutations/refresh.js.map +0 -1
  345. package/dist/component/server/mutations/register.js +0 -87
  346. package/dist/component/server/mutations/register.js.map +0 -1
  347. package/dist/component/server/mutations/retrieve.js +0 -61
  348. package/dist/component/server/mutations/retrieve.js.map +0 -1
  349. package/dist/component/server/mutations/signature.js +0 -38
  350. package/dist/component/server/mutations/signature.js.map +0 -1
  351. package/dist/component/server/mutations/signin.js +0 -27
  352. package/dist/component/server/mutations/signin.js.map +0 -1
  353. package/dist/component/server/mutations/signout.js +0 -27
  354. package/dist/component/server/mutations/signout.js.map +0 -1
  355. package/dist/component/server/mutations/store/refs.js +0 -15
  356. package/dist/component/server/mutations/store/refs.js.map +0 -1
  357. package/dist/component/server/mutations/store.js +0 -70
  358. package/dist/component/server/mutations/store.js.map +0 -1
  359. package/dist/component/server/mutations/verifier.js +0 -18
  360. package/dist/component/server/mutations/verifier.js.map +0 -1
  361. package/dist/component/server/mutations/verify.js +0 -98
  362. package/dist/component/server/mutations/verify.js.map +0 -1
  363. package/dist/component/server/oauth.js +0 -242
  364. package/dist/component/server/oauth.js.map +0 -1
  365. package/dist/component/server/passkey.js +0 -415
  366. package/dist/component/server/passkey.js.map +0 -1
  367. package/dist/component/server/redirects.js +0 -40
  368. package/dist/component/server/redirects.js.map +0 -1
  369. package/dist/component/server/refresh.js +0 -99
  370. package/dist/component/server/refresh.js.map +0 -1
  371. package/dist/component/server/runtime.d.ts +0 -136
  372. package/dist/component/server/runtime.d.ts.map +0 -1
  373. package/dist/component/server/runtime.js +0 -456
  374. package/dist/component/server/runtime.js.map +0 -1
  375. package/dist/component/server/sessions.js +0 -71
  376. package/dist/component/server/sessions.js.map +0 -1
  377. package/dist/component/server/signin.js +0 -225
  378. package/dist/component/server/signin.js.map +0 -1
  379. package/dist/component/server/tokens.js +0 -17
  380. package/dist/component/server/tokens.js.map +0 -1
  381. package/dist/component/server/totp.js +0 -208
  382. package/dist/component/server/totp.js.map +0 -1
  383. package/dist/component/server/types.d.ts +0 -949
  384. package/dist/component/server/types.d.ts.map +0 -1
  385. package/dist/component/server/types.js +0 -79
  386. package/dist/component/server/types.js.map +0 -1
  387. package/dist/component/server/users.js +0 -123
  388. package/dist/component/server/users.js.map +0 -1
  389. package/dist/component/server/utils.js +0 -140
  390. package/dist/component/server/utils.js.map +0 -1
  391. package/dist/core/types.d.ts +0 -361
  392. package/dist/core/types.d.ts.map +0 -1
  393. package/dist/factors/device.js +0 -104
  394. package/dist/factors/device.js.map +0 -1
  395. package/dist/factors/passkey.js.map +0 -1
  396. package/dist/factors/totp.js.map +0 -1
  397. package/dist/providers/anonymous.d.ts.map +0 -1
  398. package/dist/providers/anonymous.js.map +0 -1
  399. package/dist/providers/credentials.d.ts.map +0 -1
  400. package/dist/providers/credentials.js.map +0 -1
  401. package/dist/providers/device.d.ts.map +0 -1
  402. package/dist/providers/device.js.map +0 -1
  403. package/dist/providers/email.d.ts.map +0 -1
  404. package/dist/providers/email.js.map +0 -1
  405. package/dist/providers/oauth.d.ts +0 -69
  406. package/dist/providers/oauth.d.ts.map +0 -1
  407. package/dist/providers/oauth.js +0 -43
  408. package/dist/providers/oauth.js.map +0 -1
  409. package/dist/providers/passkey.d.ts.map +0 -1
  410. package/dist/providers/passkey.js.map +0 -1
  411. package/dist/providers/password.d.ts.map +0 -1
  412. package/dist/providers/password.js.map +0 -1
  413. package/dist/providers/phone.d.ts.map +0 -1
  414. package/dist/providers/phone.js.map +0 -1
  415. package/dist/providers/sso.d.ts.map +0 -1
  416. package/dist/providers/sso.js.map +0 -1
  417. package/dist/providers/totp.d.ts.map +0 -1
  418. package/dist/providers/totp.js.map +0 -1
  419. package/dist/runtime/browser.js +0 -68
  420. package/dist/runtime/browser.js.map +0 -1
  421. package/dist/runtime/invite.js.map +0 -1
  422. package/dist/runtime/proxy.js +0 -70
  423. package/dist/runtime/proxy.js.map +0 -1
  424. package/dist/runtime/storage.js +0 -37
  425. package/dist/runtime/storage.js.map +0 -1
  426. package/dist/server/auth.d.ts.map +0 -1
  427. package/dist/server/auth.js.map +0 -1
  428. package/dist/server/config.d.ts +0 -1
  429. package/dist/server/config.js.map +0 -1
  430. package/dist/server/context.d.ts +0 -1
  431. package/dist/server/context.js.map +0 -1
  432. package/dist/server/cookies.d.ts +0 -1
  433. package/dist/server/cookies.js.map +0 -1
  434. package/dist/server/core.d.ts +0 -1315
  435. package/dist/server/core.d.ts.map +0 -1
  436. package/dist/server/core.js.map +0 -1
  437. package/dist/server/crypto.d.ts +0 -8
  438. package/dist/server/crypto.d.ts.map +0 -1
  439. package/dist/server/crypto.js.map +0 -1
  440. package/dist/server/db.d.ts +0 -1
  441. package/dist/server/db.js.map +0 -1
  442. package/dist/server/device.d.ts +0 -1
  443. package/dist/server/device.js.map +0 -1
  444. package/dist/server/enterprise/config.d.ts +0 -1
  445. package/dist/server/enterprise/config.js.map +0 -1
  446. package/dist/server/enterprise/domain.d.ts +0 -401
  447. package/dist/server/enterprise/domain.d.ts.map +0 -1
  448. package/dist/server/enterprise/domain.js +0 -974
  449. package/dist/server/enterprise/domain.js.map +0 -1
  450. package/dist/server/enterprise/http.d.ts +0 -26
  451. package/dist/server/enterprise/http.d.ts.map +0 -1
  452. package/dist/server/enterprise/http.js +0 -787
  453. package/dist/server/enterprise/http.js.map +0 -1
  454. package/dist/server/enterprise/oidc.d.ts +0 -1
  455. package/dist/server/enterprise/oidc.js +0 -248
  456. package/dist/server/enterprise/oidc.js.map +0 -1
  457. package/dist/server/enterprise/policy.d.ts +0 -1
  458. package/dist/server/enterprise/policy.js +0 -85
  459. package/dist/server/enterprise/policy.js.map +0 -1
  460. package/dist/server/enterprise/saml.d.ts +0 -1
  461. package/dist/server/enterprise/saml.js +0 -338
  462. package/dist/server/enterprise/saml.js.map +0 -1
  463. package/dist/server/enterprise/scim.d.ts +0 -1
  464. package/dist/server/enterprise/scim.js +0 -97
  465. package/dist/server/enterprise/scim.js.map +0 -1
  466. package/dist/server/enterprise/shared.d.ts +0 -5
  467. package/dist/server/enterprise/shared.d.ts.map +0 -1
  468. package/dist/server/enterprise/shared.js +0 -51
  469. package/dist/server/enterprise/shared.js.map +0 -1
  470. package/dist/server/enterprise/validators.d.ts +0 -1
  471. package/dist/server/enterprise/validators.js +0 -60
  472. package/dist/server/enterprise/validators.js.map +0 -1
  473. package/dist/server/http.d.ts.map +0 -1
  474. package/dist/server/http.js.map +0 -1
  475. package/dist/server/identity.d.ts +0 -1
  476. package/dist/server/identity.js.map +0 -1
  477. package/dist/server/keys.d.ts +0 -1
  478. package/dist/server/keys.js.map +0 -1
  479. package/dist/server/limits.d.ts +0 -1
  480. package/dist/server/limits.js.map +0 -1
  481. package/dist/server/mounts.d.ts.map +0 -1
  482. package/dist/server/mounts.js.map +0 -1
  483. package/dist/server/mutations/account.d.ts +0 -29
  484. package/dist/server/mutations/account.d.ts.map +0 -1
  485. package/dist/server/mutations/account.js.map +0 -1
  486. package/dist/server/mutations/code.d.ts +0 -30
  487. package/dist/server/mutations/code.d.ts.map +0 -1
  488. package/dist/server/mutations/code.js.map +0 -1
  489. package/dist/server/mutations/index.d.ts +0 -14
  490. package/dist/server/mutations/invalidate.d.ts +0 -20
  491. package/dist/server/mutations/invalidate.d.ts.map +0 -1
  492. package/dist/server/mutations/invalidate.js.map +0 -1
  493. package/dist/server/mutations/oauth.d.ts +0 -30
  494. package/dist/server/mutations/oauth.d.ts.map +0 -1
  495. package/dist/server/mutations/oauth.js.map +0 -1
  496. package/dist/server/mutations/refresh.d.ts +0 -21
  497. package/dist/server/mutations/refresh.d.ts.map +0 -1
  498. package/dist/server/mutations/refresh.js.map +0 -1
  499. package/dist/server/mutations/register.d.ts +0 -38
  500. package/dist/server/mutations/register.d.ts.map +0 -1
  501. package/dist/server/mutations/register.js.map +0 -1
  502. package/dist/server/mutations/retrieve.d.ts +0 -33
  503. package/dist/server/mutations/retrieve.d.ts.map +0 -1
  504. package/dist/server/mutations/retrieve.js.map +0 -1
  505. package/dist/server/mutations/signature.d.ts +0 -21
  506. package/dist/server/mutations/signature.d.ts.map +0 -1
  507. package/dist/server/mutations/signature.js.map +0 -1
  508. package/dist/server/mutations/signin.d.ts +0 -22
  509. package/dist/server/mutations/signin.d.ts.map +0 -1
  510. package/dist/server/mutations/signin.js.map +0 -1
  511. package/dist/server/mutations/signout.d.ts +0 -16
  512. package/dist/server/mutations/signout.d.ts.map +0 -1
  513. package/dist/server/mutations/signout.js.map +0 -1
  514. package/dist/server/mutations/store/refs.d.ts +0 -12
  515. package/dist/server/mutations/store/refs.d.ts.map +0 -1
  516. package/dist/server/mutations/store/refs.js.map +0 -1
  517. package/dist/server/mutations/store.d.ts +0 -306
  518. package/dist/server/mutations/store.d.ts.map +0 -1
  519. package/dist/server/mutations/store.js.map +0 -1
  520. package/dist/server/mutations/verifier.d.ts +0 -13
  521. package/dist/server/mutations/verifier.d.ts.map +0 -1
  522. package/dist/server/mutations/verifier.js.map +0 -1
  523. package/dist/server/mutations/verify.d.ts +0 -26
  524. package/dist/server/mutations/verify.d.ts.map +0 -1
  525. package/dist/server/mutations/verify.js.map +0 -1
  526. package/dist/server/oauth.d.ts +0 -1
  527. package/dist/server/oauth.js +0 -242
  528. package/dist/server/oauth.js.map +0 -1
  529. package/dist/server/passkey.d.ts +0 -27
  530. package/dist/server/passkey.d.ts.map +0 -1
  531. package/dist/server/passkey.js.map +0 -1
  532. package/dist/server/redirects.d.ts +0 -1
  533. package/dist/server/redirects.js.map +0 -1
  534. package/dist/server/refresh.d.ts +0 -1
  535. package/dist/server/refresh.js.map +0 -1
  536. package/dist/server/runtime.d.ts.map +0 -1
  537. package/dist/server/runtime.js.map +0 -1
  538. package/dist/server/sessions.d.ts +0 -1
  539. package/dist/server/sessions.js.map +0 -1
  540. package/dist/server/signin.d.ts +0 -1
  541. package/dist/server/signin.js.map +0 -1
  542. package/dist/server/ssr.d.ts.map +0 -1
  543. package/dist/server/ssr.js +0 -777
  544. package/dist/server/ssr.js.map +0 -1
  545. package/dist/server/templates.d.ts +0 -1
  546. package/dist/server/templates.js.map +0 -1
  547. package/dist/server/tokens.d.ts +0 -1
  548. package/dist/server/tokens.js.map +0 -1
  549. package/dist/server/totp.d.ts +0 -1
  550. package/dist/server/totp.js.map +0 -1
  551. package/dist/server/types.d.ts.map +0 -1
  552. package/dist/server/types.js.map +0 -1
  553. package/dist/server/users.d.ts +0 -1
  554. package/dist/server/users.js.map +0 -1
  555. package/dist/server/utils.d.ts +0 -1
  556. package/dist/server/utils.js +0 -140
  557. package/dist/server/utils.js.map +0 -1
  558. package/src/authorization/index.ts +0 -83
  559. package/src/cli/bin.ts +0 -5
  560. package/src/cli/command.ts +0 -70
  561. package/src/cli/index.ts +0 -1112
  562. package/src/cli/keys.ts +0 -23
  563. package/src/client/core/types.ts +0 -437
  564. package/src/client/factors/device.ts +0 -158
  565. package/src/client/factors/passkey.ts +0 -279
  566. package/src/client/factors/totp.ts +0 -150
  567. package/src/client/index.ts +0 -1124
  568. package/src/client/runtime/browser.ts +0 -112
  569. package/src/client/runtime/invite.ts +0 -63
  570. package/src/client/runtime/proxy.ts +0 -111
  571. package/src/client/runtime/storage.ts +0 -79
  572. package/src/component/_generated/api.ts +0 -96
  573. package/src/component/_generated/component.ts +0 -3774
  574. package/src/component/_generated/dataModel.ts +0 -60
  575. package/src/component/_generated/server.ts +0 -156
  576. package/src/component/convex.config.ts +0 -5
  577. package/src/component/functions.ts +0 -104
  578. package/src/component/index.ts +0 -42
  579. package/src/component/model.ts +0 -449
  580. package/src/component/public/enterprise/audit.ts +0 -125
  581. package/src/component/public/enterprise/core.ts +0 -355
  582. package/src/component/public/enterprise/domains.ts +0 -327
  583. package/src/component/public/enterprise/scim.ts +0 -397
  584. package/src/component/public/enterprise/secrets.ts +0 -133
  585. package/src/component/public/enterprise/webhooks.ts +0 -307
  586. package/src/component/public/factors/devices.ts +0 -224
  587. package/src/component/public/factors/passkeys.ts +0 -243
  588. package/src/component/public/factors/totp.ts +0 -259
  589. package/src/component/public/groups/core.ts +0 -481
  590. package/src/component/public/groups/invites.ts +0 -608
  591. package/src/component/public/groups/members.ts +0 -410
  592. package/src/component/public/identity/accounts.ts +0 -207
  593. package/src/component/public/identity/codes.ts +0 -149
  594. package/src/component/public/identity/sessions.ts +0 -210
  595. package/src/component/public/identity/tokens.ts +0 -251
  596. package/src/component/public/identity/users.ts +0 -355
  597. package/src/component/public/identity/verifiers.ts +0 -158
  598. package/src/component/public/security/keys.ts +0 -366
  599. package/src/component/public/security/limits.ts +0 -174
  600. package/src/component/public.ts +0 -27
  601. package/src/component/schema.ts +0 -505
  602. package/src/providers/anonymous.ts +0 -99
  603. package/src/providers/credentials.ts +0 -102
  604. package/src/providers/device.ts +0 -87
  605. package/src/providers/email.ts +0 -99
  606. package/src/providers/index.ts +0 -31
  607. package/src/providers/oauth.ts +0 -117
  608. package/src/providers/passkey.ts +0 -77
  609. package/src/providers/password.ts +0 -441
  610. package/src/providers/phone.ts +0 -93
  611. package/src/providers/sso.ts +0 -54
  612. package/src/providers/totp.ts +0 -62
  613. package/src/samlify.d.ts +0 -53
  614. package/src/server/auth.ts +0 -949
  615. package/src/server/config.ts +0 -200
  616. package/src/server/context.ts +0 -90
  617. package/src/server/cookies.ts +0 -49
  618. package/src/server/core.ts +0 -2004
  619. package/src/server/crypto.ts +0 -90
  620. package/src/server/db.ts +0 -203
  621. package/src/server/device.ts +0 -254
  622. package/src/server/enterprise/config.ts +0 -51
  623. package/src/server/enterprise/domain.ts +0 -1739
  624. package/src/server/enterprise/http.ts +0 -1331
  625. package/src/server/enterprise/oidc.ts +0 -500
  626. package/src/server/enterprise/policy.ts +0 -128
  627. package/src/server/enterprise/saml.ts +0 -578
  628. package/src/server/enterprise/scim.ts +0 -135
  629. package/src/server/enterprise/shared.ts +0 -134
  630. package/src/server/enterprise/validators.ts +0 -93
  631. package/src/server/http.ts +0 -790
  632. package/src/server/identity.ts +0 -18
  633. package/src/server/index.ts +0 -40
  634. package/src/server/keys.ts +0 -158
  635. package/src/server/limits.ts +0 -107
  636. package/src/server/mounts.ts +0 -924
  637. package/src/server/mutations/account.ts +0 -62
  638. package/src/server/mutations/code.ts +0 -119
  639. package/src/server/mutations/index.ts +0 -13
  640. package/src/server/mutations/invalidate.ts +0 -50
  641. package/src/server/mutations/oauth.ts +0 -243
  642. package/src/server/mutations/refresh.ts +0 -299
  643. package/src/server/mutations/register.ts +0 -155
  644. package/src/server/mutations/retrieve.ts +0 -109
  645. package/src/server/mutations/signature.ts +0 -57
  646. package/src/server/mutations/signin.ts +0 -54
  647. package/src/server/mutations/signout.ts +0 -43
  648. package/src/server/mutations/store/refs.ts +0 -10
  649. package/src/server/mutations/store.ts +0 -123
  650. package/src/server/mutations/verifier.ts +0 -34
  651. package/src/server/mutations/verify.ts +0 -200
  652. package/src/server/oauth.ts +0 -418
  653. package/src/server/passkey.ts +0 -838
  654. package/src/server/redirects.ts +0 -59
  655. package/src/server/refresh.ts +0 -218
  656. package/src/server/runtime.ts +0 -918
  657. package/src/server/sessions.ts +0 -132
  658. package/src/server/signin.ts +0 -445
  659. package/src/server/ssr.ts +0 -1747
  660. package/src/server/templates.ts +0 -82
  661. package/src/server/tokens.ts +0 -35
  662. package/src/server/totp.ts +0 -399
  663. package/src/server/types.ts +0 -1942
  664. package/src/server/users.ts +0 -291
  665. package/src/server/utils.ts +0 -220
  666. /package/dist/{runtime → client/runtime}/invite.js +0 -0
@@ -1,242 +0,0 @@
1
- import { isLocalHost, logWithLevel } from "./utils.js";
2
- import { SHARED_COOKIE_OPTIONS } from "./cookies.js";
3
- import { Fx } from "@robelest/fx";
4
- import { Cv } from "@robelest/fx/convex";
5
- import * as arctic from "arctic";
6
-
7
- //#region src/server/oauth.ts
8
- /**
9
- * Arctic-based OAuth flow implementation.
10
- *
11
- * Uses Arctic for OAuth provider integration.
12
- *
13
- * All functions return `Fx<A, ConvexError<any>>` composed via `Fx.gen` pipelines.
14
- *
15
- * @internal
16
- * @module
17
- */
18
- const COOKIE_TTL = 900;
19
- function oauthCookieName(type, providerId) {
20
- return (!isLocalHost(process.env.CONVEX_SITE_URL) ? "__Host-" : "") + providerId + "OAuth" + type;
21
- }
22
- function createCookie(type, providerId, value) {
23
- const expires = /* @__PURE__ */ new Date();
24
- expires.setTime(expires.getTime() + COOKIE_TTL * 1e3);
25
- return {
26
- name: oauthCookieName(type, providerId),
27
- value,
28
- options: {
29
- ...SHARED_COOKIE_OPTIONS,
30
- expires
31
- }
32
- };
33
- }
34
- function clearCookie(type, providerId) {
35
- return {
36
- name: oauthCookieName(type, providerId),
37
- value: "",
38
- options: {
39
- ...SHARED_COOKIE_OPTIONS,
40
- maxAge: 0
41
- }
42
- };
43
- }
44
- /**
45
- * Creates a signature string from the OAuth state parameters.
46
- * This is stored in the verifier table and validated during callback.
47
- */
48
- /** @internal */
49
- function getAuthorizationSignature({ codeVerifier, state }) {
50
- return [codeVerifier, state].filter((param) => param !== void 0).join(" ");
51
- }
52
- /**
53
- * Detect whether an Arctic provider uses PKCE by checking the arity
54
- * of `createAuthorizationURL`. PKCE providers take 3 args
55
- * (state, codeVerifier, scopes), non-PKCE take 2 (state, scopes).
56
- */
57
- function isPKCEProvider(provider) {
58
- return typeof provider.createAuthorizationURL === "function" && provider.createAuthorizationURL.length >= 3;
59
- }
60
- /**
61
- * Exchange the authorization code for tokens via Arctic.
62
- * Maps Arctic-specific errors to typed `ConvexError<any>` failures.
63
- */
64
- function exchangeCode(arcticProvider, code, codeVerifier) {
65
- return Fx.from({
66
- ok: () => isPKCEProvider(arcticProvider) ? arcticProvider.validateAuthorizationCode(code, codeVerifier) : arcticProvider.validateAuthorizationCode(code),
67
- err: (e) => {
68
- if (e instanceof arctic.OAuth2RequestError) return Cv.error({
69
- code: "OAUTH_PROVIDER_ERROR",
70
- message: `Token exchange failed: ${e.code}`
71
- });
72
- if (e instanceof arctic.ArcticFetchError) return Cv.error({
73
- code: "OAUTH_PROVIDER_ERROR",
74
- message: `Network error during token exchange: ${e.message}`
75
- });
76
- return Cv.error({
77
- code: "OAUTH_PROVIDER_ERROR",
78
- message: `Unexpected error during token exchange: ${e instanceof Error ? e.message : String(e)}`
79
- });
80
- }
81
- }).pipe(Fx.chain((tokens) => {
82
- return Fx.succeed(tokens);
83
- }));
84
- }
85
- /**
86
- * Extract the user profile from tokens using the config callback,
87
- * OIDC auto-decode, or fail if neither is available.
88
- */
89
- function extractProfile(providerId, oauthConfig, tokens) {
90
- const hasIdToken = "id_token" in tokens.data && typeof tokens.data.id_token === "string";
91
- const profileSource = oauthConfig.profile ? { source: "callback" } : hasIdToken ? { source: "idToken" } : { source: "missing" };
92
- return Fx.match(profileSource, profileSource.source, {
93
- callback: (_profileSource) => Fx.from({
94
- ok: () => oauthConfig.profile(tokens),
95
- err: (e) => Cv.error({
96
- code: "OAUTH_INVALID_PROFILE",
97
- message: `Profile callback threw: ${e instanceof Error ? e.message : String(e)}`
98
- })
99
- }),
100
- idToken: (_profileSource) => {
101
- const claims = arctic.decodeIdToken(tokens.idToken());
102
- return Fx.succeed({
103
- id: claims.sub ?? crypto.randomUUID(),
104
- name: claims.name ?? void 0,
105
- email: claims.email ?? void 0,
106
- image: claims.picture ?? void 0
107
- });
108
- },
109
- missing: (_profileSource) => Cv.fail({
110
- code: "OAUTH_INVALID_PROFILE",
111
- message: `Provider "${providerId}" does not return an ID token. Add a \`profile\` callback in the OAuth() config to extract user info from the access token.`
112
- })
113
- });
114
- }
115
- /**
116
- * Validate that the profile has a non-empty string `id`.
117
- */
118
- function validateProfileId(providerId, profile) {
119
- return typeof profile.id === "string" && profile.id ? Fx.succeed(profile) : Cv.fail({
120
- code: "OAUTH_INVALID_PROFILE",
121
- message: `The profile callback for "${providerId}" must return an object with a string \`id\` field.`
122
- });
123
- }
124
- /**
125
- * Create an OAuth authorization URL using an Arctic provider.
126
- *
127
- * Handles PKCE detection, state generation, and cookie creation.
128
- */
129
- /** @internal */
130
- async function createOAuthAuthorizationURL(providerId, arcticProvider, oauthConfig) {
131
- const state = arctic.generateState();
132
- const cookies = [];
133
- let codeVerifier;
134
- const scopes = oauthConfig.scopes ?? [];
135
- let url;
136
- if (isPKCEProvider(arcticProvider)) {
137
- codeVerifier = arctic.generateCodeVerifier();
138
- url = arcticProvider.createAuthorizationURL(state, codeVerifier, scopes);
139
- cookies.push(createCookie("pkce", providerId, codeVerifier));
140
- } else url = arcticProvider.createAuthorizationURL(state, scopes);
141
- cookies.push(createCookie("state", providerId, state));
142
- if (oauthConfig.nonce === true) {
143
- const nonce = arctic.generateState();
144
- url.searchParams.set("nonce", nonce);
145
- cookies.push(createCookie("nonce", providerId, nonce));
146
- }
147
- logWithLevel("DEBUG", "OAuth authorization URL created", {
148
- url: url.toString(),
149
- providerId,
150
- hasPKCE: !!codeVerifier
151
- });
152
- const signature = getAuthorizationSignature({
153
- codeVerifier,
154
- state
155
- });
156
- return {
157
- redirect: url.toString(),
158
- cookies,
159
- signature
160
- };
161
- }
162
- /**
163
- * Handle the OAuth callback: validate state, exchange code for tokens,
164
- * extract profile.
165
- *
166
- * Returns `Fx<CallbackResult, ConvexError<any>>` composed via `Fx.gen`.
167
- */
168
- /** @internal */
169
- function handleOAuthCallback(providerId, arcticProvider, oauthConfig, params, cookies) {
170
- return Fx.gen(function* () {
171
- const resCookies = [];
172
- const storedState = cookies[oauthCookieName("state", providerId)];
173
- const returnedState = params.state;
174
- yield* Fx.guard(!storedState || !returnedState || storedState !== returnedState, Cv.fail({
175
- code: "OAUTH_INVALID_STATE",
176
- message: "Invalid OAuth state. Please try signing in again."
177
- }));
178
- resCookies.push(clearCookie("state", providerId));
179
- if (params.error) {
180
- const cause = {
181
- providerId,
182
- error: params.error,
183
- error_description: params.error_description
184
- };
185
- logWithLevel("DEBUG", "OAuthCallbackError", cause);
186
- yield* Cv.fail({
187
- code: "OAUTH_PROVIDER_ERROR",
188
- message: "OAuth provider returned an error",
189
- cause: JSON.stringify(cause)
190
- });
191
- }
192
- const code = yield* params.code != null ? Fx.succeed(params.code) : Cv.fail({
193
- code: "OAUTH_PROVIDER_ERROR",
194
- message: "Missing authorization code in callback"
195
- });
196
- let codeVerifier;
197
- if (isPKCEProvider(arcticProvider)) {
198
- const pkceCookieName = oauthCookieName("pkce", providerId);
199
- codeVerifier = yield* cookies[pkceCookieName] != null ? Fx.succeed(cookies[pkceCookieName]) : Cv.fail({
200
- code: "OAUTH_MISSING_VERIFIER",
201
- message: "Missing PKCE verifier cookie for OAuth callback"
202
- });
203
- resCookies.push(clearCookie("pkce", providerId));
204
- }
205
- let nonce;
206
- if (oauthConfig.nonce === true) {
207
- const nonceCookieName = oauthCookieName("nonce", providerId);
208
- nonce = yield* cookies[nonceCookieName] != null ? Fx.succeed(cookies[nonceCookieName]) : Cv.fail({
209
- code: "OAUTH_PROVIDER_ERROR",
210
- message: "Missing nonce cookie for OAuth callback"
211
- });
212
- resCookies.push(clearCookie("nonce", providerId));
213
- }
214
- const tokens = yield* exchangeCode(arcticProvider, code, codeVerifier);
215
- if (oauthConfig.validateTokens !== void 0) yield* Fx.from({
216
- ok: () => oauthConfig.validateTokens(tokens, { nonce }),
217
- err: (e) => Cv.error({
218
- code: "OAUTH_PROVIDER_ERROR",
219
- message: `Token validation failed: ${e instanceof Error ? e.message : String(e)}`
220
- })
221
- });
222
- const profile = yield* validateProfileId(providerId, yield* extractProfile(providerId, oauthConfig, tokens));
223
- logWithLevel("DEBUG", "OAuth callback profile extracted", {
224
- providerId,
225
- profileId: profile.id
226
- });
227
- const signature = getAuthorizationSignature({
228
- codeVerifier,
229
- state: storedState
230
- });
231
- return {
232
- profile,
233
- providerAccountId: profile.id,
234
- cookies: resCookies,
235
- signature
236
- };
237
- });
238
- }
239
-
240
- //#endregion
241
- export { createOAuthAuthorizationURL, getAuthorizationSignature, handleOAuthCallback };
242
- //# sourceMappingURL=oauth.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"oauth.js","names":[],"sources":["../../src/server/oauth.ts"],"sourcesContent":["/**\n * Arctic-based OAuth flow implementation.\n *\n * Uses Arctic for OAuth provider integration.\n *\n * All functions return `Fx<A, ConvexError<any>>` composed via `Fx.gen` pipelines.\n *\n * @internal\n * @module\n */\n\nimport { Fx } from \"@robelest/fx\";\nimport { Cv } from \"@robelest/fx/convex\";\nimport * as arctic from \"arctic\";\nimport type { ConvexError } from \"convex/values\";\n\nimport { SHARED_COOKIE_OPTIONS } from \"./cookies\";\nimport type { OAuthProfile } from \"./types\";\nimport { logWithLevel } from \"./utils\";\nimport { isLocalHost } from \"./utils\";\n\ntype OAuthProviderConfigLike = {\n scopes?: string[];\n profile?: (tokens: arctic.OAuth2Tokens) => Promise<OAuthProfile>;\n nonce?: boolean;\n validateTokens?: (\n tokens: arctic.OAuth2Tokens,\n ctx: { nonce?: string },\n ) => Promise<void>;\n};\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** A cookie to be set on the HTTP response. */\n/** @internal */\nexport interface OAuthCookie {\n name: string;\n value: string;\n options: Record<string, unknown>;\n}\n\n/** Result of creating an authorization URL. */\n/** @internal */\nexport interface AuthorizationResult {\n redirect: string;\n cookies: OAuthCookie[];\n signature: string;\n}\n\n/** Result of handling an OAuth callback. */\n/** @internal */\nexport interface CallbackResult {\n profile: OAuthProfile;\n providerAccountId: string;\n cookies: OAuthCookie[];\n signature: string;\n}\n\n// ============================================================================\n// Cookie helpers\n// ============================================================================\n\nconst COOKIE_TTL = 60 * 15; // 15 minutes\n\nfunction oauthCookieName(type: \"state\" | \"pkce\" | \"nonce\", providerId: string) {\n const prefix = !isLocalHost(process.env.CONVEX_SITE_URL) ? \"__Host-\" : \"\";\n return prefix + providerId + \"OAuth\" + type;\n}\n\nfunction createCookie(\n type: \"state\" | \"pkce\" | \"nonce\",\n providerId: string,\n value: string,\n): OAuthCookie {\n const expires = new Date();\n expires.setTime(expires.getTime() + COOKIE_TTL * 1000);\n return {\n name: oauthCookieName(type, providerId),\n value,\n options: { ...SHARED_COOKIE_OPTIONS, expires },\n };\n}\n\nfunction clearCookie(\n type: \"state\" | \"pkce\" | \"nonce\",\n providerId: string,\n): OAuthCookie {\n return {\n name: oauthCookieName(type, providerId),\n value: \"\",\n options: { ...SHARED_COOKIE_OPTIONS, maxAge: 0 },\n };\n}\n\n// ============================================================================\n// Signature (ConvexAuth-specific verifier mechanism)\n// ============================================================================\n\n/**\n * Creates a signature string from the OAuth state parameters.\n * This is stored in the verifier table and validated during callback.\n */\n/** @internal */\nexport function getAuthorizationSignature({\n codeVerifier,\n state,\n}: {\n codeVerifier?: string;\n state?: string;\n}) {\n return [codeVerifier, state].filter((param) => param !== undefined).join(\" \");\n}\n\n// ============================================================================\n// PKCE Detection\n// ============================================================================\n\n/**\n * Detect whether an Arctic provider uses PKCE by checking the arity\n * of `createAuthorizationURL`. PKCE providers take 3 args\n * (state, codeVerifier, scopes), non-PKCE take 2 (state, scopes).\n */\nfunction isPKCEProvider(provider: any): boolean {\n return (\n typeof provider.createAuthorizationURL === \"function\" &&\n provider.createAuthorizationURL.length >= 3\n );\n}\n\n// ============================================================================\n// Token exchange — wraps Arctic's validateAuthorizationCode\n// ============================================================================\n\n/**\n * Exchange the authorization code for tokens via Arctic.\n * Maps Arctic-specific errors to typed `ConvexError<any>` failures.\n */\nfunction exchangeCode(\n arcticProvider: any,\n code: string,\n codeVerifier: string | undefined,\n): Fx<arctic.OAuth2Tokens, ConvexError<any>> {\n return Fx.from({\n ok: () =>\n isPKCEProvider(arcticProvider)\n ? arcticProvider.validateAuthorizationCode(code, codeVerifier)\n : arcticProvider.validateAuthorizationCode(code),\n err: (e) => {\n if (e instanceof arctic.OAuth2RequestError) {\n return Cv.error({\n code: \"OAUTH_PROVIDER_ERROR\",\n message: `Token exchange failed: ${e.code}`,\n });\n }\n if (e instanceof arctic.ArcticFetchError) {\n return Cv.error({\n code: \"OAUTH_PROVIDER_ERROR\",\n message: `Network error during token exchange: ${e.message}`,\n });\n }\n // Unknown error — treat as unrecoverable defect; we surface it as\n // an ConvexError<any> here so the pipeline type stays Fx<_, ConvexError<any>>.\n // The original `throw e` re-throw is replicated via Fx.fatal below.\n return Cv.error({\n code: \"OAUTH_PROVIDER_ERROR\",\n message: `Unexpected error during token exchange: ${e instanceof Error ? e.message : String(e)}`,\n });\n },\n }).pipe(\n Fx.chain((tokens) => {\n // If the original error was neither OAuth2RequestError nor\n // ArcticFetchError the old code re-threw it raw. We replicate that\n // by checking whether we created an \"Unexpected\" marker message\n // — but since `Fx.from` already mapped it, we just pass through.\n return Fx.succeed(tokens);\n }),\n );\n}\n\n/**\n * Extract the user profile from tokens using the config callback,\n * OIDC auto-decode, or fail if neither is available.\n */\nfunction extractProfile(\n providerId: string,\n oauthConfig: OAuthProviderConfigLike,\n tokens: arctic.OAuth2Tokens,\n): Fx<OAuthProfile, ConvexError<any>> {\n const hasIdToken =\n \"id_token\" in tokens.data &&\n typeof (tokens.data as any).id_token === \"string\";\n const profileSource = oauthConfig.profile\n ? { source: \"callback\" as const }\n : hasIdToken\n ? { source: \"idToken\" as const }\n : { source: \"missing\" as const };\n\n return Fx.match(profileSource, profileSource.source, {\n callback: (_profileSource) =>\n Fx.from({\n ok: () => oauthConfig.profile!(tokens),\n err: (e) =>\n Cv.error({\n code: \"OAUTH_INVALID_PROFILE\",\n message: `Profile callback threw: ${e instanceof Error ? e.message : String(e)}`,\n }),\n }),\n idToken: (_profileSource) => {\n const claims = arctic.decodeIdToken(tokens.idToken()) as Record<\n string,\n unknown\n >;\n return Fx.succeed({\n id: (claims.sub as string) ?? crypto.randomUUID(),\n name: (claims.name as string) ?? undefined,\n email: (claims.email as string) ?? undefined,\n image: (claims.picture as string) ?? undefined,\n });\n },\n missing: (_profileSource) =>\n Cv.fail({\n code: \"OAUTH_INVALID_PROFILE\",\n message:\n `Provider \"${providerId}\" does not return an ID token. ` +\n `Add a \\`profile\\` callback in the OAuth() config to extract user info from the access token.`,\n }),\n });\n}\n\n/**\n * Validate that the profile has a non-empty string `id`.\n */\nfunction validateProfileId(\n providerId: string,\n profile: OAuthProfile,\n): Fx<OAuthProfile, ConvexError<any>> {\n return typeof profile.id === \"string\" && profile.id\n ? Fx.succeed(profile)\n : Cv.fail({\n code: \"OAUTH_INVALID_PROFILE\",\n message: `The profile callback for \"${providerId}\" must return an object with a string \\`id\\` field.`,\n });\n}\n\n// ============================================================================\n// Authorization URL creation\n// ============================================================================\n\n/**\n * Create an OAuth authorization URL using an Arctic provider.\n *\n * Handles PKCE detection, state generation, and cookie creation.\n */\n/** @internal */\nexport async function createOAuthAuthorizationURL(\n providerId: string,\n arcticProvider: any,\n oauthConfig: OAuthProviderConfigLike,\n): Promise<AuthorizationResult> {\n const state = arctic.generateState();\n const cookies: OAuthCookie[] = [];\n let codeVerifier: string | undefined;\n\n const scopes = oauthConfig.scopes ?? [];\n\n let url: URL;\n\n if (isPKCEProvider(arcticProvider)) {\n codeVerifier = arctic.generateCodeVerifier();\n url = arcticProvider.createAuthorizationURL(state, codeVerifier, scopes);\n cookies.push(createCookie(\"pkce\", providerId, codeVerifier));\n } else {\n url = arcticProvider.createAuthorizationURL(state, scopes);\n }\n\n cookies.push(createCookie(\"state\", providerId, state));\n\n if (oauthConfig.nonce === true) {\n const nonce = arctic.generateState();\n url.searchParams.set(\"nonce\", nonce);\n cookies.push(createCookie(\"nonce\", providerId, nonce));\n }\n\n logWithLevel(\"DEBUG\", \"OAuth authorization URL created\", {\n url: url.toString(),\n providerId,\n hasPKCE: !!codeVerifier,\n });\n\n const signature = getAuthorizationSignature({ codeVerifier, state });\n\n return {\n redirect: url.toString(),\n cookies,\n signature,\n };\n}\n\n// ============================================================================\n// OAuth callback handling\n// ============================================================================\n\n/**\n * Handle the OAuth callback: validate state, exchange code for tokens,\n * extract profile.\n *\n * Returns `Fx<CallbackResult, ConvexError<any>>` composed via `Fx.gen`.\n */\n/** @internal */\nexport function handleOAuthCallback(\n providerId: string,\n arcticProvider: any,\n oauthConfig: OAuthProviderConfigLike,\n params: Record<string, string>,\n cookies: Record<string, string | undefined>,\n): Fx<CallbackResult, ConvexError<any>> {\n return Fx.gen(function* () {\n const resCookies: OAuthCookie[] = [];\n\n // 1. Validate state\n const stateCookieName = oauthCookieName(\"state\", providerId);\n const storedState = cookies[stateCookieName];\n const returnedState = params.state;\n\n yield* Fx.guard(\n !storedState || !returnedState || storedState !== returnedState,\n Cv.fail({\n code: \"OAUTH_INVALID_STATE\",\n message: \"Invalid OAuth state. Please try signing in again.\",\n }),\n );\n resCookies.push(clearCookie(\"state\", providerId));\n\n // Check for error from provider\n if (params.error) {\n const cause = {\n providerId,\n error: params.error,\n error_description: params.error_description,\n };\n logWithLevel(\"DEBUG\", \"OAuthCallbackError\", cause);\n yield* Cv.fail({\n code: \"OAUTH_PROVIDER_ERROR\",\n message: \"OAuth provider returned an error\",\n cause: JSON.stringify(cause),\n });\n }\n\n // 2. Get code\n const code = yield* params.code != null\n ? Fx.succeed(params.code)\n : Cv.fail({\n code: \"OAUTH_PROVIDER_ERROR\",\n message: \"Missing authorization code in callback\",\n });\n\n // 3. Read PKCE verifier from cookie if applicable\n let codeVerifier: string | undefined;\n if (isPKCEProvider(arcticProvider)) {\n const pkceCookieName = oauthCookieName(\"pkce\", providerId);\n codeVerifier = yield* cookies[pkceCookieName] != null\n ? Fx.succeed(cookies[pkceCookieName]!)\n : Cv.fail({\n code: \"OAUTH_MISSING_VERIFIER\",\n message: \"Missing PKCE verifier cookie for OAuth callback\",\n });\n resCookies.push(clearCookie(\"pkce\", providerId));\n }\n\n let nonce: string | undefined;\n if (oauthConfig.nonce === true) {\n const nonceCookieName = oauthCookieName(\"nonce\", providerId);\n nonce = yield* cookies[nonceCookieName] != null\n ? Fx.succeed(cookies[nonceCookieName]!)\n : Cv.fail({\n code: \"OAUTH_PROVIDER_ERROR\",\n message: \"Missing nonce cookie for OAuth callback\",\n });\n resCookies.push(clearCookie(\"nonce\", providerId));\n }\n\n // 4. Exchange code for tokens\n const tokens = yield* exchangeCode(arcticProvider, code, codeVerifier);\n\n if (oauthConfig.validateTokens !== undefined) {\n yield* Fx.from({\n ok: () => oauthConfig.validateTokens!(tokens, { nonce }),\n err: (e) =>\n Cv.error({\n code: \"OAUTH_PROVIDER_ERROR\",\n message: `Token validation failed: ${e instanceof Error ? e.message : String(e)}`,\n }),\n });\n }\n\n // 5. Extract profile\n const rawProfile = yield* extractProfile(providerId, oauthConfig, tokens);\n const profile = yield* validateProfileId(providerId, rawProfile);\n\n logWithLevel(\"DEBUG\", \"OAuth callback profile extracted\", {\n providerId,\n profileId: profile.id,\n });\n\n // 6. Compute signature for verifier validation\n const state = storedState!;\n const signature = getAuthorizationSignature({ codeVerifier, state });\n\n return {\n profile,\n providerAccountId: profile.id,\n cookies: resCookies,\n signature,\n };\n });\n}\n"],"mappings":"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"}
@@ -1,27 +0,0 @@
1
- import { AuthDataModel, GenericActionCtxWithAuthConfig, PasskeyProviderConfig, SessionInfo } from "./types.js";
2
- import { Fx } from "@robelest/fx";
3
- import { ConvexError } from "convex/values";
4
-
5
- //#region src/server/passkey.d.ts
6
- type EnrichedActionCtx = GenericActionCtxWithAuthConfig<AuthDataModel>;
7
- /** Result type for all passkey flows. */
8
- type PasskeyResult = {
9
- kind: "signedIn";
10
- signedIn: SessionInfo | null;
11
- } | {
12
- kind: "passkeyOptions";
13
- options: Record<string, any>;
14
- verifier: string;
15
- };
16
- /**
17
- * Main passkey handler dispatched from signIn.ts.
18
- *
19
- * Routes to the appropriate phase based on `params.flow` via `dispatchFx`.
20
- */
21
- declare function handlePasskeyFx(ctx: EnrichedActionCtx, provider: PasskeyProviderConfig, args: {
22
- params?: Record<string, any>;
23
- verifier?: string;
24
- }): Fx<PasskeyResult, ConvexError<any>>;
25
- //#endregion
26
- export { handlePasskeyFx };
27
- //# sourceMappingURL=passkey.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"passkey.d.ts","names":[],"sources":["../../src/server/passkey.ts"],"mappings":";;;;;KAoEK,iBAAA,GAAoB,8BAAA,CAA+B,aAAA;;KAwLnD,aAAA;EACC,IAAA;EAAkB,QAAA,EAAU,WAAA;AAAA;EAC5B,IAAA;EAAwB,OAAA,EAAS,MAAA;EAAqB,QAAA;AAAA;;;;;;iBAkD5C,eAAA,CACd,GAAA,EAAK,iBAAA,EACL,QAAA,EAAU,qBAAA,EACV,IAAA;EACE,MAAA,GAAS,MAAA;EACT,QAAA;AAAA,IAED,EAAA,CAAO,aAAA,EAAe,WAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"passkey.js","names":["hasSiteUrl","hasRpId","siteUrl"],"sources":["../../src/server/passkey.ts"],"sourcesContent":["/**\n * Server-side WebAuthn ceremony logic for passkey authentication.\n *\n * Handles the four phases of the WebAuthn flow:\n * 1. registerOptions — generate PublicKeyCredentialCreationOptions\n * 2. registerVerify — verify attestation and store credential\n * 3. authOptions — generate PublicKeyCredentialRequestOptions\n * 4. authVerify — verify assertion signature and sign in\n *\n * Uses `@oslojs/webauthn` for attestation/assertion parsing and\n * `@oslojs/crypto` for signature verification.\n *\n * All functions return `Fx<A, ConvexError<any>>` composed via `Fx.chain` pipelines.\n *\n * @module\n */\n\nimport {\n p256,\n verifyECDSASignature,\n decodeSEC1PublicKey,\n decodePKIXECDSASignature,\n} from \"@oslojs/crypto/ecdsa\";\nimport {\n RSAPublicKey,\n decodePKCS1RSAPublicKey,\n sha256ObjectIdentifier,\n verifyRSASSAPKCS1v15Signature,\n} from \"@oslojs/crypto/rsa\";\nimport { sha256 } from \"@oslojs/crypto/sha2\";\nimport {\n encodeBase64urlNoPadding,\n decodeBase64urlIgnorePadding,\n} from \"@oslojs/encoding\";\nimport {\n parseAttestationObject,\n parseClientDataJSON,\n parseAuthenticatorData,\n createAssertionSignatureMessage,\n ClientDataType,\n coseAlgorithmES256,\n coseAlgorithmRS256,\n COSEKeyType,\n} from \"@oslojs/webauthn\";\nimport type { Fx as FxType } from \"@robelest/fx\";\nimport { Fx } from \"@robelest/fx\";\nimport { Cv } from \"@robelest/fx/convex\";\nimport type { ConvexError } from \"convex/values\";\n\nimport { authDb } from \"./db\";\nimport { userIdFromIdentitySubject } from \"./identity\";\nimport { callSignIn, callVerifier } from \"./mutations/index\";\nimport { callVerifierSignature } from \"./mutations/signature\";\nimport { PasskeyProviderConfig, GenericActionCtxWithAuthConfig } from \"./types\";\nimport {\n AuthDataModel,\n SessionInfo,\n queryUserById,\n queryUserByVerifiedEmail,\n queryPasskeysByUserId,\n queryPasskeyByCredentialId,\n queryVerifierById,\n mutatePasskeyInsert,\n mutatePasskeyUpdateCounter,\n mutateVerifierDelete,\n} from \"./types\";\nimport { siteUrlsFromEnv } from \"./utils\";\n\ntype EnrichedActionCtx = GenericActionCtxWithAuthConfig<AuthDataModel>;\n\n// ============================================================================\n// Resolve RP options — Fx pipeline with validation\n// ============================================================================\n\n/** Resolved relying party configuration. */\ninterface RpOptions {\n rpName: string;\n rpId: string;\n origin: string | string[];\n attestation: string;\n userVerification: string;\n residentKey: string;\n authenticatorAttachment?: string;\n algorithms: number[];\n challengeExpirationMs: number;\n}\n\n/**\n * Resolve passkey relying party options from provider config and environment.\n *\n * Returns `Fx<RpOptions, ConvexError<any>>` — fails if neither SITE_URL nor rpId\n * is configured.\n */\nconst resolveRpOptionsFx = (\n provider: PasskeyProviderConfig,\n): FxType<RpOptions, ConvexError<any>> => {\n const configuredSiteUrls =\n process.env.SITE_URL === undefined ? null : siteUrlsFromEnv();\n const siteUrl = configuredSiteUrls?.primaryUrl;\n const hasSiteUrl = siteUrl !== undefined && siteUrl !== \"\";\n const hasRpId = provider.options.rpId !== undefined;\n\n return Fx.succeed({ siteUrl, hasSiteUrl, hasRpId }).pipe(\n Fx.chain(({ siteUrl, hasSiteUrl, hasRpId }) =>\n !hasSiteUrl && !hasRpId\n ? Cv.fail({\n code: \"PASSKEY_MISSING_CONFIG\",\n message:\n \"Passkey provider requires SITE_URL env var (your frontend URL) \" +\n \"or explicit rpId / origin in the provider config. \" +\n \"CONVEX_SITE_URL cannot be used because WebAuthn RP ID must match the frontend domain.\",\n })\n : Fx.succeed(siteUrl),\n ),\n Fx.map((siteUrl) => {\n const siteHostname = siteUrl ? new URL(siteUrl).hostname : undefined;\n const defaultOrigin = configuredSiteUrls?.allowedUrls ?? siteUrl;\n return {\n rpName: provider.options.rpName ?? siteHostname ?? \"localhost\",\n rpId: provider.options.rpId ?? siteHostname ?? \"localhost\",\n origin: provider.options.origin ?? defaultOrigin ?? \"http://localhost\",\n attestation: provider.options.attestation ?? \"none\",\n userVerification: provider.options.userVerification ?? \"required\",\n residentKey: provider.options.residentKey ?? \"preferred\",\n authenticatorAttachment: provider.options.authenticatorAttachment,\n algorithms: provider.options.algorithms ?? [\n coseAlgorithmES256,\n coseAlgorithmRS256,\n ],\n challengeExpirationMs:\n provider.options.challengeExpirationMs ?? 300_000,\n };\n }),\n );\n};\n\n// ============================================================================\n// Composable validators — small functions (A) => Fx<B, ConvexError<any>>\n// ============================================================================\n\n/** Verify client data type matches expected WebAuthn ceremony type. */\nconst verifyClientDataType =\n <T extends { type: ClientDataType }>(\n expectedType: ClientDataType,\n label: string,\n ) =>\n (clientData: T): FxType<T, ConvexError<any>> =>\n clientData.type === expectedType\n ? Fx.succeed(clientData)\n : Cv.fail({\n code: \"PASSKEY_INVALID_CLIENT_DATA\",\n message: `Invalid client data type: expected ${label}`,\n });\n\n/** Verify origin is in the allowed list. */\nconst verifyOrigin =\n (rp: RpOptions) =>\n <T extends { origin: string }>(\n clientData: T,\n ): FxType<T, ConvexError<any>> => {\n const allowed = Array.isArray(rp.origin) ? rp.origin : [rp.origin];\n return allowed.includes(clientData.origin)\n ? Fx.succeed(clientData)\n : Cv.fail({\n code: \"PASSKEY_INVALID_ORIGIN\",\n message: `Invalid origin: ${clientData.origin}, expected one of: ${allowed.join(\", \")}`,\n });\n };\n\n/** Verify the challenge hash matches the stored verifier, then delete verifier. */\nconst verifyAndConsumeChallenge =\n (ctx: EnrichedActionCtx, verifierValue: string) =>\n <T extends { challenge: Uint8Array }>(\n clientData: T,\n ): FxType<T, ConvexError<any>> => {\n const challengeHash = encodeBase64urlNoPadding(\n new Uint8Array(sha256(clientData.challenge)),\n );\n return Fx.from({\n ok: () => queryVerifierById(ctx, verifierValue),\n err: () =>\n Cv.error({\n code: \"PASSKEY_INVALID_CHALLENGE\",\n message: \"Invalid or expired passkey challenge.\",\n }),\n }).pipe(\n Fx.chain((doc) =>\n !doc || doc.signature !== challengeHash\n ? Cv.fail({\n code: \"PASSKEY_INVALID_CHALLENGE\",\n message: \"Invalid or expired passkey challenge.\",\n })\n : Fx.succeed(doc),\n ),\n Fx.chain(() =>\n Fx.from({\n ok: () => mutateVerifierDelete(ctx, verifierValue),\n err: () =>\n Cv.error({\n code: \"PASSKEY_INVALID_CHALLENGE\",\n message: \"Invalid or expired passkey challenge.\",\n }),\n }),\n ),\n Fx.map(() => clientData),\n );\n };\n\n/** Verify RP ID hash matches. */\nconst verifyRpId =\n (rpId: string) =>\n <T extends { verifyRelyingPartyIdHash: (id: string) => boolean }>(\n authData: T,\n ): FxType<T, ConvexError<any>> =>\n authData.verifyRelyingPartyIdHash(rpId)\n ? Fx.succeed(authData)\n : Cv.fail({\n code: \"PASSKEY_RP_MISMATCH\",\n message: \"Relying party ID mismatch.\",\n });\n\n/** Verify user presence and (optionally) user verification flags. */\nconst verifyUserFlags =\n (rp: RpOptions) =>\n <T extends { userPresent: boolean; userVerified: boolean }>(\n authData: T,\n ): FxType<T, ConvexError<any>> =>\n !authData.userPresent\n ? Cv.fail({\n code: \"PASSKEY_USER_PRESENCE\",\n message: \"User presence flag not set.\",\n })\n : rp.userVerification === \"required\" && !authData.userVerified\n ? Cv.fail({\n code: \"PASSKEY_USER_VERIFICATION\",\n message: \"User verification required but not performed.\",\n })\n : Fx.succeed(authData);\n\n// ============================================================================\n// Registration flow\n// ============================================================================\n\n// ============================================================================\n// Authentication flow\n// ============================================================================\n\n// ============================================================================\n// Main dispatch\n// ============================================================================\n\n/** Result type for all passkey flows. */\ntype PasskeyResult =\n | { kind: \"signedIn\"; signedIn: SessionInfo | null }\n | { kind: \"passkeyOptions\"; options: Record<string, any>; verifier: string };\n\nconst PASSKEY_FLOW = {\n registerOptions: \"registerOptions\",\n registerVerify: \"registerVerify\",\n authOptions: \"authOptions\",\n authVerify: \"authVerify\",\n} as const;\n\nconst PASSKEY_FLOWS = [\n PASSKEY_FLOW.registerOptions,\n PASSKEY_FLOW.registerVerify,\n PASSKEY_FLOW.authOptions,\n PASSKEY_FLOW.authVerify,\n] as const;\n\ntype PasskeyDispatch =\n | { flow: typeof PASSKEY_FLOW.registerOptions }\n | { flow: typeof PASSKEY_FLOW.registerVerify }\n | { flow: typeof PASSKEY_FLOW.authOptions }\n | { flow: typeof PASSKEY_FLOW.authVerify };\n\nconst resolvePasskeyDispatchFx = (\n params: Record<string, unknown>,\n): FxType<PasskeyDispatch, ConvexError<any>> => {\n const flow = params.flow;\n return typeof flow === \"string\" && PASSKEY_FLOWS.includes(flow as never)\n ? Fx.succeed({ flow: flow as (typeof PASSKEY_FLOWS)[number] })\n : Cv.fail({\n code: \"PASSKEY_MISSING_FLOW\",\n message:\n \"Missing `flow` parameter. Expected one of: registerOptions, registerVerify, authOptions, authVerify\",\n });\n};\n\nconst requirePasskeyVerifierFx = (\n verifier: string | undefined,\n): FxType<string, ConvexError<any>> =>\n verifier != null\n ? Fx.succeed(verifier)\n : Cv.fail({\n code: \"PASSKEY_MISSING_VERIFIER\",\n message: \"Missing verifier for passkey operation.\",\n });\n\n/**\n * Main passkey handler dispatched from signIn.ts.\n *\n * Routes to the appropriate phase based on `params.flow` via `dispatchFx`.\n */\nexport function handlePasskeyFx(\n ctx: EnrichedActionCtx,\n provider: PasskeyProviderConfig,\n args: {\n params?: Record<string, any>;\n verifier?: string;\n },\n): FxType<PasskeyResult, ConvexError<any>> {\n const params = (args.params ?? {}) as Record<string, any>;\n\n return resolvePasskeyDispatchFx(params).pipe(\n Fx.chain((dispatch) => {\n const flowFx: FxType<PasskeyResult, ConvexError<any>> = Fx.match(\n dispatch,\n ).on(\"flow\", {\n registerOptions: (_) =>\n Fx.zip(\n Fx.from({\n ok: () => ctx.auth.getUserIdentity(),\n err: () =>\n Cv.error({\n code: \"PASSKEY_AUTH_REQUIRED\",\n message: \"Sign in first, then add a passkey to your account.\",\n }),\n }).pipe(\n Fx.chain((id) =>\n id === null\n ? Cv.fail({\n code: \"PASSKEY_AUTH_REQUIRED\",\n message:\n \"Sign in first, then add a passkey to your account.\",\n })\n : Fx.succeed(userIdFromIdentitySubject(id.subject)),\n ),\n ),\n resolveRpOptionsFx(provider),\n ).pipe(\n Fx.chain(([userId, rp]) => {\n const challenge = new Uint8Array(32);\n crypto.getRandomValues(challenge);\n const challengeHash = encodeBase64urlNoPadding(\n new Uint8Array(sha256(challenge)),\n );\n\n return Fx.from({\n ok: async () => {\n const verifier = await callVerifier(ctx);\n await callVerifierSignature(ctx, {\n verifier,\n signature: challengeHash,\n });\n\n const user = await queryUserById(ctx, userId);\n const userName = params.userName ?? user?.email ?? \"user\";\n const userDisplayName =\n params.userDisplayName ?? user?.name ?? userName;\n\n const existing = await queryPasskeysByUserId(ctx, userId);\n const excludeCredentials = existing.map((pk) => ({\n id: pk.credentialId,\n transports: pk.transports,\n }));\n\n const userHandle = encodeBase64urlNoPadding(\n new TextEncoder().encode(userId),\n );\n\n const options = {\n rp: { name: rp.rpName, id: rp.rpId },\n user: {\n id: userHandle,\n name: userName,\n displayName: userDisplayName,\n },\n challenge: encodeBase64urlNoPadding(challenge),\n pubKeyCredParams: rp.algorithms.map((alg) => ({\n type: \"public-key\" as const,\n alg,\n })),\n timeout: rp.challengeExpirationMs,\n attestation: rp.attestation,\n authenticatorSelection: {\n residentKey: rp.residentKey,\n requireResidentKey: rp.residentKey === \"required\",\n userVerification: rp.userVerification,\n ...(rp.authenticatorAttachment\n ? {\n authenticatorAttachment: rp.authenticatorAttachment,\n }\n : {}),\n },\n excludeCredentials,\n };\n\n return {\n kind: \"passkeyOptions\" as const,\n options,\n verifier,\n };\n },\n err: () =>\n Cv.error({\n code: \"INTERNAL_ERROR\",\n message: \"An unexpected error occurred.\",\n }),\n });\n }),\n ),\n registerVerify: (_) =>\n Fx.zip(\n Fx.from({\n ok: () => ctx.auth.getUserIdentity(),\n err: () =>\n Cv.error({\n code: \"PASSKEY_AUTH_REQUIRED\",\n message: \"Sign in first, then add a passkey to your account.\",\n }),\n }).pipe(\n Fx.chain((id) =>\n id === null\n ? Cv.fail({\n code: \"PASSKEY_AUTH_REQUIRED\",\n message:\n \"Sign in first, then add a passkey to your account.\",\n })\n : Fx.succeed(userIdFromIdentitySubject(id.subject)),\n ),\n ),\n resolveRpOptionsFx(provider),\n ).pipe(\n Fx.chain(([userId, rp]) =>\n requirePasskeyVerifierFx(args.verifier).pipe(\n Fx.chain((verifier) => {\n const clientDataJSON = decodeBase64urlIgnorePadding(\n params.clientDataJSON,\n );\n const clientData = parseClientDataJSON(clientDataJSON);\n\n const verifiedClientDataFx = Fx.succeed(clientData).pipe(\n Fx.chain(\n verifyClientDataType(\n ClientDataType.Create,\n \"webauthn.create\",\n ),\n ),\n Fx.chain(verifyOrigin(rp)),\n Fx.chain(verifyAndConsumeChallenge(ctx, verifier)),\n Fx.map(() => {\n const attestationObjectBytes =\n decodeBase64urlIgnorePadding(params.attestationObject);\n const attestation = parseAttestationObject(\n attestationObjectBytes,\n );\n return attestation.authenticatorData;\n }),\n );\n\n return verifiedClientDataFx.pipe(\n Fx.chain(verifyRpId(rp.rpId)),\n Fx.chain(verifyUserFlags(rp)),\n Fx.chain((authData) => {\n if (authData.credential == null) {\n return Cv.fail({\n code: \"PASSKEY_NO_CREDENTIAL\",\n message: \"No credential in attestation.\",\n });\n }\n return Fx.succeed({\n authData,\n credential: authData.credential,\n });\n }),\n Fx.chain(({ authData, credential }) => {\n const credentialId = encodeBase64urlNoPadding(\n credential.id,\n );\n const publicKey = credential.publicKey;\n\n let algorithm: number;\n if (publicKey.isAlgorithmDefined()) {\n algorithm = publicKey.algorithm();\n } else {\n const keyType = publicKey.type();\n algorithm =\n keyType === COSEKeyType.EC2\n ? coseAlgorithmES256\n : keyType === COSEKeyType.RSA\n ? coseAlgorithmRS256\n : coseAlgorithmES256;\n }\n\n const handlers: Record<\n number,\n (() => FxType<Uint8Array, ConvexError<any>>) | undefined\n > = {\n [coseAlgorithmES256]: () => {\n const ec2 = publicKey.ec2();\n const xBytes = new Uint8Array(32);\n let vx = ec2.x;\n for (let i = 31; i >= 0; i--) {\n xBytes[i] = Number(vx & 0xffn);\n vx >>= 8n;\n }\n const yBytes = new Uint8Array(32);\n let vy = ec2.y;\n for (let i = 31; i >= 0; i--) {\n yBytes[i] = Number(vy & 0xffn);\n vy >>= 8n;\n }\n const bytes = new Uint8Array(65);\n bytes[0] = 0x04;\n bytes.set(xBytes, 1);\n bytes.set(yBytes, 33);\n return Fx.succeed(bytes);\n },\n [coseAlgorithmRS256]: () => {\n const rsa = publicKey.rsa();\n const rsaPubKey = new RSAPublicKey(rsa.n, rsa.e);\n return Fx.succeed(rsaPubKey.encodePKCS1());\n },\n };\n\n const handler = handlers[algorithm];\n return (\n handler\n ? handler()\n : Cv.fail({\n code: \"PASSKEY_UNSUPPORTED_ALGORITHM\",\n message: `Unsupported algorithm: ${algorithm}`,\n })\n ).pipe(\n Fx.chain((publicKeyBytes) =>\n Fx.from({\n ok: async () => {\n const deviceType =\n params.deviceType ?? \"single-device\";\n const backedUp = params.backedUp ?? false;\n\n const db = authDb(ctx, ctx.auth.config);\n await db.accounts.create({\n userId,\n provider: provider.id,\n providerAccountId: credentialId,\n });\n\n await mutatePasskeyInsert(ctx, {\n userId,\n credentialId,\n publicKey: publicKeyBytes.buffer.slice(\n publicKeyBytes.byteOffset,\n publicKeyBytes.byteOffset +\n publicKeyBytes.byteLength,\n ),\n algorithm,\n counter: authData.signatureCounter,\n transports: params.transports,\n deviceType,\n backedUp,\n name: params.passkeyName,\n createdAt: Date.now(),\n });\n\n const signInResult = await callSignIn(ctx, {\n userId,\n generateTokens: true,\n });\n\n return {\n kind: \"signedIn\" as const,\n signedIn: signInResult,\n };\n },\n err: () =>\n Cv.error({\n code: \"INTERNAL_ERROR\",\n message: \"An unexpected error occurred.\",\n }),\n }),\n ),\n );\n }),\n );\n }),\n ),\n ),\n ),\n authOptions: (_) =>\n resolveRpOptionsFx(provider).pipe(\n Fx.chain((rp) => {\n const challenge = new Uint8Array(32);\n crypto.getRandomValues(challenge);\n const challengeHash = encodeBase64urlNoPadding(\n new Uint8Array(sha256(challenge)),\n );\n\n return Fx.from({\n ok: async () => {\n const verifier = await callVerifier(ctx);\n await callVerifierSignature(ctx, {\n verifier,\n signature: challengeHash,\n });\n\n let allowCredentials:\n | Array<{\n type: string;\n id: string;\n transports?: string[];\n }>\n | undefined;\n if (params.email) {\n const user = await queryUserByVerifiedEmail(\n ctx,\n params.email,\n );\n if (user) {\n const passkeys = await queryPasskeysByUserId(\n ctx,\n user._id,\n );\n if (passkeys.length > 0) {\n allowCredentials = passkeys.map((pk) => ({\n type: \"public-key\",\n id: pk.credentialId,\n transports: pk.transports,\n }));\n }\n }\n }\n\n const options: Record<string, any> = {\n challenge: encodeBase64urlNoPadding(challenge),\n timeout: rp.challengeExpirationMs,\n rpId: rp.rpId,\n userVerification: rp.userVerification,\n };\n\n if (allowCredentials) {\n options.allowCredentials = allowCredentials;\n }\n\n return {\n kind: \"passkeyOptions\" as const,\n options,\n verifier,\n };\n },\n err: () =>\n Cv.error({\n code: \"INTERNAL_ERROR\",\n message: \"An unexpected error occurred.\",\n }),\n });\n }),\n ),\n authVerify: (_) =>\n Fx.zip(\n resolveRpOptionsFx(provider),\n requirePasskeyVerifierFx(args.verifier),\n ).pipe(\n Fx.chain(([rp, verifier]) => {\n const clientDataJSON = decodeBase64urlIgnorePadding(\n params.clientDataJSON,\n );\n const clientData = parseClientDataJSON(clientDataJSON);\n\n const verifiedClientDataFx = Fx.succeed(clientData).pipe(\n Fx.chain(\n verifyClientDataType(ClientDataType.Get, \"webauthn.get\"),\n ),\n Fx.chain(verifyOrigin(rp)),\n Fx.chain(verifyAndConsumeChallenge(ctx, verifier)),\n Fx.chain(() =>\n params.credentialId != null\n ? Fx.succeed(params.credentialId as string)\n : Cv.fail({\n code: \"PASSKEY_UNKNOWN_CREDENTIAL\",\n message: \"Missing credential ID\",\n }),\n ),\n );\n\n return verifiedClientDataFx.pipe(\n Fx.chain((credentialId) =>\n Fx.from({\n ok: () => queryPasskeyByCredentialId(ctx, credentialId),\n err: () =>\n Cv.error({\n code: \"PASSKEY_UNKNOWN_CREDENTIAL\",\n message: \"Unknown passkey credential.\",\n }),\n }).pipe(\n Fx.chain((passkey) =>\n passkey\n ? Fx.succeed(passkey)\n : Cv.fail({\n code: \"PASSKEY_UNKNOWN_CREDENTIAL\",\n message: \"Unknown credential\",\n }),\n ),\n ),\n ),\n Fx.chain((passkey) => {\n const authenticatorDataBytes = decodeBase64urlIgnorePadding(\n params.authenticatorData,\n );\n const authenticatorData = parseAuthenticatorData(\n authenticatorDataBytes,\n );\n\n const signature = decodeBase64urlIgnorePadding(\n params.signature,\n );\n const signatureMessage = createAssertionSignatureMessage(\n authenticatorDataBytes,\n clientDataJSON,\n );\n const messageHash = sha256(signatureMessage);\n\n const checkedAuthenticatorFx = Fx.succeed(\n authenticatorData,\n ).pipe(\n Fx.chain(verifyRpId(rp.rpId)),\n Fx.chain(verifyUserFlags(rp)),\n );\n\n const signatureVerifiedFx = checkedAuthenticatorFx.pipe(\n Fx.chain(() => {\n const storedPublicKeyBytes = new Uint8Array(\n passkey.publicKey,\n );\n const algorithmHandlers: Record<\n number,\n (() => FxType<void, ConvexError<any>>) | undefined\n > = {\n [coseAlgorithmES256]: () => {\n const ecPublicKey = decodeSEC1PublicKey(\n p256,\n storedPublicKeyBytes,\n );\n const ecdsaSignature =\n decodePKIXECDSASignature(signature);\n const valid = verifyECDSASignature(\n ecPublicKey,\n messageHash,\n ecdsaSignature,\n );\n return valid\n ? Fx.succeed(undefined as void)\n : Cv.fail({\n code: \"PASSKEY_INVALID_SIGNATURE\",\n message: \"Invalid passkey signature.\",\n });\n },\n [coseAlgorithmRS256]: () => {\n const rsaPublicKey =\n decodePKCS1RSAPublicKey(storedPublicKeyBytes);\n const valid = verifyRSASSAPKCS1v15Signature(\n rsaPublicKey,\n sha256ObjectIdentifier,\n messageHash,\n signature,\n );\n return valid\n ? Fx.succeed(undefined as void)\n : Cv.fail({\n code: \"PASSKEY_INVALID_SIGNATURE\",\n message: \"Invalid passkey signature.\",\n });\n },\n };\n\n const handler = algorithmHandlers[passkey.algorithm];\n return handler\n ? handler()\n : Cv.fail({\n code: \"PASSKEY_UNSUPPORTED_ALGORITHM\",\n message: `Unsupported algorithm: ${passkey.algorithm}`,\n });\n }),\n );\n\n const counterValidatedFx = signatureVerifiedFx.pipe(\n Fx.chain(() =>\n passkey.counter !== 0 &&\n authenticatorData.signatureCounter !== 0 &&\n authenticatorData.signatureCounter <= passkey.counter\n ? Cv.fail({\n code: \"PASSKEY_COUNTER_ERROR\",\n message:\n \"Authenticator counter did not increase — possible credential cloning detected.\",\n })\n : Fx.succeed(authenticatorData),\n ),\n );\n\n return counterValidatedFx.pipe(\n Fx.chain(() =>\n Fx.from({\n ok: async () => {\n await mutatePasskeyUpdateCounter(\n ctx,\n passkey._id,\n authenticatorData.signatureCounter,\n Date.now(),\n );\n\n const signInResult = await callSignIn(ctx, {\n userId: passkey.userId,\n generateTokens: true,\n });\n\n return {\n kind: \"signedIn\" as const,\n signedIn: signInResult,\n };\n },\n err: () =>\n Cv.error({\n code: \"INTERNAL_ERROR\",\n message: \"An unexpected error occurred.\",\n }),\n }),\n ),\n );\n }),\n );\n }),\n ),\n });\n return flowFx;\n }),\n );\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- export { };
@@ -1 +0,0 @@
1
- {"version":3,"file":"redirects.js","names":[],"sources":["../../src/server/redirects.ts"],"sourcesContent":["import { Cv } from \"@robelest/fx/convex\";\n\nimport { ConvexAuthMaterializedConfig } from \"./types\";\nimport { requireEnv } from \"./utils\";\n\n/** @internal */\nexport async function redirectAbsoluteUrl(\n config: ConvexAuthMaterializedConfig,\n params: { redirectTo: unknown },\n) {\n if (params.redirectTo === undefined) {\n return requireEnv(\"SITE_URL\").replace(/\\/$/, \"\");\n }\n if (typeof params.redirectTo !== \"string\") {\n throw Cv.error({\n code: \"INVALID_REDIRECT\",\n message: `Expected \\`redirectTo\\` to be a string, got ${params.redirectTo as any}`,\n });\n }\n const redirectCallback =\n config.callbacks?.redirect ?? defaultRedirectCallback;\n try {\n return await redirectCallback({ redirectTo: params.redirectTo });\n } catch {\n throw Cv.error({\n code: \"INTERNAL_ERROR\",\n message: \"An unexpected error occurred.\",\n });\n }\n}\n\nasync function defaultRedirectCallback({ redirectTo }: { redirectTo: string }) {\n // Resolve relative paths against SITE_URL; absolute URLs are passed through\n // as-is. The developer is trusted to provide valid redirect targets.\n if (redirectTo.startsWith(\"?\") || redirectTo.startsWith(\"/\")) {\n return `${requireEnv(\"SITE_URL\").replace(/\\/$/, \"\")}${redirectTo}`;\n }\n return redirectTo;\n}\n\n// Temporary work-around because Convex doesn't support\n// schemes other than http and https.\n/** @internal */\nexport function setURLSearchParam(\n absoluteUrl: string,\n param: string,\n value: string,\n) {\n const pattern = /([^:]+):(.*)/;\n const [, scheme, rest] = absoluteUrl.match(pattern)!;\n const hasNoDomain = /^\\/\\/(?:\\/|$|\\?)/.test(rest);\n const startsWithPath = hasNoDomain && rest.startsWith(\"///\");\n const url = new URL(\n `http:${hasNoDomain ? \"//googblibok\" + rest.slice(2) : rest}`,\n );\n url.searchParams.set(param, value);\n const [, , withParam] = url.toString().match(pattern)!;\n return `${scheme}:${hasNoDomain ? (startsWithPath ? \"/\" : \"\") + \"//\" + withParam.slice(13) : withParam}`;\n}\n"],"mappings":";;;;;AAMA,eAAsB,oBACpB,QACA,QACA;AACA,KAAI,OAAO,eAAe,OACxB,QAAO,WAAW,WAAW,CAAC,QAAQ,OAAO,GAAG;AAElD,KAAI,OAAO,OAAO,eAAe,SAC/B,OAAM,GAAG,MAAM;EACb,MAAM;EACN,SAAS,+CAA+C,OAAO;EAChE,CAAC;CAEJ,MAAM,mBACJ,OAAO,WAAW,YAAY;AAChC,KAAI;AACF,SAAO,MAAM,iBAAiB,EAAE,YAAY,OAAO,YAAY,CAAC;SAC1D;AACN,QAAM,GAAG,MAAM;GACb,MAAM;GACN,SAAS;GACV,CAAC;;;AAIN,eAAe,wBAAwB,EAAE,cAAsC;AAG7E,KAAI,WAAW,WAAW,IAAI,IAAI,WAAW,WAAW,IAAI,CAC1D,QAAO,GAAG,WAAW,WAAW,CAAC,QAAQ,OAAO,GAAG,GAAG;AAExD,QAAO;;;AAMT,SAAgB,kBACd,aACA,OACA,OACA;CACA,MAAM,UAAU;CAChB,MAAM,GAAG,QAAQ,QAAQ,YAAY,MAAM,QAAQ;CACnD,MAAM,cAAc,mBAAmB,KAAK,KAAK;CACjD,MAAM,iBAAiB,eAAe,KAAK,WAAW,MAAM;CAC5D,MAAM,MAAM,IAAI,IACd,QAAQ,cAAc,iBAAiB,KAAK,MAAM,EAAE,GAAG,OACxD;AACD,KAAI,aAAa,IAAI,OAAO,MAAM;CAClC,MAAM,KAAK,aAAa,IAAI,UAAU,CAAC,MAAM,QAAQ;AACrD,QAAO,GAAG,OAAO,GAAG,eAAe,iBAAiB,MAAM,MAAM,OAAO,UAAU,MAAM,GAAG,GAAG"}
@@ -1 +0,0 @@
1
- export { };
@@ -1 +0,0 @@
1
- {"version":3,"file":"refresh.js","names":[],"sources":["../../src/server/refresh.ts"],"sourcesContent":["import { Fx } from \"@robelest/fx\";\nimport { Cv } from \"@robelest/fx/convex\";\nimport { ConvexError, GenericId } from \"convex/values\";\n\nimport { authDb } from \"./db\";\nimport { Doc, MutationCtx } from \"./types\";\nimport { ConvexAuthConfig } from \"./types\";\nimport {\n LOG_LEVELS,\n REFRESH_TOKEN_DIVIDER,\n logWithLevel,\n maybeRedact,\n} from \"./utils\";\n\nconst DEFAULT_SESSION_INACTIVE_DURATION_MS = 1000 * 60 * 60 * 24 * 30; // 30 days\n/** @internal */\nexport const REFRESH_TOKEN_REUSE_WINDOW_MS = 10 * 1000; // 10 seconds\n\n// ---------------------------------------------------------------------------\n// Refresh token CRUD\n// ---------------------------------------------------------------------------\n\n/**\n * Create a new refresh token for the given session.\n */\n/** @internal */\nexport async function createRefreshToken(\n ctx: MutationCtx,\n config: ConvexAuthConfig,\n sessionId: GenericId<\"Session\">,\n parentRefreshTokenId: GenericId<\"RefreshToken\"> | null,\n): Promise<GenericId<\"RefreshToken\">> {\n const expirationTime =\n Date.now() +\n (config.session?.inactiveDurationMs ??\n (process.env.AUTH_SESSION_INACTIVE_DURATION_MS !== undefined\n ? Number(process.env.AUTH_SESSION_INACTIVE_DURATION_MS)\n : undefined) ??\n DEFAULT_SESSION_INACTIVE_DURATION_MS);\n\n return authDb(ctx, config).refreshTokens.create({\n sessionId,\n expirationTime,\n parentRefreshTokenId: parentRefreshTokenId ?? undefined,\n }) as Promise<GenericId<\"RefreshToken\">>;\n}\n\n/**\n * Parse a compound refresh token string into its constituent IDs.\n */\n/** @internal */\nexport const parseRefreshToken = (\n refreshToken: string,\n): Fx<\n {\n refreshTokenId: GenericId<\"RefreshToken\">;\n sessionId: GenericId<\"Session\">;\n },\n ConvexError<any>\n> => {\n const [refreshTokenId, sessionId] = refreshToken.split(REFRESH_TOKEN_DIVIDER);\n const msg = `Can't parse refresh token: ${maybeRedact(refreshToken)}`;\n const refreshTokenIdFx: Fx<string, ConvexError<any>> = refreshTokenId != null\n ? Fx.succeed(refreshTokenId)\n : Cv.fail({ code: \"INVALID_REFRESH_TOKEN\", message: msg });\n\n return refreshTokenIdFx.pipe(\n Fx.chain((rtId) => {\n const sessionIdFx: Fx<string, ConvexError<any>> = sessionId != null\n ? Fx.succeed(sessionId)\n : Cv.fail({ code: \"INVALID_REFRESH_TOKEN\", message: msg });\n return sessionIdFx.pipe(\n Fx.map((sId) => ({\n refreshTokenId: rtId as GenericId<\"RefreshToken\">,\n sessionId: sId as GenericId<\"Session\">,\n })),\n );\n }),\n );\n};\n\n/**\n * Mark all refresh tokens descending from the given refresh token as invalid\n * immediately. Used when we detect token reuse — revoke the entire tree.\n */\n/** @internal */\nexport async function invalidateRefreshTokensInSubtree(\n ctx: MutationCtx,\n refreshToken: Doc<\"RefreshToken\">,\n config: ConvexAuthConfig,\n) {\n const db = authDb(ctx, config);\n const tokensToInvalidate = [refreshToken];\n const visited = new Set<GenericId<\"RefreshToken\">>([refreshToken._id]);\n let frontier: GenericId<\"RefreshToken\">[] = [refreshToken._id];\n while (frontier.length > 0) {\n const nextFrontier: GenericId<\"RefreshToken\">[] = [];\n for (const currentTokenId of frontier) {\n const children = (await db.refreshTokens.getChildren(\n refreshToken.sessionId,\n currentTokenId,\n )) as Doc<\"RefreshToken\">[];\n for (const child of children) {\n if (visited.has(child._id)) continue;\n visited.add(child._id);\n tokensToInvalidate.push(child);\n nextFrontier.push(child._id);\n }\n }\n frontier = nextFrontier;\n }\n await Fx.run(\n Fx.each(tokensToInvalidate, (token) =>\n token.firstUsedTime === undefined ||\n token.firstUsedTime > Date.now() - REFRESH_TOKEN_REUSE_WINDOW_MS\n ? Fx.promise(() =>\n db.refreshTokens.patch(token._id, {\n firstUsedTime: Date.now() - REFRESH_TOKEN_REUSE_WINDOW_MS,\n }),\n )\n : Fx.unit,\n ),\n );\n return tokensToInvalidate;\n}\n\n// ---------------------------------------------------------------------------\n// Validation pipeline — the core of refresh token handling\n// ---------------------------------------------------------------------------\n\n/**\n * Validate a refresh token and its associated session.\n *\n * Returns `null` on any validation failure (matching original semantics).\n * Each validation step is a small composable function chained with `Fx.chain`.\n * On failure, the error message is logged and the pipeline folds to `null`.\n */\n/** @internal */\nexport const refreshTokenIfValid = (\n ctx: MutationCtx,\n refreshTokenId: string,\n tokenSessionId: string,\n config: ConvexAuthConfig,\n): Fx<\n { session: Doc<\"Session\">; refreshTokenDoc: Doc<\"RefreshToken\"> } | null,\n never\n> => {\n const db = authDb(ctx, config);\n\n const fetchDoc = <T>(\n promise: () => Promise<T | null>,\n failMsg: string,\n ): Fx<T | null, never> =>\n Fx.from({ ok: promise, err: () => failMsg }).pipe(\n Fx.recover((msg) => {\n logWithLevel(LOG_LEVELS.ERROR, msg);\n return Fx.succeed(null as T | null);\n }),\n );\n\n // The entire validation is a single pipeline:\n // fetch token → not null → not expired → session matches → fetch session → not null → not expired → combine\n return fetchDoc(\n () =>\n db.refreshTokens.getById(\n refreshTokenId as GenericId<\"RefreshToken\">,\n ) as Promise<Doc<\"RefreshToken\"> | null>,\n \"Invalid refresh token format\",\n )\n .pipe(\n Fx.chain((doc) =>\n doc !== null ? Fx.succeed(doc) : Fx.fail(\"Invalid refresh token\"),\n ),\n Fx.chain((doc) =>\n doc.expirationTime >= Date.now()\n ? Fx.succeed(doc)\n : Fx.fail(\"Expired refresh token\"),\n ),\n Fx.chain((doc) =>\n doc.sessionId === tokenSessionId\n ? Fx.succeed(doc)\n : Fx.fail(\"Invalid refresh token session ID\"),\n ),\n )\n .pipe(\n Fx.chain((doc: Doc<\"RefreshToken\">) =>\n fetchDoc(\n () =>\n db.sessions.getById(\n doc.sessionId,\n ) as Promise<Doc<\"Session\"> | null>,\n \"Invalid refresh token session format\",\n ).pipe(\n Fx.chain((session) =>\n session !== null\n ? Fx.succeed(session)\n : Fx.fail(\"Invalid refresh token session\"),\n ),\n Fx.chain((session) =>\n session.expirationTime >= Date.now()\n ? Fx.succeed(session)\n : Fx.fail(\"Expired refresh token session\"),\n ),\n Fx.map((session) => ({\n session,\n refreshTokenDoc: doc,\n })),\n ),\n ),\n Fx.fold({\n ok: (result) => result,\n err: (msg) => {\n logWithLevel(LOG_LEVELS.ERROR, msg);\n return null;\n },\n }),\n );\n};\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"runtime.d.ts","names":[],"sources":["../../src/server/runtime.ts"],"mappings":";;;;;;;;;AAqJA;;;;;;;;;;;;;;iBAAgB,IAAA,CAAK,OAAA,EAAS,gBAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"runtime.js","names":["serializeCookie"],"sources":["../../src/server/runtime.ts"],"sourcesContent":["import { Fx } from \"@robelest/fx\";\nimport { Cv } from \"@robelest/fx/convex\";\nimport {\n GenericActionCtx,\n GenericDataModel,\n HttpRouter,\n actionGeneric,\n internalMutationGeneric,\n} from \"convex/server\";\nimport { v } from \"convex/values\";\nimport { serialize as serializeCookie } from \"cookie\";\n\nimport { configDefaults, listAvailableProviders } from \"./config\";\nimport { redirectToParamCookie, useRedirectToParam } from \"./cookies\";\nimport { createCoreDomains } from \"./core\";\nimport { GetProviderOrThrowFunc } from \"./crypto\";\nimport {\n getOidcConfig,\n getPublicOidcConfig,\n getSamlConfig,\n upsertProtocolConfig,\n withOidcSecretState,\n} from \"./enterprise/config\";\nimport { createEnterpriseDomain } from \"./enterprise/domain\";\nimport { addEnterpriseHttpRuntime } from \"./enterprise/http\";\nimport {\n normalizeEnterprisePolicy,\n patchEnterprisePolicy,\n} from \"./enterprise/policy\";\nimport {\n createServiceProviderMetadata,\n getSamlServiceProviderOptions,\n parseSamlIdpMetadata,\n} from \"./enterprise/saml\";\nimport { parseScimPath } from \"./enterprise/scim\";\nimport {\n enterpriseOidcProviderId,\n getEnterpriseOidcUrls,\n isEnterpriseSamlSourceActive,\n normalizeDomain,\n} from \"./enterprise/shared\";\nimport {\n addAuthRoutes,\n addOpenIdRoutes,\n convertErrorsToResponse,\n createHttpAction,\n createHttpContext,\n createHttpRoute,\n getCookies,\n} from \"./http\";\nimport {\n callCreateAccountFromCredentials,\n callInvalidateSessions,\n callModifyAccount,\n callRetrieveAccountWithCredentials,\n callSignOut,\n callUserOAuth,\n callVerifierSignature,\n storeArgs,\n storeImpl,\n} from \"./mutations/index\";\nimport { createOAuthAuthorizationURL, handleOAuthCallback } from \"./oauth\";\nimport { redirectAbsoluteUrl, setURLSearchParam } from \"./redirects\";\nimport { signInImpl } from \"./signin\";\nimport type {\n ConvexAuthConfig,\n FunctionReferenceFromExport,\n OAuthMaterializedConfig,\n Tokens,\n} from \"./types\";\nimport { MutationCtx } from \"./types\";\nimport {\n decryptSecret,\n encryptSecret,\n generateRandomString,\n LOG_LEVELS,\n logError,\n logWithLevel,\n sha256,\n} from \"./utils\";\nimport { requireEnv } from \"./utils\";\n\nconst ENTERPRISE_OIDC_CLIENT_SECRET_KIND = \"oidc_client_secret\" as const;\n\n/**\n * The type of the signIn Convex Action returned from the auth() helper.\n *\n * This type is exported for implementors of other client integrations.\n * However it is not stable, and may change until this library reaches 1.0.\n *\n * @internal\n */\nexport type SignInAction = FunctionReferenceFromExport<\n ReturnType<typeof Auth>[\"signIn\"]\n>;\n\n/** @internal */\nexport type SignInActionResult =\n | { kind: \"signedIn\"; tokens: Tokens | null }\n | { kind: \"redirect\"; redirect: string; verifier: string }\n | { kind: \"started\" }\n | { kind: \"passkeyOptions\"; options: Record<string, any>; verifier: string }\n | { kind: \"totpRequired\"; verifier: string }\n | {\n kind: \"totpSetup\";\n totpSetup: { uri: string; secret: string; totpId: string };\n verifier: string;\n }\n | {\n kind: \"deviceCode\";\n deviceCode: {\n deviceCode: string;\n userCode: string;\n verificationUri: string;\n verificationUriComplete: string;\n expiresIn: number;\n interval: number;\n };\n };\n/**\n * The type of the signOut Convex Action returned from the auth() helper.\n *\n * This type is exported for implementors of other client integrations.\n * However it is not stable, and may change until this library reaches 1.0.\n *\n * @internal\n */\nexport type SignOutAction = FunctionReferenceFromExport<\n ReturnType<typeof Auth>[\"signOut\"]\n>;\n\n/**\n * Configure the Convex Auth library. Returns an object with\n * functions and `auth` helper. You must export the functions\n * from `convex/auth.ts` to make them callable:\n *\n * ```ts filename=\"convex/auth.ts\"\n * import { createAuth } from \"@robelest/convex-auth/component\";\n * import { components } from \"./_generated/api\";\n *\n * export const auth = createAuth(components.auth, {\n * providers: [],\n * });\n * export const { signIn, signOut, store } = auth;\n * ```\n *\n * @returns An object with fields you should reexport from your\n * `convex/auth.ts` file.\n */\nexport function Auth(config_: ConvexAuthConfig) {\n const config = configDefaults(config_);\n const hasOAuth = config.providers.some(\n (provider) => provider.type === \"oauth\",\n );\n const hasSSO = config.providers.some((provider) => provider.type === \"sso\");\n const getProviderOrThrow: GetProviderOrThrowFunc = (\n id: string,\n allowExtraProviders: boolean = false,\n ) => {\n const provider =\n config.providers.find(\n (configuredProvider) => configuredProvider.id === id,\n ) ??\n (allowExtraProviders\n ? config.extraProviders.find(\n (configuredProvider) => configuredProvider.id === id,\n )\n : undefined);\n if (provider === undefined) {\n const detail =\n `Provider \\`${id}\\` is not configured, ` +\n `available providers are ${listAvailableProviders(config, allowExtraProviders)}.`;\n logWithLevel(LOG_LEVELS.ERROR, detail);\n throw Cv.error({\n code: \"PROVIDER_NOT_CONFIGURED\",\n message: detail,\n provider: id,\n });\n }\n return provider;\n };\n type ComponentCtx = Pick<\n GenericActionCtx<GenericDataModel>,\n \"runQuery\" | \"runMutation\"\n >;\n type ComponentReadCtx = Pick<GenericActionCtx<GenericDataModel>, \"runQuery\">;\n const getEnterpriseSecret = async (\n ctx: ComponentReadCtx | ComponentCtx,\n enterpriseId: string,\n kind: typeof ENTERPRISE_OIDC_CLIENT_SECRET_KIND,\n ) => {\n return await ctx.runQuery(config.component.public.enterpriseSecretGet, {\n enterpriseId,\n kind,\n });\n };\n const getEnterpriseOidcConfigWithSecret = async (\n ctx: ComponentReadCtx | ComponentCtx,\n enterprise: { _id: string; config?: unknown },\n ): Promise<Record<string, any>> => {\n const oidc = getOidcConfig(enterprise.config);\n const secret = await getEnterpriseSecret(\n ctx,\n enterprise._id,\n ENTERPRISE_OIDC_CLIENT_SECRET_KIND,\n );\n return {\n ...oidc,\n ...(secret\n ? { clientSecret: await decryptSecret(secret.ciphertext) }\n : {}),\n };\n };\n const INVITE_TOKEN_ALPHABET =\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n const INVITE_TOKEN_LENGTH = 48;\n\n const enterpriseNotFoundError = \"Enterprise not found.\";\n\n const ENTERPRISE_CONTROL_ROUTE_BASE = \"/api/auth/sso\";\n\n const getPolicyFromEnterprise = (enterprise: { policy?: unknown }) =>\n normalizeEnterprisePolicy(enterprise.policy);\n\n const loadEnterpriseOrThrow = async (\n ctx: ComponentReadCtx,\n enterpriseId: string,\n ) => {\n const enterprise = await ctx.runQuery(\n config.component.public.enterpriseGet,\n {\n enterpriseId,\n },\n );\n if (!enterprise) {\n throw Cv.error({\n code: \"INVALID_PARAMETERS\",\n message: enterpriseNotFoundError,\n });\n }\n return enterprise;\n };\n\n const loadActiveEnterpriseOrThrow = async (\n ctx: ComponentReadCtx,\n enterpriseId: string,\n ) => {\n const enterprise = await loadEnterpriseOrThrow(ctx, enterpriseId);\n if (enterprise.status !== \"active\") {\n throw Cv.error({\n code: \"INVALID_PARAMETERS\",\n message: \"Enterprise connection is not active.\",\n });\n }\n return enterprise;\n };\n\n const loadActiveEnterpriseSamlOrThrow = async (\n ctx: ComponentReadCtx,\n enterpriseId: string,\n ) => {\n const enterprise = await loadEnterpriseOrThrow(ctx, enterpriseId);\n const loaded = {\n source: {\n kind: \"enterprise\" as const,\n id: enterpriseId,\n },\n config: enterprise.config,\n status: enterprise.status,\n enterprise,\n };\n if (!isEnterpriseSamlSourceActive(loaded)) {\n throw Cv.error({\n code: \"INVALID_PARAMETERS\",\n message: \"Enterprise connection is not active.\",\n });\n }\n const saml = getSamlConfig(loaded.config);\n if (!saml.idp?.metadataXml) {\n throw Cv.error({\n code: \"PROVIDER_NOT_CONFIGURED\",\n message: \"SAML is not configured for this enterprise.\",\n });\n }\n return { loaded, enterprise, saml };\n };\n\n const loadEnterpriseOidcOrThrow = async (\n ctx: ComponentReadCtx,\n enterpriseId: string,\n ) => {\n const enterprise = await loadActiveEnterpriseOrThrow(ctx, enterpriseId);\n const oidc = await getEnterpriseOidcConfigWithSecret(ctx, enterprise);\n if (oidc.enabled !== true) {\n throw Cv.error({\n code: \"PROVIDER_NOT_CONFIGURED\",\n message: \"OIDC is not configured for this enterprise.\",\n });\n }\n return { enterprise, oidc };\n };\n\n const validateEnterprisePolicy = (\n policy: ReturnType<typeof normalizeEnterprisePolicy>,\n ) => {\n const checks: Array<{\n name: string;\n ok: boolean;\n message?: string;\n }> = [];\n\n checks.push({ name: \"policy_version\", ok: policy.version === 1 });\n checks.push({\n name: \"jit_default_role_ids_present\",\n ok:\n policy.provisioning.jit.mode !== \"createUserAndMembership\" ||\n policy.provisioning.jit.defaultRoleIds.length > 0,\n message:\n policy.provisioning.jit.mode === \"createUserAndMembership\" &&\n policy.provisioning.jit.defaultRoleIds.length === 0\n ? \"At least one default roleId is required when JIT membership provisioning is enabled.\"\n : undefined,\n });\n checks.push({\n name: \"jit_default_role_ids_known\",\n ok: policy.provisioning.jit.defaultRoleIds.every(\n (roleId) => config.authorization.roles[roleId] !== undefined,\n ),\n message: policy.provisioning.jit.defaultRoleIds.every(\n (roleId) => config.authorization.roles[roleId] !== undefined,\n )\n ? undefined\n : \"JIT defaultRoleIds contains unknown roleIds.\",\n });\n checks.push({\n name: \"scim_reuse_supported\",\n ok:\n policy.provisioning.scimReuse.user === \"externalId\" ||\n policy.provisioning.scimReuse.user === \"none\",\n });\n\n return checks;\n };\n\n const recordEnterpriseAuditEvent = async (\n ctx: ComponentCtx,\n data: {\n enterpriseId: string;\n groupId: string;\n eventType: string;\n actorType: \"user\" | \"system\" | \"scim\" | \"api_key\" | \"webhook\";\n actorId?: string;\n subjectType: string;\n subjectId?: string;\n ok: boolean;\n requestId?: string;\n ip?: string;\n metadata?: Record<string, unknown>;\n },\n ) => {\n const { ok, ...rest } = data;\n return (await ctx.runMutation(\n config.component.public.enterpriseAuditEventCreate,\n {\n ...rest,\n status: ok ? \"success\" : \"failure\",\n occurredAt: Date.now(),\n },\n )) as string;\n };\n\n const emitEnterpriseWebhookDeliveries = async (\n ctx: ComponentCtx,\n data: {\n enterpriseId: string;\n eventType: string;\n payload: Record<string, unknown>;\n auditEventId?: string;\n },\n ) => {\n const endpoints = await ctx.runQuery(\n config.component.public.enterpriseWebhookEndpointList,\n { enterpriseId: data.enterpriseId },\n );\n for (const endpoint of endpoints) {\n if (\n endpoint.status !== \"active\" ||\n !endpoint.subscriptions.includes(data.eventType)\n ) {\n continue;\n }\n await ctx.runMutation(\n config.component.public.enterpriseWebhookDeliveryEnqueue,\n {\n enterpriseId: data.enterpriseId,\n endpointId: endpoint._id,\n auditEventId: data.auditEventId,\n eventType: data.eventType,\n payload: data.payload,\n nextAttemptAt: Date.now(),\n },\n );\n }\n };\n\n const getEnterpriseScimContext = async (\n ctx: ComponentReadCtx,\n request: Request,\n ) => {\n const authHeader = request.headers.get(\"Authorization\");\n if (!authHeader?.startsWith(\"Bearer \")) {\n throw Cv.error({\n code: \"MISSING_BEARER_TOKEN\",\n message: \"Missing or malformed Authorization: Bearer header.\",\n });\n }\n const token = authHeader.slice(7);\n const scimConfig = await ctx.runQuery(\n config.component.public.enterpriseScimConfigGetByTokenHash,\n { tokenHash: await sha256(token) },\n );\n if (!scimConfig || scimConfig.status !== \"active\") {\n throw Cv.error({\n code: \"INVALID_API_KEY\",\n message: \"Invalid SCIM token.\",\n });\n }\n const parsedPath = parseScimPath(new URL(request.url).pathname);\n if (parsedPath.enterpriseId !== scimConfig.enterpriseId) {\n throw Cv.error({\n code: \"INVALID_API_KEY\",\n message: \"SCIM token/tenant mismatch.\",\n });\n }\n const enterprise = await ctx.runQuery(\n config.component.public.enterpriseGet,\n {\n enterpriseId: scimConfig.enterpriseId,\n },\n );\n if (enterprise === null) {\n throw Cv.error({\n code: \"INVALID_PARAMETERS\",\n message: \"Enterprise not found.\",\n });\n }\n return { scimConfig, enterprise, parsedPath };\n };\n\n let auth: any;\n auth = {\n ...createCoreDomains({\n config,\n getAuth: () => auth,\n callInvalidateSessions,\n callCreateAccountFromCredentials,\n callRetrieveAccountWithCredentials,\n callModifyAccount,\n getEnrichCtx: () => enrichCtx,\n inviteTokenAlphabet: INVITE_TOKEN_ALPHABET,\n inviteTokenLength: INVITE_TOKEN_LENGTH,\n }),\n /**\n * SSO namespace — enterprise SSO connection management, domain, OIDC,\n * SAML, SCIM, audit, and webhook helpers.\n */\n sso: createEnterpriseDomain({\n config,\n getAuth: () => auth,\n normalizeEnterprisePolicy,\n normalizeDomain,\n getEnterpriseSecret,\n loadEnterpriseOrThrow,\n validateEnterprisePolicy,\n recordEnterpriseAuditEvent,\n emitEnterpriseWebhookDeliveries,\n enterpriseNotFoundError,\n ENTERPRISE_OIDC_CLIENT_SECRET_KIND,\n requireEnv,\n generateRandomString,\n INVITE_TOKEN_ALPHABET,\n sha256,\n encryptSecret,\n upsertProtocolConfig,\n parseSamlIdpMetadata,\n createServiceProviderMetadata,\n getSamlServiceProviderOptions,\n getPublicOidcConfig,\n withOidcSecretState,\n getOidcConfig,\n getEnterpriseOidcUrls,\n enterpriseOidcProviderId,\n getPolicyFromEnterprise,\n patchEnterprisePolicy,\n }),\n };\n\n // HTTP wiring stays local to the factory because it still depends on a\n // dense mix of OAuth, SAML, SCIM, cookie, and response helpers.\n auth.http = {\n /**\n * Register core HTTP routes for JWT verification and OAuth sign-in.\n *\n * ```ts\n * import { httpRouter } from \"convex/server\";\n * import { auth } from \"./auth\";\n *\n * const http = httpRouter();\n *\n * auth.http.add(http);\n *\n * export default http;\n * ```\n *\n * The following routes are handled always:\n *\n * - `/.well-known/openid-configuration`\n * - `/.well-known/jwks.json`\n *\n * The following routes are handled if OAuth is configured:\n *\n * - `/api/auth/signin/*`\n * - `/api/auth/callback/*`\n *\n * @param http your HTTP router\n */\n add: (http: HttpRouter) => {\n addOpenIdRoutes(http, {\n getIssuer: () => requireEnv(\"CONVEX_SITE_URL\"),\n getJwks: () => requireEnv(\"JWKS\"),\n });\n\n addEnterpriseHttpRuntime({\n http,\n hasSSO,\n auth,\n config,\n routeBase: ENTERPRISE_CONTROL_ROUTE_BASE,\n requireEnv,\n loadActiveEnterpriseSamlOrThrow,\n loadEnterpriseOidcOrThrow,\n getEnterpriseScimContext,\n getPolicyFromEnterprise,\n normalizeEnterprisePolicy,\n recordEnterpriseAuditEvent,\n emitEnterpriseWebhookDeliveries,\n generateRandomString,\n inviteTokenAlphabet: INVITE_TOKEN_ALPHABET,\n callUserOAuth,\n callVerifierSignature,\n });\n\n if (hasOAuth) {\n addAuthRoutes(http, {\n handleSignIn: convertErrorsToResponse(400, async (ctx, request) => {\n const url = new URL(request.url);\n const pathParts = url.pathname.split(\"/\");\n const providerId = pathParts[pathParts.length - 1]!;\n if (providerId === null) {\n throw Cv.error({\n code: \"OAUTH_MISSING_PROVIDER\",\n message: \"Missing OAuth provider ID.\",\n });\n }\n const verifier = url.searchParams.get(\"code\");\n if (verifier === null) {\n throw Cv.error({\n code: \"OAUTH_MISSING_VERIFIER\",\n message: \"Missing sign-in verifier.\",\n });\n }\n const provider = getProviderOrThrow(providerId);\n\n const oauthConfig = provider as OAuthMaterializedConfig;\n const { redirect, cookies, signature } =\n await createOAuthAuthorizationURL(\n providerId,\n oauthConfig.provider,\n oauthConfig,\n );\n\n await callVerifierSignature(ctx, {\n verifier,\n signature,\n });\n\n const redirectTo = url.searchParams.get(\"redirectTo\");\n if (redirectTo !== null) {\n cookies.push(redirectToParamCookie(providerId, redirectTo));\n }\n\n const headers = new Headers({ Location: redirect });\n for (const { name, value, options } of cookies) {\n headers.append(\n \"Set-Cookie\",\n serializeCookie(name, value, options as any),\n );\n }\n\n return new Response(null, { status: 302, headers });\n }),\n handleCallback: async (ctx, request) => {\n const url = new URL(request.url);\n const callbackPathParts = new URL(request.url).pathname.split(\"/\");\n const providerId = callbackPathParts[callbackPathParts.length - 1];\n if (!providerId) {\n throw Cv.error({\n code: \"OAUTH_MISSING_PROVIDER\",\n message: \"Missing OAuth provider ID.\",\n });\n }\n logWithLevel(\n LOG_LEVELS.DEBUG,\n \"Handling OAuth callback for provider:\",\n providerId,\n );\n const provider = getProviderOrThrow(providerId);\n\n const cookies = getCookies(request);\n\n const maybeRedirectTo = useRedirectToParam(provider.id, cookies);\n\n const destinationUrl = await redirectAbsoluteUrl(config, {\n redirectTo: maybeRedirectTo?.redirectTo,\n });\n\n const params = url.searchParams;\n\n if (\n request.headers.get(\"Content-Type\") ===\n \"application/x-www-form-urlencoded\"\n ) {\n const formData = await request.formData();\n formData.forEach((value, key) => {\n if (typeof value === \"string\") {\n params.append(key, value);\n }\n });\n }\n\n return Fx.run(\n Fx.from({\n ok: async () => {\n const oauthConfig = provider as OAuthMaterializedConfig;\n const result = await Fx.run(\n handleOAuthCallback(\n providerId,\n oauthConfig.provider,\n oauthConfig,\n Object.fromEntries(params.entries()),\n cookies,\n ),\n );\n const oauthCookies = result.cookies;\n const { id: profileId, ...profileData } = result.profile;\n const { signature } = result;\n\n const verificationCode = await callUserOAuth(ctx, {\n provider: providerId,\n providerAccountId: profileId,\n profile: profileData,\n signature,\n });\n\n const redirUrl = setURLSearchParam(\n destinationUrl,\n \"code\",\n verificationCode,\n );\n const redirHeaders = new Headers({ Location: redirUrl });\n redirHeaders.set(\"Cache-Control\", \"must-revalidate\");\n for (const { name, value, options } of [\n ...oauthCookies,\n ...(maybeRedirectTo !== null\n ? [maybeRedirectTo.updatedCookie]\n : []),\n ] as any) {\n redirHeaders.append(\n \"Set-Cookie\",\n serializeCookie(name, value, options),\n );\n }\n return new Response(null, {\n status: 302,\n headers: redirHeaders,\n });\n },\n err: (error) => error,\n }).pipe(\n Fx.recover((error) => {\n logError(error);\n const respHeaders = new Headers({\n Location: destinationUrl,\n });\n for (const { name, value, options } of maybeRedirectTo !== null\n ? [maybeRedirectTo.updatedCookie]\n : []) {\n respHeaders.append(\n \"Set-Cookie\",\n serializeCookie(name, value, options),\n );\n }\n return Fx.succeed(\n new Response(null, {\n status: 302,\n headers: respHeaders,\n }),\n );\n }),\n ),\n );\n },\n });\n }\n },\n\n /**\n * Resolve mixed HTTP auth for a raw `httpAction`.\n *\n * Checks session auth first, then falls back to `Authorization: Bearer sk_*`\n * API keys. This is the low-level helper for endpoints that intentionally\n * accept either browser sessions or API keys.\n * Pass `{ optional: true }` to get a null-shaped auth object instead of a\n * `NOT_SIGNED_IN` error.\n *\n * ```ts\n * http.route({\n * path: \"/api/data\",\n * method: \"GET\",\n * handler: httpAction(async (ctx, request) => {\n * const authContext = await auth.http.context(ctx, request);\n * return Response.json({\n * userId: authContext.userId,\n * source: authContext.source,\n * });\n * }),\n * });\n * ```\n */\n context: createHttpContext(auth),\n\n /**\n * Wrap an HTTP action handler with Bearer token authentication.\n *\n * Extracts the `Authorization: Bearer <key>` header, verifies the\n * API key via `auth.key.verify()`, and injects `ctx.key` with the\n * verified key info. Returns structured JSON error responses for\n * missing/invalid/revoked/expired/rate-limited keys.\n *\n * If the handler returns a plain object, it is auto-wrapped in a\n * `200 JSON` response. If it returns a `Response`, CORS headers\n * are merged and the response is passed through.\n *\n * ```ts\n * const handler = auth.http.action(async (ctx, request) => {\n * const data = await ctx.runQuery(api.data.get, { userId: ctx.key.userId });\n * return { data };\n * });\n * http.route({ path: \"/api/data\", method: \"GET\", handler });\n * ```\n *\n * @param handler - Receives enriched `ctx` (with `ctx.key`) and the raw `Request`.\n * @param options.scope - Optional scope check; returns 403 if the key lacks permission.\n * @param options.cors - CORS config; defaults to permissive (`*`).\n */\n action: createHttpAction(auth),\n\n /**\n * Register a Bearer-authenticated route **and** its OPTIONS preflight\n * in a single call.\n *\n * ```ts\n * auth.http.route(http, {\n * path: \"/api/messages\",\n * method: \"POST\",\n * handler: async (ctx, request) => {\n * const { body } = await request.json();\n * await ctx.runMutation(internal.messages.sendAsUser, {\n * userId: ctx.key.userId,\n * body,\n * });\n * return { success: true };\n * },\n * });\n * ```\n *\n * @param http - The Convex HTTP router.\n * @param routeConfig.path - The URL path to match.\n * @param routeConfig.method - HTTP method (GET, POST, PUT, PATCH, DELETE).\n * @param routeConfig.handler - Receives enriched `ctx` (with `ctx.key`) and the raw `Request`.\n * @param routeConfig.scope - Optional scope check; returns 403 if the key lacks permission.\n * @param routeConfig.cors - CORS config; defaults to permissive (`*`).\n */\n route: createHttpRoute(createHttpAction(auth)),\n };\n\n const enrichCtx = <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n ) => ({\n ...ctx,\n auth: {\n ...ctx.auth,\n config,\n account: auth.account,\n session: auth.session,\n member: auth.member,\n provider: auth.provider,\n },\n });\n\n return {\n /**\n * Helper for configuring HTTP actions.\n */\n auth,\n /**\n * Action called by the client to sign the user in.\n *\n * Also used for refreshing the session.\n */\n signIn: actionGeneric({\n args: {\n provider: v.optional(v.string()),\n params: v.optional(v.any()),\n verifier: v.optional(v.string()),\n refreshToken: v.optional(v.string()),\n calledBy: v.optional(v.string()),\n },\n handler: async (ctx, args): Promise<SignInActionResult> => {\n if (args.calledBy !== undefined) {\n logWithLevel(\"INFO\", `\\`auth:signIn\\` called by ${args.calledBy}`);\n }\n const provider =\n args.provider !== undefined\n ? getProviderOrThrow(args.provider)\n : null;\n const result = await signInImpl(enrichCtx(ctx), provider, args, {\n generateTokens: true,\n allowExtraProviders: false,\n });\n return Fx.run(\n Fx.match(result, result.kind, {\n redirect: (r) =>\n Fx.succeed({\n kind: \"redirect\" as const,\n redirect: r.redirect,\n verifier: r.verifier,\n }),\n signedIn: (r) =>\n Fx.succeed({\n kind: \"signedIn\" as const,\n tokens: r.signedIn?.tokens ?? null,\n }),\n refreshTokens: (r) =>\n Fx.succeed({\n kind: \"signedIn\" as const,\n tokens: r.signedIn?.tokens ?? null,\n }),\n started: () => Fx.succeed({ kind: \"started\" as const }),\n passkeyOptions: (r) =>\n Fx.succeed({\n kind: \"passkeyOptions\" as const,\n options: r.options,\n verifier: r.verifier,\n }),\n totpRequired: (r) =>\n Fx.succeed({\n kind: \"totpRequired\" as const,\n verifier: r.verifier,\n }),\n totpSetup: (r) =>\n Fx.succeed({\n kind: \"totpSetup\" as const,\n totpSetup: {\n uri: r.uri,\n secret: r.secret,\n totpId: r.totpId,\n },\n verifier: r.verifier,\n }),\n deviceCode: (r) =>\n Fx.succeed({\n kind: \"deviceCode\" as const,\n deviceCode: {\n deviceCode: r.deviceCode,\n userCode: r.userCode,\n verificationUri: r.verificationUri,\n verificationUriComplete: r.verificationUriComplete,\n expiresIn: r.expiresIn,\n interval: r.interval,\n },\n }),\n }),\n );\n },\n }),\n /**\n * Action called by the client to invalidate the current session.\n */\n signOut: actionGeneric({\n args: {},\n handler: async (ctx) => {\n await callSignOut(ctx);\n },\n }),\n\n /**\n * Internal mutation used by the library to read and write\n * to the database during signin and signout.\n */\n store: internalMutationGeneric({\n args: storeArgs,\n handler: async (ctx: MutationCtx, args) => {\n return storeImpl(ctx, args, getProviderOrThrow, config);\n },\n }),\n };\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- export { };
@@ -1 +0,0 @@
1
- {"version":3,"file":"sessions.js","names":[],"sources":["../../src/server/sessions.ts"],"sourcesContent":["import { Auth } from \"convex/server\";\nimport { GenericId } from \"convex/values\";\n\nimport { authDb } from \"./db\";\nimport { createRefreshToken } from \"./refresh\";\nimport { generateToken } from \"./tokens\";\nimport { Doc, MutationCtx, SessionInfo } from \"./types\";\nimport { ConvexAuthConfig } from \"./types\";\nimport {\n LOG_LEVELS,\n TOKEN_SUB_CLAIM_DIVIDER,\n REFRESH_TOKEN_DIVIDER,\n logWithLevel,\n maybeRedact,\n} from \"./utils\";\n\nconst DEFAULT_SESSION_TOTAL_DURATION_MS = 1000 * 60 * 60 * 24 * 30; // 30 days\n\n/** @internal */\nexport async function maybeGenerateTokensForSession(\n ctx: MutationCtx,\n config: ConvexAuthConfig,\n userId: GenericId<\"User\">,\n sessionId: GenericId<\"Session\">,\n generateTokens: boolean,\n): Promise<SessionInfo> {\n return {\n userId,\n sessionId,\n tokens: generateTokens\n ? await generateTokensForSession(ctx, config, {\n userId,\n sessionId,\n issuedRefreshTokenId: null,\n parentRefreshTokenId: null,\n })\n : null,\n };\n}\n\n/** @internal */\nexport async function createNewAndDeleteExistingSession(\n ctx: MutationCtx,\n config: ConvexAuthConfig,\n userId: GenericId<\"User\">,\n) {\n const db = authDb(ctx, config);\n const existingSessionId = await getAuthSessionId(ctx);\n if (existingSessionId !== null) {\n const existingSession = await db.sessions.getById(existingSessionId);\n if (existingSession !== null) {\n await deleteSession(ctx, existingSession, config);\n }\n }\n return await createSession(ctx, userId, config);\n}\n\n/** @internal */\nexport async function generateTokensForSession(\n ctx: MutationCtx,\n config: ConvexAuthConfig,\n args: {\n userId: GenericId<\"User\">;\n sessionId: GenericId<\"Session\">;\n issuedRefreshTokenId: GenericId<\"RefreshToken\"> | null;\n parentRefreshTokenId: GenericId<\"RefreshToken\"> | null;\n },\n) {\n const ids = { userId: args.userId, sessionId: args.sessionId };\n const refreshTokenId =\n args.issuedRefreshTokenId ??\n (await createRefreshToken(\n ctx,\n config,\n args.sessionId,\n args.parentRefreshTokenId,\n ));\n const result = {\n token: await generateToken(ids, config),\n refreshToken: `${refreshTokenId}${REFRESH_TOKEN_DIVIDER}${args.sessionId}`,\n };\n logWithLevel(\n LOG_LEVELS.DEBUG,\n `Generated token ${maybeRedact(result.token)} and refresh token ${maybeRedact(refreshTokenId)} for session ${maybeRedact(args.sessionId)}`,\n );\n return result;\n}\n\nasync function createSession(\n ctx: MutationCtx,\n userId: GenericId<\"User\">,\n config: ConvexAuthConfig,\n) {\n const db = authDb(ctx, config);\n const expirationTime =\n Date.now() +\n (config.session?.totalDurationMs ??\n (process.env.AUTH_SESSION_TOTAL_DURATION_MS !== undefined\n ? Number(process.env.AUTH_SESSION_TOTAL_DURATION_MS)\n : undefined) ??\n DEFAULT_SESSION_TOTAL_DURATION_MS);\n return (await db.sessions.create(\n userId,\n expirationTime,\n )) as GenericId<\"Session\">;\n}\n\n/** @internal */\nexport async function deleteSession(\n ctx: MutationCtx,\n session: Doc<\"Session\">,\n config: ConvexAuthConfig,\n) {\n const db = authDb(ctx, config);\n await db.sessions.delete(session._id);\n await db.refreshTokens.deleteAll(session._id);\n}\n\n/**\n * Return the current session ID from the auth identity subject.\n *\n * Internal helper used by auth runtime internals and `auth.session.current`.\n */\n/** @internal */\nexport async function getAuthSessionId(ctx: { auth: Auth }) {\n const identity = await ctx.auth.getUserIdentity();\n if (identity === null) {\n return null;\n }\n const [, sessionId] = identity.subject.split(TOKEN_SUB_CLAIM_DIVIDER);\n return sessionId as GenericId<\"Session\">;\n}\n"],"mappings":";;;;;;AAgBA,MAAM,oCAAoC,MAAO,KAAK,KAAK,KAAK;;AAGhE,eAAsB,8BACpB,KACA,QACA,QACA,WACA,gBACsB;AACtB,QAAO;EACL;EACA;EACA,QAAQ,iBACJ,MAAM,yBAAyB,KAAK,QAAQ;GAC1C;GACA;GACA,sBAAsB;GACtB,sBAAsB;GACvB,CAAC,GACF;EACL;;;AAIH,eAAsB,kCACpB,KACA,QACA,QACA;CACA,MAAM,KAAK,OAAO,KAAK,OAAO;CAC9B,MAAM,oBAAoB,MAAM,iBAAiB,IAAI;AACrD,KAAI,sBAAsB,MAAM;EAC9B,MAAM,kBAAkB,MAAM,GAAG,SAAS,QAAQ,kBAAkB;AACpE,MAAI,oBAAoB,KACtB,OAAM,cAAc,KAAK,iBAAiB,OAAO;;AAGrD,QAAO,MAAM,cAAc,KAAK,QAAQ,OAAO;;;AAIjD,eAAsB,yBACpB,KACA,QACA,MAMA;CACA,MAAM,MAAM;EAAE,QAAQ,KAAK;EAAQ,WAAW,KAAK;EAAW;CAC9D,MAAM,iBACJ,KAAK,wBACJ,MAAM,mBACL,KACA,QACA,KAAK,WACL,KAAK,qBACN;CACH,MAAM,SAAS;EACb,OAAO,MAAM,cAAc,KAAK,OAAO;EACvC,cAAc,GAAG,iBAAiB,wBAAwB,KAAK;EAChE;AACD,cACE,WAAW,OACX,mBAAmB,YAAY,OAAO,MAAM,CAAC,qBAAqB,YAAY,eAAe,CAAC,eAAe,YAAY,KAAK,UAAU,GACzI;AACD,QAAO;;AAGT,eAAe,cACb,KACA,QACA,QACA;CACA,MAAM,KAAK,OAAO,KAAK,OAAO;CAC9B,MAAM,iBACJ,KAAK,KAAK,IACT,OAAO,SAAS,oBACd,QAAQ,IAAI,mCAAmC,SAC5C,OAAO,QAAQ,IAAI,+BAA+B,GAClD,WACJ;AACJ,QAAQ,MAAM,GAAG,SAAS,OACxB,QACA,eACD;;;AAIH,eAAsB,cACpB,KACA,SACA,QACA;CACA,MAAM,KAAK,OAAO,KAAK,OAAO;AAC9B,OAAM,GAAG,SAAS,OAAO,QAAQ,IAAI;AACrC,OAAM,GAAG,cAAc,UAAU,QAAQ,IAAI;;;;;;;;AAS/C,eAAsB,iBAAiB,KAAqB;CAC1D,MAAM,WAAW,MAAM,IAAI,KAAK,iBAAiB;AACjD,KAAI,aAAa,KACf,QAAO;CAET,MAAM,GAAG,aAAa,SAAS,QAAQ,MAAM,wBAAwB;AACrE,QAAO"}
@@ -1 +0,0 @@
1
- export { };