@robelest/convex-auth 0.0.4-preview.13 → 0.0.4-preview.16

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 (328) hide show
  1. package/README.md +140 -9
  2. package/dist/bin.cjs +5957 -5478
  3. package/dist/client/index.d.ts +3 -7
  4. package/dist/client/index.d.ts.map +1 -1
  5. package/dist/client/index.js +27 -26
  6. package/dist/client/index.js.map +1 -1
  7. package/dist/component/_generated/api.d.ts +14 -0
  8. package/dist/component/_generated/api.d.ts.map +1 -1
  9. package/dist/component/_generated/api.js.map +1 -1
  10. package/dist/component/_generated/component.d.ts +1672 -24
  11. package/dist/component/_generated/component.d.ts.map +1 -1
  12. package/dist/component/convex.config.d.ts +2 -2
  13. package/dist/component/convex.config.d.ts.map +1 -1
  14. package/dist/component/index.d.ts +1 -1
  15. package/dist/component/index.js +2 -2
  16. package/dist/component/model.d.ts +153 -0
  17. package/dist/component/model.d.ts.map +1 -0
  18. package/dist/component/model.js +343 -0
  19. package/dist/component/model.js.map +1 -0
  20. package/dist/component/providers/sso.d.ts +1 -1
  21. package/dist/component/public/enterprise.d.ts +54 -0
  22. package/dist/component/public/enterprise.d.ts.map +1 -0
  23. package/dist/component/public/enterprise.js +515 -0
  24. package/dist/component/public/enterprise.js.map +1 -0
  25. package/dist/component/public/factors.d.ts +52 -0
  26. package/dist/component/public/factors.d.ts.map +1 -0
  27. package/dist/component/public/factors.js +285 -0
  28. package/dist/component/public/factors.js.map +1 -0
  29. package/dist/component/public/groups.d.ts +116 -0
  30. package/dist/component/public/groups.d.ts.map +1 -0
  31. package/dist/component/public/groups.js +596 -0
  32. package/dist/component/public/groups.js.map +1 -0
  33. package/dist/component/public/identity.d.ts +93 -0
  34. package/dist/component/public/identity.d.ts.map +1 -0
  35. package/dist/component/public/identity.js +426 -0
  36. package/dist/component/public/identity.js.map +1 -0
  37. package/dist/component/public/keys.d.ts +41 -0
  38. package/dist/component/public/keys.d.ts.map +1 -0
  39. package/dist/component/public/keys.js +157 -0
  40. package/dist/component/public/keys.js.map +1 -0
  41. package/dist/component/public/shared.d.ts +26 -0
  42. package/dist/component/public/shared.d.ts.map +1 -0
  43. package/dist/component/public/shared.js +32 -0
  44. package/dist/component/public/shared.js.map +1 -0
  45. package/dist/component/public.d.ts +9 -321
  46. package/dist/component/public.d.ts.map +1 -1
  47. package/dist/component/public.js +6 -2145
  48. package/dist/component/schema.d.ts +406 -260
  49. package/dist/component/schema.js +37 -32
  50. package/dist/component/schema.js.map +1 -1
  51. package/dist/component/server/auth.d.ts +161 -15
  52. package/dist/component/server/auth.d.ts.map +1 -1
  53. package/dist/component/server/auth.js +100 -7
  54. package/dist/component/server/auth.js.map +1 -1
  55. package/dist/component/server/cookies.js +3 -0
  56. package/dist/component/server/cookies.js.map +1 -1
  57. package/dist/component/server/db.js +1 -0
  58. package/dist/component/server/db.js.map +1 -1
  59. package/dist/component/server/device.js +3 -1
  60. package/dist/component/server/device.js.map +1 -1
  61. package/dist/component/server/domains/core.js +629 -0
  62. package/dist/component/server/domains/core.js.map +1 -0
  63. package/dist/component/server/domains/sso.js +884 -0
  64. package/dist/component/server/domains/sso.js.map +1 -0
  65. package/dist/component/server/factory.d.ts +136 -0
  66. package/dist/component/server/factory.d.ts.map +1 -0
  67. package/dist/component/server/factory.js +1134 -0
  68. package/dist/component/server/factory.js.map +1 -0
  69. package/dist/component/server/fx.js +2 -1
  70. package/dist/component/server/fx.js.map +1 -1
  71. package/dist/component/server/http.js +287 -0
  72. package/dist/component/server/http.js.map +1 -0
  73. package/dist/component/server/identity.js +13 -0
  74. package/dist/component/server/identity.js.map +1 -0
  75. package/dist/component/server/keys.js +4 -0
  76. package/dist/component/server/keys.js.map +1 -1
  77. package/dist/component/server/mutations/account.js +1 -1
  78. package/dist/component/server/mutations/index.js +2 -2
  79. package/dist/component/server/mutations/index.js.map +1 -1
  80. package/dist/component/server/mutations/invalidate.js +1 -1
  81. package/dist/component/server/mutations/oauth.js +10 -7
  82. package/dist/component/server/mutations/oauth.js.map +1 -1
  83. package/dist/component/server/mutations/refresh.js +1 -1
  84. package/dist/component/server/mutations/register.js +1 -1
  85. package/dist/component/server/mutations/retrieve.js +1 -1
  86. package/dist/component/server/mutations/signature.js +1 -1
  87. package/dist/component/server/mutations/store.js +6 -3
  88. package/dist/component/server/mutations/store.js.map +1 -1
  89. package/dist/component/server/mutations/verify.js +1 -1
  90. package/dist/component/server/oauth.js +3 -0
  91. package/dist/component/server/oauth.js.map +1 -1
  92. package/dist/component/server/passkey.js +3 -2
  93. package/dist/component/server/passkey.js.map +1 -1
  94. package/dist/component/server/provider.js +2 -0
  95. package/dist/component/server/provider.js.map +1 -1
  96. package/dist/component/server/providers.js +10 -0
  97. package/dist/component/server/providers.js.map +1 -1
  98. package/dist/component/server/ratelimit.js +3 -0
  99. package/dist/component/server/ratelimit.js.map +1 -1
  100. package/dist/component/server/redirects.js +2 -0
  101. package/dist/component/server/redirects.js.map +1 -1
  102. package/dist/component/server/refresh.js +5 -0
  103. package/dist/component/server/refresh.js.map +1 -1
  104. package/dist/component/server/sessions.js +5 -0
  105. package/dist/component/server/sessions.js.map +1 -1
  106. package/dist/component/server/signin.js +2 -1
  107. package/dist/component/server/signin.js.map +1 -1
  108. package/dist/component/server/sso.js +166 -19
  109. package/dist/component/server/sso.js.map +1 -1
  110. package/dist/component/server/tokens.js +1 -0
  111. package/dist/component/server/tokens.js.map +1 -1
  112. package/dist/component/server/totp.js +4 -2
  113. package/dist/component/server/totp.js.map +1 -1
  114. package/dist/component/server/types.d.ts +106 -38
  115. package/dist/component/server/types.d.ts.map +1 -1
  116. package/dist/component/server/types.js.map +1 -1
  117. package/dist/component/server/users.js +1 -0
  118. package/dist/component/server/users.js.map +1 -1
  119. package/dist/component/server/utils.js +44 -2
  120. package/dist/component/server/utils.js.map +1 -1
  121. package/dist/providers/anonymous.d.ts +1 -1
  122. package/dist/providers/credentials.d.ts +1 -1
  123. package/dist/providers/password.d.ts +1 -1
  124. package/dist/providers/sso.d.ts +1 -1
  125. package/dist/providers/sso.js.map +1 -1
  126. package/dist/server/auth.d.ts +163 -17
  127. package/dist/server/auth.d.ts.map +1 -1
  128. package/dist/server/auth.js +100 -7
  129. package/dist/server/auth.js.map +1 -1
  130. package/dist/server/cookies.d.ts +1 -38
  131. package/dist/server/cookies.js +3 -0
  132. package/dist/server/cookies.js.map +1 -1
  133. package/dist/server/db.d.ts +1 -125
  134. package/dist/server/db.js +1 -0
  135. package/dist/server/db.js.map +1 -1
  136. package/dist/server/device.d.ts +1 -24
  137. package/dist/server/device.js +3 -1
  138. package/dist/server/device.js.map +1 -1
  139. package/dist/server/domains/core.d.ts +434 -0
  140. package/dist/server/domains/core.d.ts.map +1 -0
  141. package/dist/server/domains/core.js +629 -0
  142. package/dist/server/domains/core.js.map +1 -0
  143. package/dist/server/domains/sso.d.ts +409 -0
  144. package/dist/server/domains/sso.d.ts.map +1 -0
  145. package/dist/server/domains/sso.js +884 -0
  146. package/dist/server/domains/sso.js.map +1 -0
  147. package/dist/server/enterpriseValidators.d.ts +1 -0
  148. package/dist/server/enterpriseValidators.js +60 -0
  149. package/dist/server/enterpriseValidators.js.map +1 -0
  150. package/dist/server/factory.d.ts +136 -0
  151. package/dist/server/factory.d.ts.map +1 -0
  152. package/dist/server/factory.js +1134 -0
  153. package/dist/server/factory.js.map +1 -0
  154. package/dist/server/fx.d.ts +1 -16
  155. package/dist/server/fx.d.ts.map +1 -1
  156. package/dist/server/fx.js +1 -0
  157. package/dist/server/fx.js.map +1 -1
  158. package/dist/server/http.d.ts +59 -0
  159. package/dist/server/http.d.ts.map +1 -0
  160. package/dist/server/http.js +287 -0
  161. package/dist/server/http.js.map +1 -0
  162. package/dist/server/identity.d.ts +1 -0
  163. package/dist/server/identity.js +13 -0
  164. package/dist/server/identity.js.map +1 -0
  165. package/dist/server/index.d.ts +468 -1
  166. package/dist/server/index.d.ts.map +1 -1
  167. package/dist/server/index.js +530 -36
  168. package/dist/server/index.js.map +1 -1
  169. package/dist/server/keys.d.ts +1 -57
  170. package/dist/server/keys.js +4 -0
  171. package/dist/server/keys.js.map +1 -1
  172. package/dist/server/mutations/account.d.ts +7 -7
  173. package/dist/server/mutations/account.d.ts.map +1 -1
  174. package/dist/server/mutations/code.d.ts +13 -13
  175. package/dist/server/mutations/code.d.ts.map +1 -1
  176. package/dist/server/mutations/index.d.ts +107 -107
  177. package/dist/server/mutations/index.d.ts.map +1 -1
  178. package/dist/server/mutations/index.js +1 -1
  179. package/dist/server/mutations/index.js.map +1 -1
  180. package/dist/server/mutations/invalidate.d.ts +5 -5
  181. package/dist/server/mutations/invalidate.d.ts.map +1 -1
  182. package/dist/server/mutations/oauth.d.ts +10 -10
  183. package/dist/server/mutations/oauth.d.ts.map +1 -1
  184. package/dist/server/mutations/oauth.js +9 -6
  185. package/dist/server/mutations/oauth.js.map +1 -1
  186. package/dist/server/mutations/refresh.d.ts +4 -4
  187. package/dist/server/mutations/register.d.ts +12 -12
  188. package/dist/server/mutations/register.d.ts.map +1 -1
  189. package/dist/server/mutations/retrieve.d.ts +7 -7
  190. package/dist/server/mutations/signature.d.ts +5 -5
  191. package/dist/server/mutations/signin.d.ts +6 -6
  192. package/dist/server/mutations/signin.d.ts.map +1 -1
  193. package/dist/server/mutations/signout.d.ts +1 -1
  194. package/dist/server/mutations/store.d.ts +3 -2
  195. package/dist/server/mutations/store.d.ts.map +1 -1
  196. package/dist/server/mutations/store.js +6 -3
  197. package/dist/server/mutations/store.js.map +1 -1
  198. package/dist/server/mutations/verifier.d.ts +1 -1
  199. package/dist/server/mutations/verify.d.ts +11 -11
  200. package/dist/server/mutations/verify.d.ts.map +1 -1
  201. package/dist/server/oauth.d.ts +1 -59
  202. package/dist/server/oauth.js +3 -0
  203. package/dist/server/oauth.js.map +1 -1
  204. package/dist/server/passkey.d.ts.map +1 -1
  205. package/dist/server/passkey.js +3 -2
  206. package/dist/server/passkey.js.map +1 -1
  207. package/dist/server/provider.d.ts +1 -14
  208. package/dist/server/provider.d.ts.map +1 -1
  209. package/dist/server/provider.js +2 -0
  210. package/dist/server/provider.js.map +1 -1
  211. package/dist/server/providers.js +10 -0
  212. package/dist/server/providers.js.map +1 -1
  213. package/dist/server/ratelimit.d.ts +1 -22
  214. package/dist/server/ratelimit.js +3 -0
  215. package/dist/server/ratelimit.js.map +1 -1
  216. package/dist/server/redirects.d.ts +1 -10
  217. package/dist/server/redirects.js +2 -0
  218. package/dist/server/redirects.js.map +1 -1
  219. package/dist/server/refresh.d.ts +1 -37
  220. package/dist/server/refresh.js +5 -0
  221. package/dist/server/refresh.js.map +1 -1
  222. package/dist/server/sessions.d.ts +1 -28
  223. package/dist/server/sessions.js +5 -0
  224. package/dist/server/sessions.js.map +1 -1
  225. package/dist/server/signin.d.ts +1 -55
  226. package/dist/server/signin.js +2 -1
  227. package/dist/server/signin.js.map +1 -1
  228. package/dist/server/sso.d.ts +1 -348
  229. package/dist/server/sso.js +165 -18
  230. package/dist/server/sso.js.map +1 -1
  231. package/dist/server/templates.d.ts +1 -21
  232. package/dist/server/templates.js +1 -0
  233. package/dist/server/templates.js.map +1 -1
  234. package/dist/server/tokens.d.ts +1 -11
  235. package/dist/server/tokens.js +1 -0
  236. package/dist/server/tokens.js.map +1 -1
  237. package/dist/server/totp.d.ts +1 -23
  238. package/dist/server/totp.js +4 -2
  239. package/dist/server/totp.js.map +1 -1
  240. package/dist/server/types.d.ts +114 -77
  241. package/dist/server/types.d.ts.map +1 -1
  242. package/dist/server/types.js.map +1 -1
  243. package/dist/server/users.d.ts +1 -31
  244. package/dist/server/users.js +1 -0
  245. package/dist/server/users.js.map +1 -1
  246. package/dist/server/utils.d.ts +1 -27
  247. package/dist/server/utils.js +44 -2
  248. package/dist/server/utils.js.map +1 -1
  249. package/dist/server/version.d.ts +1 -1
  250. package/dist/server/version.js +1 -1
  251. package/dist/server/version.js.map +1 -1
  252. package/package.json +4 -5
  253. package/src/cli/bin.ts +5 -0
  254. package/src/cli/index.ts +22 -9
  255. package/src/cli/keys.ts +3 -0
  256. package/src/client/index.ts +36 -37
  257. package/src/component/_generated/api.ts +14 -0
  258. package/src/component/_generated/component.ts +2106 -9
  259. package/src/component/index.ts +3 -1
  260. package/src/component/model.ts +441 -0
  261. package/src/component/public/enterprise.ts +753 -0
  262. package/src/component/public/factors.ts +332 -0
  263. package/src/component/public/groups.ts +932 -0
  264. package/src/component/public/identity.ts +566 -0
  265. package/src/component/public/keys.ts +209 -0
  266. package/src/component/public/shared.ts +119 -0
  267. package/src/component/public.ts +5 -2965
  268. package/src/component/schema.ts +68 -63
  269. package/src/providers/sso.ts +1 -1
  270. package/src/server/auth.ts +413 -18
  271. package/src/server/cookies.ts +3 -0
  272. package/src/server/db.ts +3 -0
  273. package/src/server/device.ts +3 -1
  274. package/src/server/domains/core.ts +1071 -0
  275. package/src/server/domains/sso.ts +1749 -0
  276. package/src/server/enterpriseValidators.ts +93 -0
  277. package/src/server/factory.ts +2181 -0
  278. package/src/server/fx.ts +1 -0
  279. package/src/server/http.ts +529 -0
  280. package/src/server/identity.ts +18 -0
  281. package/src/server/index.ts +806 -40
  282. package/src/server/keys.ts +4 -0
  283. package/src/server/mutations/index.ts +1 -1
  284. package/src/server/mutations/oauth.ts +36 -8
  285. package/src/server/mutations/store.ts +6 -3
  286. package/src/server/oauth.ts +6 -0
  287. package/src/server/passkey.ts +3 -2
  288. package/src/server/provider.ts +2 -0
  289. package/src/server/providers.ts +20 -0
  290. package/src/server/ratelimit.ts +3 -0
  291. package/src/server/redirects.ts +2 -0
  292. package/src/server/refresh.ts +5 -0
  293. package/src/server/sessions.ts +5 -0
  294. package/src/server/signin.ts +1 -0
  295. package/src/server/sso.ts +259 -17
  296. package/src/server/templates.ts +1 -0
  297. package/src/server/tokens.ts +1 -0
  298. package/src/server/totp.ts +4 -2
  299. package/src/server/types.ts +178 -83
  300. package/src/server/users.ts +1 -0
  301. package/src/server/utils.ts +71 -1
  302. package/src/server/version.ts +1 -1
  303. package/dist/component/public.js.map +0 -1
  304. package/dist/component/server/implementation.d.ts +0 -1264
  305. package/dist/component/server/implementation.d.ts.map +0 -1
  306. package/dist/component/server/implementation.js +0 -2365
  307. package/dist/component/server/implementation.js.map +0 -1
  308. package/dist/server/cookies.d.ts.map +0 -1
  309. package/dist/server/db.d.ts.map +0 -1
  310. package/dist/server/device.d.ts.map +0 -1
  311. package/dist/server/implementation.d.ts +0 -1264
  312. package/dist/server/implementation.d.ts.map +0 -1
  313. package/dist/server/implementation.js +0 -2365
  314. package/dist/server/implementation.js.map +0 -1
  315. package/dist/server/keys.d.ts.map +0 -1
  316. package/dist/server/oauth.d.ts.map +0 -1
  317. package/dist/server/ratelimit.d.ts.map +0 -1
  318. package/dist/server/redirects.d.ts.map +0 -1
  319. package/dist/server/refresh.d.ts.map +0 -1
  320. package/dist/server/sessions.d.ts.map +0 -1
  321. package/dist/server/signin.d.ts.map +0 -1
  322. package/dist/server/sso.d.ts.map +0 -1
  323. package/dist/server/templates.d.ts.map +0 -1
  324. package/dist/server/tokens.d.ts.map +0 -1
  325. package/dist/server/totp.d.ts.map +0 -1
  326. package/dist/server/users.d.ts.map +0 -1
  327. package/dist/server/utils.d.ts.map +0 -1
  328. package/src/server/implementation.ts +0 -5336
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.js","names":["serializeCookie","state"],"sources":["../../src/server/factory.ts"],"sourcesContent":["import {\n Auth,\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 { redirectToParamCookie, useRedirectToParam } from \"./cookies\";\nimport { createCoreDomains } from \"./domains/core\";\nimport { createSsoDomain } from \"./domains/sso\";\nimport { isAuthError } from \"./errors\";\nimport { AuthError, Fx } from \"./fx\";\nimport {\n addAuthRoutes,\n addOpenIdRoutes,\n addSSORoutes,\n convertErrorsToResponse,\n createHttpAction,\n createHttpRoute,\n getCookies,\n type SSORuntimeRoute,\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 { GetProviderOrThrowFunc } from \"./provider\";\nimport { configDefaults, listAvailableProviders } from \"./providers\";\nimport { redirectAbsoluteUrl, setURLSearchParam } from \"./redirects\";\nimport { signInImpl } from \"./signin\";\nimport {\n createEnterpriseSamlMetadataXml,\n createEnterpriseSamlSignInRequest,\n createEnterpriseOidcRuntime,\n createServiceProviderMetadata,\n createSamlPostBindingResponse,\n encodeEnterpriseSamlRelayState,\n enterpriseOidcProviderId,\n enterpriseSamlProviderId,\n getEnterpriseOidcUrls,\n getPublicOidcConfig,\n getSamlServiceProviderOptions,\n isEnterpriseSamlSourceActive,\n parseEnterpriseSamlLoginResponse,\n parseEnterpriseSamlLogoutMessage,\n getOidcConfig,\n getSamlConfig,\n normalizeEnterprisePolicy,\n normalizeDomain,\n patchEnterprisePolicy,\n parseScimListRequest,\n parseScimPath,\n parseSamlIdpMetadata,\n profileFromSamlExtract,\n SCIM_GROUP_SCHEMA_ID,\n SCIM_USER_SCHEMA_ID,\n scimError,\n scimJson,\n serializeScimGroup,\n serializeScimUser,\n upsertProtocolConfig,\n validateEnterpriseSamlLoginRelayState,\n withOidcSecretState,\n} from \"./sso\";\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 new AuthError(\"PROVIDER_NOT_CONFIGURED\", detail, {\n provider: id,\n }).toConvexError();\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 new AuthError(\n \"INVALID_PARAMETERS\",\n enterpriseNotFoundError,\n ).toConvexError();\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 new AuthError(\n \"INVALID_PARAMETERS\",\n \"Enterprise connection is not active.\",\n ).toConvexError();\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 new AuthError(\n \"INVALID_PARAMETERS\",\n \"Enterprise connection is not active.\",\n ).toConvexError();\n }\n const saml = getSamlConfig(loaded.config);\n if (!saml.idp?.metadataXml) {\n throw new AuthError(\n \"PROVIDER_NOT_CONFIGURED\",\n \"SAML is not configured for this enterprise.\",\n ).toConvexError();\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 new AuthError(\n \"PROVIDER_NOT_CONFIGURED\",\n \"OIDC is not configured for this enterprise.\",\n ).toConvexError();\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 new AuthError(\"MISSING_BEARER_TOKEN\").toConvexError();\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 new AuthError(\n \"INVALID_API_KEY\",\n \"Invalid SCIM token.\",\n ).toConvexError();\n }\n const parsedPath = parseScimPath(new URL(request.url).pathname);\n if (parsedPath.enterpriseId !== scimConfig.enterpriseId) {\n throw new AuthError(\n \"INVALID_API_KEY\",\n \"SCIM token/tenant mismatch.\",\n ).toConvexError();\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 new AuthError(\n \"INVALID_PARAMETERS\",\n \"Enterprise not found.\",\n ).toConvexError();\n }\n return { scimConfig, enterprise, parsedPath };\n };\n\n type ScimState = {\n ctx: ComponentCtx;\n request: Request;\n url: URL;\n parsedPath: ReturnType<typeof parseScimPath>;\n enterprise: Awaited<\n ReturnType<typeof getEnterpriseScimContext>\n >[\"enterprise\"];\n scimConfig: Awaited<\n ReturnType<typeof getEnterpriseScimContext>\n >[\"scimConfig\"];\n policy: ReturnType<typeof normalizeEnterprisePolicy>;\n recordScimEvent: (\n eventType: string,\n ok: boolean,\n subjectType: string,\n subjectId?: string,\n metadata?: Record<string, unknown>,\n ) => Promise<void>;\n };\n\n type ScimHandler = (state: ScimState) => Promise<Response>;\n\n const SCIM_SCHEMAS = [\n {\n id: SCIM_USER_SCHEMA_ID,\n name: \"User\",\n description: \"User Account\",\n attributes: [\n { name: \"userName\", type: \"string\", required: true },\n { name: \"displayName\", type: \"string\" },\n { name: \"active\", type: \"boolean\" },\n { name: \"emails\", type: \"complex\", multiValued: true },\n ],\n },\n {\n id: SCIM_GROUP_SCHEMA_ID,\n name: \"Group\",\n description: \"Group\",\n attributes: [\n { name: \"displayName\", type: \"string\", required: true },\n { name: \"members\", type: \"complex\", multiValued: true },\n ],\n },\n ] as const;\n\n const SCIM_RESOURCE_TYPES = [\n {\n id: \"User\",\n name: \"User\",\n endpoint: \"/Users\",\n schema: SCIM_USER_SCHEMA_ID,\n },\n {\n id: \"Group\",\n name: \"Group\",\n endpoint: \"/Groups\",\n schema: SCIM_GROUP_SCHEMA_ID,\n },\n ] as const;\n\n const handleStaticScimCollection = <T extends { id?: string; name?: string }>(\n items: readonly T[],\n resourceId: string | undefined,\n opts: { by: \"id\" | \"name\"; notFound: string },\n ) => {\n if (resourceId !== undefined) {\n const item = items.find(\n (entry) => entry[opts.by] === decodeURIComponent(resourceId),\n );\n return item ? scimJson(item) : scimError(404, \"notFound\", opts.notFound);\n }\n return scimJson({\n schemas: [\"urn:ietf:params:scim:api:messages:2.0:ListResponse\"],\n Resources: items,\n totalResults: items.length,\n startIndex: 1,\n itemsPerPage: items.length,\n });\n };\n\n const filterScimCollection = <T>(\n items: T[],\n filter: ReturnType<typeof parseScimListRequest>[\"filter\"],\n filters: Record<string, (item: T, value: string) => boolean>,\n ) => {\n if (!filter) {\n return items;\n }\n const predicate = filters[filter.attribute];\n if (!predicate) {\n throw new Error(\"Unsupported SCIM filter.\");\n }\n return items.filter((item) => predicate(item, filter.value));\n };\n\n const paginateScimCollection = <T>(\n items: T[],\n listRequest: ReturnType<typeof parseScimListRequest>,\n ) => {\n const start = listRequest.startIndex - 1;\n return items.slice(start, start + listRequest.count);\n };\n\n const requireScimResourceId = (\n resourceId: string | undefined,\n label: string,\n ) => {\n if (!resourceId) {\n return scimError(400, \"invalidPath\", `${label} resource ID is required.`);\n }\n return null;\n };\n\n const readScimJson = async (request: Request) =>\n (await request.json()) as Record<string, any>;\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: createSsoDomain({\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 // 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 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 if (hasSSO) {\n const handleSamlAcs = async (\n ctx: GenericActionCtx<any>,\n request: Request,\n runtimeRoute: SSORuntimeRoute,\n ) =>\n Fx.run(\n Fx.gen(function* () {\n yield* Fx.guard(\n runtimeRoute.protocol !== \"saml\" ||\n runtimeRoute.rest.length !== 1 ||\n runtimeRoute.rest[0] !== \"acs\",\n Fx.fail(\n new AuthError(\n \"INVALID_PARAMETERS\",\n \"Invalid enterprise runtime path.\",\n ).toConvexError(),\n ),\n );\n\n const enterpriseId = runtimeRoute.enterpriseId;\n const { loaded, enterprise, saml } = yield* Fx.from({\n ok: () => loadActiveEnterpriseSamlOrThrow(ctx, enterpriseId),\n err: (e) => e,\n });\n\n const parsedResponse = yield* Fx.from({\n ok: () =>\n parseEnterpriseSamlLoginResponse({\n request,\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n source: { kind: \"enterprise\", id: enterprise._id },\n config: loaded.config,\n }),\n err: (e) =>\n new AuthError(\n \"OAUTH_PROVIDER_ERROR\",\n `SAML response parse failed: ${e instanceof Error ? e.message : String(e)}`,\n ).toConvexError(),\n });\n\n yield* Fx.from({\n ok: () => {\n validateEnterpriseSamlLoginRelayState({\n relayState: parsedResponse.relayState,\n source: { kind: \"enterprise\", id: enterprise._id },\n inResponseTo:\n parsedResponse.parsed.extract?.response?.inResponseTo,\n });\n return Promise.resolve();\n },\n err: () =>\n new AuthError(\n \"OAUTH_INVALID_STATE\",\n \"SAML RelayState did not match the pending login request.\",\n ).toConvexError(),\n });\n\n const { samlAttributes, samlSessionIndex, ...userProfile } =\n profileFromSamlExtract(\n parsedResponse.parsed.extract,\n saml.attributeMapping,\n );\n const profile = userProfile as Record<string, unknown> & {\n id: string;\n };\n\n const maybeRedirectTo = useRedirectToParam(\n enterpriseSamlProviderId(enterprise._id),\n getCookies(request),\n );\n\n const verificationCode = yield* Fx.from({\n ok: () =>\n callUserOAuth(ctx, {\n provider: enterpriseSamlProviderId(enterprise._id),\n providerAccountId: profile.id,\n profile,\n signature: parsedResponse.relayState.signature,\n accountExtend: {\n identity: {\n protocol: \"saml\",\n enterpriseId: enterprise._id,\n subject: profile.id,\n entityId:\n typeof saml.entityId === \"string\"\n ? saml.entityId\n : undefined,\n },\n saml: {\n attributes: samlAttributes,\n sessionIndex: samlSessionIndex,\n },\n },\n }),\n err: (e) => e,\n });\n\n const destinationUrl = yield* Fx.from({\n ok: () =>\n redirectAbsoluteUrl(config, {\n redirectTo:\n maybeRedirectTo?.redirectTo ??\n (typeof parsedResponse.relayState.redirectTo ===\n \"string\"\n ? parsedResponse.relayState.redirectTo\n : undefined),\n }),\n err: (e) => e,\n });\n\n const vurl = setURLSearchParam(\n destinationUrl,\n \"code\",\n verificationCode,\n );\n const vheaders = new Headers({ Location: vurl });\n vheaders.set(\"Cache-Control\", \"must-revalidate\");\n for (const { name, value, options } of maybeRedirectTo !== null\n ? [maybeRedirectTo.updatedCookie]\n : []) {\n vheaders.append(\n \"Set-Cookie\",\n serializeCookie(name, value, options),\n );\n }\n return new Response(null, { status: 302, headers: vheaders });\n }).pipe(Fx.recover((e) => Fx.fatal(e))),\n );\n\n const handleSamlSlo = async (\n ctx: GenericActionCtx<any>,\n request: Request,\n runtimeRoute: SSORuntimeRoute,\n ) => {\n if (\n runtimeRoute.protocol !== \"saml\" ||\n runtimeRoute.rest.length !== 1 ||\n runtimeRoute.rest[0] !== \"slo\"\n ) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Invalid enterprise runtime path.\",\n ).toConvexError();\n }\n const { loaded, enterprise } =\n await loadActiveEnterpriseSamlOrThrow(\n ctx,\n runtimeRoute.enterpriseId,\n );\n const parsedMessage = await parseEnterpriseSamlLogoutMessage({\n request,\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n source: { kind: \"enterprise\", id: enterprise._id },\n config: loaded.config,\n });\n if (parsedMessage.hasSamlRequest && parsedMessage.parsedRequest) {\n const responseContext = (\n parsedMessage.runtime.sp as any\n ).createLogoutResponse(\n parsedMessage.runtime.idp as any,\n parsedMessage.parsedRequest.extract,\n parsedMessage.binding as any,\n parsedMessage.relayState ?? \"\",\n ) as any;\n if (parsedMessage.binding === \"redirect\") {\n return new Response(null, {\n status: 302,\n headers: { Location: responseContext.context },\n });\n }\n return createSamlPostBindingResponse({\n endpoint: responseContext.entityEndpoint,\n parameter: \"SAMLResponse\",\n value: responseContext.context,\n relayState: parsedMessage.relayState,\n });\n }\n if (parsedMessage.hasSamlResponse) {\n return new Response(null, { status: 204 });\n }\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Missing SAML logout payload.\",\n ).toConvexError();\n };\n\n const handleScimRequest = async (\n ctx: GenericActionCtx<any>,\n request: Request,\n ) => {\n try {\n const { scimConfig, enterprise, parsedPath } =\n await getEnterpriseScimContext(ctx, request);\n const url = new URL(request.url);\n const state: ScimState = {\n ctx,\n request,\n url,\n parsedPath,\n enterprise,\n scimConfig,\n policy: getPolicyFromEnterprise(enterprise),\n recordScimEvent: async (\n eventType,\n ok,\n subjectType,\n subjectId,\n metadata,\n ) => {\n const auditEventId = await recordEnterpriseAuditEvent(ctx, {\n enterpriseId: enterprise._id,\n groupId: enterprise.groupId,\n eventType,\n actorType: \"scim\",\n subjectType,\n subjectId,\n ok,\n metadata,\n });\n await emitEnterpriseWebhookDeliveries(ctx, {\n enterpriseId: enterprise._id,\n eventType,\n auditEventId,\n payload: {\n enterpriseId: enterprise._id,\n subjectId,\n metadata,\n },\n });\n },\n };\n\n const handleUsersGet: ScimHandler = async (state) => {\n const members = await auth.member.list(state.ctx, {\n where: { groupId: state.enterprise.groupId },\n limit: 100,\n });\n const identities = await state.ctx.runQuery(\n config.component.public\n .enterpriseScimIdentityListByEnterprise,\n { enterpriseId: state.enterprise._id },\n );\n const identityByUserId = new Map(\n identities\n .filter((identity: any) => identity.userId !== undefined)\n .map((identity: any) => [identity.userId, identity]),\n );\n const users = (\n await Promise.all(\n members.items.map(async (member: any) => {\n const user = await auth.user.get(\n state.ctx,\n member.userId,\n );\n return user\n ? {\n user,\n member,\n identity: identityByUserId.get(user._id),\n }\n : null;\n }),\n )\n ).filter(Boolean) as Array<{\n user: any;\n member: any;\n identity?: any;\n }>;\n const listRequest = parseScimListRequest(state.url);\n const filtered = filterScimCollection(\n users,\n listRequest.filter,\n {\n id: (item: { user: any }, value: string) =>\n item.user._id === value,\n externalId: (item: { identity?: any }, value: string) =>\n item.identity?.externalId === value,\n userName: (item: { user: any }, value: string) =>\n item.user.email === value,\n \"emails.value\": (item: { user: any }, value: string) =>\n item.user.email === value,\n active: (\n item: { identity?: any; member: any },\n value: string,\n ) =>\n String(\n item.identity?.active ??\n item.member.status === \"active\",\n ) === value,\n },\n );\n if (state.parsedPath.resourceId) {\n const resource = filtered.find(\n ({ user }) => user._id === state.parsedPath.resourceId,\n );\n return resource\n ? scimJson(\n serializeScimUser({\n id: resource.user._id,\n user: resource.user,\n externalId: resource.identity?.externalId,\n location: `${state.url.origin}${state.url.pathname.replace(/\\/[^/]+$/, \"\")}/${resource.user._id}`,\n active:\n resource.identity?.active ??\n resource.member.status === \"active\",\n }),\n 200,\n {\n Location: `${state.url.origin}${state.url.pathname.replace(/\\/[^/]+$/, \"\")}/${resource.user._id}`,\n },\n )\n : scimError(404, \"notFound\", \"User not found.\");\n }\n const paged = paginateScimCollection(filtered, listRequest);\n await state.recordScimEvent(\n \"enterprise.scim.read\",\n true,\n \"enterprise_scim\",\n state.scimConfig._id,\n );\n return scimJson({\n schemas: [\n \"urn:ietf:params:scim:api:messages:2.0:ListResponse\",\n ],\n Resources: paged.map(({ user, identity, member }) =>\n serializeScimUser({\n id: user._id,\n user,\n externalId: identity?.externalId,\n location: `${state.url.origin}${state.url.pathname}/${user._id}`,\n active: identity?.active ?? member.status === \"active\",\n }),\n ),\n totalResults: filtered.length,\n startIndex: listRequest.startIndex,\n itemsPerPage: paged.length,\n });\n };\n\n const handleUsersPost: ScimHandler = async (state) => {\n const body = await readScimJson(state.request);\n const primaryEmail = Array.isArray(body.emails)\n ? (body.emails.find((entry) => entry.primary === true)\n ?.value ?? body.emails[0]?.value)\n : undefined;\n const phone = Array.isArray(body.phoneNumbers)\n ? body.phoneNumbers[0]?.value\n : undefined;\n const userId = (await state.ctx.runMutation(\n config.component.public.userInsert,\n {\n data: {\n name: body.displayName ?? body.name?.formatted,\n email: primaryEmail ?? body.userName,\n ...(typeof (primaryEmail ?? body.userName) === \"string\"\n ? { emailVerificationTime: Date.now() }\n : {}),\n phone,\n ...(typeof phone === \"string\"\n ? { phoneVerificationTime: Date.now() }\n : {}),\n },\n },\n )) as string;\n try {\n await auth.member.create(state.ctx, {\n groupId: state.enterprise.groupId,\n userId,\n roleIds: state.policy.provisioning.jit.defaultRoleIds,\n status: body.active === false ? \"inactive\" : \"active\",\n });\n } catch {}\n if (typeof body.externalId === \"string\") {\n await state.ctx.runMutation(\n config.component.public.enterpriseScimIdentityUpsert,\n {\n enterpriseId: state.enterprise._id,\n groupId: state.enterprise.groupId,\n resourceType: \"user\",\n externalId: body.externalId,\n userId,\n active: body.active !== false,\n raw: body,\n lastProvisionedAt: Date.now(),\n },\n );\n }\n await state.recordScimEvent(\n \"enterprise.scim.user.created\",\n true,\n \"user\",\n userId,\n );\n const createdUser = await auth.user.get(state.ctx, userId);\n const location = `${state.url.origin}${state.url.pathname}/${userId}`;\n return scimJson(\n serializeScimUser({\n id: userId,\n user: createdUser ?? {},\n externalId: body.externalId,\n location,\n active: body.active !== false,\n }),\n 201,\n { Location: location },\n );\n };\n\n const handleUsersUpsert: ScimHandler = async (state) => {\n const missing = requireScimResourceId(\n state.parsedPath.resourceId,\n \"User\",\n );\n if (missing) return missing;\n const userId = state.parsedPath.resourceId!;\n const existingUser = await auth.user.get(state.ctx, userId);\n if (!existingUser) {\n return scimError(404, \"notFound\", \"User not found.\");\n }\n const body = await readScimJson(state.request);\n const patchData: Record<string, unknown> = {};\n let nextActive: boolean | undefined;\n if (state.request.method === \"PUT\") {\n patchData.name = body.displayName ?? body.name?.formatted;\n patchData.email =\n body.userName ??\n (Array.isArray(body.emails)\n ? body.emails[0]?.value\n : undefined);\n patchData.phone = Array.isArray(body.phoneNumbers)\n ? body.phoneNumbers[0]?.value\n : undefined;\n if (typeof patchData.email === \"string\") {\n patchData.emailVerificationTime = Date.now();\n }\n if (typeof patchData.phone === \"string\") {\n patchData.phoneVerificationTime = Date.now();\n }\n } else {\n for (const operation of Array.isArray(body.Operations)\n ? body.Operations\n : []) {\n if (operation.path === \"active\") {\n nextActive = operation.value;\n }\n if (\n operation.path === \"displayName\" ||\n operation.path === \"name.formatted\"\n ) {\n patchData.name = operation.value;\n }\n if (\n operation.path === \"userName\" ||\n operation.path === \"emails.value\"\n ) {\n patchData.email = operation.value;\n if (typeof operation.value === \"string\") {\n patchData.emailVerificationTime = Date.now();\n }\n }\n if (operation.path === \"phoneNumbers.value\") {\n patchData.phone = operation.value;\n if (typeof operation.value === \"string\") {\n patchData.phoneVerificationTime = Date.now();\n }\n }\n }\n }\n await state.ctx.runMutation(config.component.public.userPatch, {\n userId,\n data: patchData,\n });\n const membership = await auth.member.getByUserAndGroup(\n state.ctx,\n {\n groupId: state.enterprise.groupId,\n userId,\n },\n );\n if (membership) {\n await auth.member.update(state.ctx, membership._id, {\n status:\n body.active === false || nextActive === false\n ? \"inactive\"\n : \"active\",\n });\n }\n await state.ctx.runMutation(\n config.component.public.enterpriseScimIdentityUpsert,\n {\n enterpriseId: state.enterprise._id,\n groupId: state.enterprise.groupId,\n resourceType: \"user\",\n externalId:\n typeof body.externalId === \"string\"\n ? body.externalId\n : ((\n await state.ctx.runQuery(\n config.component.public\n .enterpriseScimIdentityGetByEnterpriseAndUser,\n {\n enterpriseId: state.enterprise._id,\n userId,\n },\n )\n )?.externalId ?? userId),\n userId,\n active: body.active !== false && nextActive !== false,\n raw: body,\n lastProvisionedAt: Date.now(),\n },\n );\n await state.recordScimEvent(\n \"enterprise.scim.user.updated\",\n true,\n \"user\",\n userId,\n );\n const updatedUser = await auth.user.get(state.ctx, userId);\n const location = `${state.url.origin}${state.url.pathname}`;\n return scimJson(\n serializeScimUser({\n id: userId,\n user: updatedUser ?? existingUser,\n externalId:\n typeof body.externalId === \"string\"\n ? body.externalId\n : undefined,\n location,\n active: body.active !== false && nextActive !== false,\n }),\n 200,\n { Location: location },\n );\n };\n\n const handleUsersDelete: ScimHandler = async (state) => {\n const missing = requireScimResourceId(\n state.parsedPath.resourceId,\n \"User\",\n );\n if (missing) return missing;\n const userId = state.parsedPath.resourceId!;\n const membership = await auth.member.getByUserAndGroup(\n state.ctx,\n {\n groupId: state.enterprise.groupId,\n userId,\n },\n );\n if (membership) {\n await auth.member.delete(state.ctx, membership._id);\n }\n const identity = await state.ctx.runQuery(\n config.component.public\n .enterpriseScimIdentityGetByEnterpriseAndUser,\n {\n enterpriseId: state.enterprise._id,\n userId,\n },\n );\n if (identity) {\n if (state.policy.provisioning.deprovision.mode === \"hard\") {\n await state.ctx.runMutation(\n config.component.public.enterpriseScimIdentityDelete,\n { identityId: identity._id },\n );\n } else {\n await state.ctx.runMutation(\n config.component.public.enterpriseScimIdentityUpsert,\n {\n enterpriseId: identity.enterpriseId,\n groupId: identity.groupId,\n resourceType: identity.resourceType,\n externalId: identity.externalId,\n userId: identity.userId,\n mappedGroupId: identity.mappedGroupId,\n active: false,\n raw: identity.raw,\n lastProvisionedAt: Date.now(),\n },\n );\n }\n }\n await state.recordScimEvent(\n \"enterprise.scim.user.deleted\",\n true,\n \"user\",\n userId,\n );\n return new Response(null, { status: 204 });\n };\n\n const handleGroupsGet: ScimHandler = async (state) => {\n const groupsList = await auth.group.list(state.ctx, {\n where: { parentGroupId: state.enterprise.groupId },\n limit: 100,\n });\n const identities = await state.ctx.runQuery(\n config.component.public\n .enterpriseScimIdentityListByEnterprise,\n { enterpriseId: state.enterprise._id },\n );\n const identityByGroupId = new Map(\n identities\n .filter(\n (identity: any) => identity.mappedGroupId !== undefined,\n )\n .map((identity: any) => [identity.mappedGroupId, identity]),\n );\n const groups = groupsList.items.map((group: any) => ({\n group,\n identity: identityByGroupId.get(group._id),\n }));\n const listRequest = parseScimListRequest(state.url);\n const filtered = filterScimCollection<{\n group: any;\n identity?: any;\n }>(groups, listRequest.filter, {\n id: (item: { group: any }, value: string) =>\n item.group._id === value,\n externalId: (item: { identity?: any }, value: string) =>\n item.identity?.externalId === value,\n displayName: (item: { group: any }, value: string) =>\n item.group.name === value,\n });\n if (state.parsedPath.resourceId) {\n const resource = filtered.find(\n ({ group }) => group._id === state.parsedPath.resourceId,\n );\n if (!resource) {\n return scimError(404, \"notFound\", \"Group not found.\");\n }\n const members = (\n await auth.member.list(state.ctx, {\n where: {\n groupId: resource.group._id,\n status: \"active\",\n },\n limit: 100,\n })\n ).items.map((member: any) => ({ value: member.userId }));\n const location = `${state.url.origin}${state.url.pathname.replace(/\\/[^/]+$/, \"\")}/${resource.group._id}`;\n return scimJson(\n serializeScimGroup({\n id: resource.group._id,\n group: resource.group,\n externalId: resource.identity?.externalId,\n location,\n members,\n }),\n 200,\n { Location: location },\n );\n }\n const paged = paginateScimCollection(filtered, listRequest);\n return scimJson({\n schemas: [\n \"urn:ietf:params:scim:api:messages:2.0:ListResponse\",\n ],\n Resources: paged.map(({ group, identity }) =>\n serializeScimGroup({\n id: group._id,\n group,\n externalId: identity?.externalId,\n location: `${state.url.origin}${state.url.pathname}/${group._id}`,\n }),\n ),\n totalResults: filtered.length,\n startIndex: listRequest.startIndex,\n itemsPerPage: paged.length,\n });\n };\n\n const handleGroupsPost: ScimHandler = async (state) => {\n const body = await readScimJson(state.request);\n const { groupId } = await auth.group.create(state.ctx, {\n name: String(body.displayName ?? \"Group\"),\n parentGroupId: state.enterprise.groupId,\n type: \"organization\",\n });\n await state.ctx.runMutation(\n config.component.public.enterpriseScimIdentityUpsert,\n {\n enterpriseId: state.enterprise._id,\n groupId: state.enterprise.groupId,\n resourceType: \"group\",\n externalId: body.externalId ?? groupId,\n mappedGroupId: groupId,\n active: true,\n raw: body,\n lastProvisionedAt: Date.now(),\n },\n );\n for (const member of Array.isArray(body.members)\n ? body.members\n : []) {\n try {\n await auth.member.create(state.ctx, {\n groupId,\n userId: String(member.value),\n roleIds: state.policy.provisioning.jit.defaultRoleIds,\n status: \"active\",\n });\n } catch {}\n }\n await state.recordScimEvent(\n \"enterprise.scim.group.created\",\n true,\n \"group\",\n groupId,\n );\n const group = await auth.group.get(state.ctx, groupId);\n const location = `${state.url.origin}${state.url.pathname}/${groupId}`;\n return scimJson(\n serializeScimGroup({\n id: groupId,\n group: group ?? {},\n externalId: body.externalId,\n location,\n members: (\n await auth.member.list(state.ctx, {\n where: { groupId, status: \"active\" },\n limit: 100,\n })\n ).items.map((member: any) => ({ value: member.userId })),\n }),\n 201,\n { Location: location },\n );\n };\n\n const handleGroupsPatch: ScimHandler = async (state) => {\n const missing = requireScimResourceId(\n state.parsedPath.resourceId,\n \"Group\",\n );\n if (missing) return missing;\n const groupId = state.parsedPath.resourceId!;\n const body = await readScimJson(state.request);\n for (const operation of Array.isArray(body.Operations)\n ? body.Operations\n : []) {\n if (operation.path === \"displayName\") {\n await auth.group.update(state.ctx, groupId, {\n name: operation.value,\n });\n }\n if (operation.path === \"members\" && operation.op === \"add\") {\n for (const member of Array.isArray(operation.value)\n ? operation.value\n : []) {\n try {\n await auth.member.create(state.ctx, {\n groupId,\n userId: String(member.value),\n roleIds: state.policy.provisioning.jit.defaultRoleIds,\n status: \"active\",\n });\n } catch {}\n }\n }\n if (\n operation.path === \"members\" &&\n operation.op === \"replace\"\n ) {\n const currentMembers = (\n await auth.member.list(state.ctx, {\n where: { groupId, status: \"active\" },\n limit: 100,\n })\n ).items as Array<{ _id: string; userId: string }>;\n const currentUserIds = new Set<string>(\n currentMembers.map((member) => member.userId),\n );\n const nextUserIds = new Set<string>(\n (Array.isArray(operation.value)\n ? operation.value\n : []\n ).map((member: any) => String(member.value)),\n );\n for (const member of currentMembers) {\n if (!nextUserIds.has(member.userId)) {\n await auth.member.delete(state.ctx, member._id);\n }\n }\n for (const userId of nextUserIds.values()) {\n if (!currentUserIds.has(userId)) {\n try {\n await auth.member.create(state.ctx, {\n groupId,\n userId,\n roleIds:\n state.policy.provisioning.jit.defaultRoleIds,\n status: \"active\",\n });\n } catch {}\n }\n }\n }\n if (\n typeof operation.path === \"string\" &&\n operation.op === \"remove\" &&\n operation.path.startsWith(\"members[\")\n ) {\n const match = operation.path.match(\n /^members\\[value eq \"([^\"]+)\"\\]$/,\n );\n const userId = match?.[1];\n if (userId) {\n const membership = await auth.member.getByUserAndGroup(\n state.ctx,\n { groupId, userId },\n );\n if (membership) {\n await auth.member.delete(state.ctx, membership._id);\n }\n }\n }\n }\n await state.recordScimEvent(\n \"enterprise.scim.group.updated\",\n true,\n \"group\",\n groupId,\n );\n const group = await auth.group.get(state.ctx, groupId);\n const location = `${state.url.origin}${state.url.pathname}`;\n const members = (\n await auth.member.list(state.ctx, {\n where: { groupId, status: \"active\" },\n limit: 100,\n })\n ).items as Array<{ userId: string }>;\n return scimJson(\n serializeScimGroup({\n id: groupId,\n group: group ?? {},\n location,\n members: members.map((member) => ({\n value: member.userId,\n })),\n }),\n 200,\n { Location: location },\n );\n };\n\n const handleGroupsDelete: ScimHandler = async (state) => {\n const missing = requireScimResourceId(\n state.parsedPath.resourceId,\n \"Group\",\n );\n if (missing) return missing;\n const groupId = state.parsedPath.resourceId!;\n await auth.group.delete(state.ctx, groupId);\n const identity = await state.ctx.runQuery(\n config.component.public\n .enterpriseScimIdentityGetByMappedGroup,\n { mappedGroupId: groupId },\n );\n if (identity) {\n await state.ctx.runMutation(\n config.component.public.enterpriseScimIdentityDelete,\n { identityId: identity._id },\n );\n }\n await state.recordScimEvent(\n \"enterprise.scim.group.deleted\",\n true,\n \"group\",\n groupId,\n );\n return new Response(null, { status: 204 });\n };\n\n const scimHandlers: Record<\n string,\n Partial<Record<string, ScimHandler>>\n > = {\n ServiceProviderConfig: {\n GET: async () =>\n scimJson({\n schemas: [\n \"urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig\",\n ],\n patch: { supported: true },\n bulk: {\n supported: false,\n maxOperations: 0,\n maxPayloadSize: 0,\n },\n filter: { supported: true, maxResults: 100 },\n changePassword: { supported: false },\n sort: { supported: false },\n etag: { supported: false },\n authenticationSchemes: [\n {\n type: \"oauthbearertoken\",\n name: \"Bearer Token\",\n description:\n \"Use the SCIM token generated by Convex Auth enterprise.\",\n },\n ],\n }),\n },\n Schemas: {\n GET: async (state) =>\n handleStaticScimCollection(\n SCIM_SCHEMAS,\n state.parsedPath.resourceId,\n {\n by: \"id\",\n notFound: \"Schema not found.\",\n },\n ),\n },\n ResourceTypes: {\n GET: async (state) =>\n handleStaticScimCollection(\n SCIM_RESOURCE_TYPES,\n state.parsedPath.resourceId,\n { by: \"name\", notFound: \"Resource type not found.\" },\n ),\n },\n Users: {\n GET: handleUsersGet,\n POST: handleUsersPost,\n PATCH: handleUsersUpsert,\n PUT: handleUsersUpsert,\n DELETE: handleUsersDelete,\n },\n Groups: {\n GET: handleGroupsGet,\n POST: handleGroupsPost,\n PATCH: handleGroupsPatch,\n DELETE: handleGroupsDelete,\n },\n };\n\n const handler =\n scimHandlers[state.parsedPath.resource]?.[state.request.method];\n return handler\n ? await handler(state)\n : scimError(404, \"notFound\", \"SCIM resource not found.\");\n } catch (error) {\n if (\n error instanceof Error &&\n error.message === \"Unsupported SCIM filter.\"\n ) {\n return scimError(400, \"invalidFilter\", error.message);\n }\n if (isAuthError(error)) {\n const code = error.data.code as string;\n const status =\n code === \"MISSING_BEARER_TOKEN\" || code === \"INVALID_API_KEY\"\n ? 401\n : 400;\n return scimError(status, code, error.data.message);\n }\n throw error;\n }\n };\n\n addSSORoutes(http, {\n routeBase: ENTERPRISE_CONTROL_ROUTE_BASE,\n convertErrorsToResponse,\n handleSamlMetadata: async (ctx, _request, runtimeRoute) => {\n const { loaded } = await loadActiveEnterpriseSamlOrThrow(\n ctx,\n runtimeRoute.enterpriseId,\n );\n return new Response(\n createEnterpriseSamlMetadataXml({\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n source: loaded.source,\n config: loaded.config,\n }),\n {\n status: 200,\n headers: { \"Content-Type\": \"application/xml\" },\n },\n );\n },\n handleSamlSignIn: async (ctx, request, runtimeRoute) => {\n const url = new URL(request.url);\n const verifier = url.searchParams.get(\"code\");\n if (!verifier) {\n throw new AuthError(\"OAUTH_MISSING_VERIFIER\").toConvexError();\n }\n const { loaded, enterprise } =\n await loadActiveEnterpriseSamlOrThrow(\n ctx,\n runtimeRoute.enterpriseId,\n );\n const state = generateRandomString(24, INVITE_TOKEN_ALPHABET);\n const signInRequest = createEnterpriseSamlSignInRequest({\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n source: { kind: \"enterprise\", id: enterprise._id },\n config: loaded.config,\n state,\n signature: `saml ${enterprise._id} pending ${state}`,\n redirectTo: url.searchParams.get(\"redirectTo\") ?? undefined,\n });\n const signature = `saml ${enterprise._id} ${signInRequest.requestId} ${state}`;\n await callVerifierSignature(ctx, { verifier, signature });\n const redirectTo = url.searchParams.get(\"redirectTo\");\n const redirectCookies =\n redirectTo !== null\n ? [\n redirectToParamCookie(\n enterpriseSamlProviderId(enterprise._id),\n redirectTo,\n ),\n ]\n : [];\n const relayState = encodeEnterpriseSamlRelayState({\n source: { kind: \"enterprise\", id: enterprise._id },\n signature,\n requestId: signInRequest.requestId,\n state,\n redirectTo: url.searchParams.get(\"redirectTo\") ?? undefined,\n });\n if (\n signInRequest.binding === \"redirect\" &&\n signInRequest.redirectUrl\n ) {\n const redirectUrl = new URL(signInRequest.redirectUrl);\n redirectUrl.searchParams.set(\"RelayState\", relayState);\n const headers = new Headers({\n Location: redirectUrl.toString(),\n });\n for (const { name, value, options } of redirectCookies as any) {\n headers.append(\n \"Set-Cookie\",\n serializeCookie(name, value, options),\n );\n }\n return new Response(null, { status: 302, headers });\n }\n const response = createSamlPostBindingResponse({\n endpoint: signInRequest.post!.endpoint,\n parameter: \"SAMLRequest\",\n value: signInRequest.post!.value,\n relayState,\n });\n for (const { name, value, options } of redirectCookies as any) {\n response.headers.append(\n \"Set-Cookie\",\n serializeCookie(name, value, options),\n );\n }\n return response;\n },\n handleOidcSignIn: async (ctx, request, runtimeRoute) => {\n const url = new URL(request.url);\n const verifier = url.searchParams.get(\"code\");\n if (!verifier) {\n throw new AuthError(\"OAUTH_MISSING_VERIFIER\").toConvexError();\n }\n const { enterprise, oidc } = await loadEnterpriseOidcOrThrow(\n ctx,\n runtimeRoute.enterpriseId,\n );\n const { providerId, provider, oauthConfig } =\n await createEnterpriseOidcRuntime({\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n enterpriseId: enterprise._id,\n oidc,\n });\n const { redirect, cookies, signature } =\n await createOAuthAuthorizationURL(\n providerId,\n provider,\n oauthConfig,\n );\n await callVerifierSignature(ctx, { verifier, signature });\n const redirectTo = url.searchParams.get(\"redirectTo\");\n const headers_ = new Headers({ Location: redirect });\n for (const { name, value, options } of [\n ...cookies,\n ...(redirectTo !== null\n ? [redirectToParamCookie(providerId, redirectTo)]\n : []),\n ] as any) {\n headers_.append(\n \"Set-Cookie\",\n serializeCookie(name, value, options),\n );\n }\n return new Response(null, {\n status: 302,\n headers: headers_,\n });\n },\n handleOidcCallback: async (ctx, request, runtimeRoute) => {\n const url = new URL(request.url);\n const { enterprise, oidc } = await loadEnterpriseOidcOrThrow(\n ctx,\n runtimeRoute.enterpriseId,\n );\n const { providerId, provider, oauthConfig } =\n await createEnterpriseOidcRuntime({\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n enterpriseId: enterprise._id,\n oidc,\n });\n const cookies = getCookies(request);\n const maybeRedirectTo = useRedirectToParam(providerId, cookies);\n const destinationUrl = await redirectAbsoluteUrl(config, {\n redirectTo: maybeRedirectTo?.redirectTo,\n });\n const params = url.searchParams;\n const result = await Fx.run(\n handleOAuthCallback(\n providerId,\n provider,\n oauthConfig,\n Object.fromEntries(params.entries()),\n cookies,\n ),\n );\n const extraFields = oidc.extraFields as\n | Record<string, string>\n | undefined;\n let profile = result.profile as Record<string, unknown>;\n if (extraFields && typeof profile === \"object\" && profile) {\n const extend: Record<string, unknown> = {};\n for (const [claimName, fieldName] of Object.entries(\n extraFields,\n )) {\n if (claimName in profile) {\n extend[fieldName] = profile[claimName];\n }\n }\n if (Object.keys(extend).length > 0) {\n profile = { ...profile, extend };\n }\n }\n\n const verificationCode = await callUserOAuth(ctx, {\n provider: providerId,\n providerAccountId: result.providerAccountId,\n profile,\n signature: result.signature,\n accountExtend: {\n identity: {\n protocol: \"oidc\",\n enterpriseId: enterprise._id,\n subject: result.providerAccountId,\n issuer:\n typeof oidc.issuer === \"string\" ? oidc.issuer : undefined,\n discoveryUrl:\n typeof oidc.discoveryUrl === \"string\"\n ? oidc.discoveryUrl\n : undefined,\n },\n },\n });\n const headers = new Headers({\n Location: setURLSearchParam(\n destinationUrl,\n \"code\",\n verificationCode,\n ),\n });\n for (const { name, value, options } of result.cookies) {\n headers.append(\n \"Set-Cookie\",\n serializeCookie(name, value, options as any),\n );\n }\n if (maybeRedirectTo) {\n headers.append(\n \"Set-Cookie\",\n serializeCookie(\n maybeRedirectTo.updatedCookie.name,\n maybeRedirectTo.updatedCookie.value,\n maybeRedirectTo.updatedCookie.options as any,\n ),\n );\n }\n return new Response(null, { status: 302, headers });\n },\n handleSamlAcs,\n handleSamlSlo,\n handleScimRequest,\n scimError,\n });\n } // end if (hasSSO)\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.at(-1)!;\n if (providerId === null) {\n throw new AuthError(\"OAUTH_MISSING_PROVIDER\").toConvexError();\n }\n const verifier = url.searchParams.get(\"code\");\n if (verifier === null) {\n throw new AuthError(\"OAUTH_MISSING_VERIFIER\").toConvexError();\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 providerId = new URL(request.url).pathname\n .split(\"/\")\n .at(-1);\n if (!providerId) {\n throw new AuthError(\"OAUTH_MISSING_PROVIDER\").toConvexError();\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 !==\n 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 * 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\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 access: auth.access,\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,22 +1,7 @@
1
1
  import { AuthErrorCode } from "./errors.js";
2
- import { Fx as Fx$1 } from "@robelest/fx";
3
2
  import { ConvexError } from "convex/values";
4
3
 
5
4
  //#region src/server/fx.d.ts
6
- type MatchHandlers<T, K extends keyof T & string> = { [V in Extract<T[K], string>]: (value: Extract<T, Record<K, V>>) => unknown };
7
- type HandlerSuccess<T> = T extends Fx$1<infer A, any> ? A : T;
8
- type HandlerError<T> = T extends Fx$1<any, infer E> ? E : never;
9
- type MatchSuccess<Handlers> = { [V in keyof Handlers]: Handlers[V] extends ((...args: any[]) => infer R) ? HandlerSuccess<R> : never }[keyof Handlers];
10
- type MatchError<Handlers> = { [V in keyof Handlers]: Handlers[V] extends ((...args: any[]) => infer R) ? HandlerError<R> : never }[keyof Handlers];
11
- type MatchBuilder<T> = {
12
- on<K extends keyof T & string, Handlers extends MatchHandlers<T, K>>(key: K, handlers: Handlers): Fx$1<MatchSuccess<Handlers>, MatchError<Handlers>>;
13
- on(key: string, handlers: Record<string, (value: any) => unknown>): Fx$1<any, any>;
14
- };
15
- declare function match<T>(value: T): MatchBuilder<T>;
16
- declare function match<T extends Record<string, unknown>, K extends keyof T & string, Handlers extends MatchHandlers<T, K>>(value: T, tag: Extract<T[K], string>, handlers: Handlers): Fx$1<MatchSuccess<Handlers>, MatchError<Handlers>>;
17
- declare const Fx: Omit<typeof Fx$1, "match"> & {
18
- match: typeof match;
19
- };
20
5
  /**
21
6
  * Typed error for the Fx error channel.
22
7
  *
@@ -47,5 +32,5 @@ declare class AuthError extends Error {
47
32
  }>;
48
33
  }
49
34
  //#endregion
50
- export { AuthError, Fx };
35
+ export { AuthError };
51
36
  //# sourceMappingURL=fx.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fx.d.ts","names":[],"sources":["../../src/server/fx.ts"],"mappings":";;;;;KAmBK,aAAA,oBAAiC,CAAA,qBAC9B,OAAA,CAAQ,CAAA,CAAE,CAAA,cAAe,KAAA,EAAO,OAAA,CAAQ,CAAA,EAAG,MAAA,CAAO,CAAA,EAAG,CAAA;AAAA,KAGxD,cAAA,MAAoB,CAAA,SAAU,IAAA,iBAAuB,CAAA,GAAI,CAAA;AAAA,KAEzD,YAAA,MAAkB,CAAA,SAAU,IAAA,iBAAuB,CAAA;AAAA,KAEnD,YAAA,2BACS,QAAA,GAAW,QAAA,CAAS,CAAA,eAAe,IAAA,uBAC3C,cAAA,CAAe,CAAA,kBAEb,QAAA;AAAA,KAEH,UAAA,2BACS,QAAA,GAAW,QAAA,CAAS,CAAA,eAAe,IAAA,uBAC3C,YAAA,CAAa,CAAA,kBAEX,QAAA;AAAA,KAEH,YAAA;EACH,EAAA,iBAAmB,CAAA,4BAA6B,aAAA,CAAc,CAAA,EAAG,CAAA,GAC/D,GAAA,EAAK,CAAA,EACL,QAAA,EAAU,QAAA,GACT,IAAA,CAAO,YAAA,CAAa,QAAA,GAAW,UAAA,CAAW,QAAA;EAC7C,EAAA,CACE,GAAA,UACA,QAAA,EAAU,MAAA,UAAgB,KAAA,qBACzB,IAAA;AAAA;AAAA,iBAuBI,KAAA,GAAA,CAAS,KAAA,EAAO,CAAA,GAAI,YAAA,CAAa,CAAA;AAAA,iBACjC,KAAA,WACG,MAAA,mCACM,CAAA,4BACC,aAAA,CAAc,CAAA,EAAG,CAAA,EAAA,CAElC,KAAA,EAAO,CAAA,EACP,GAAA,EAAK,OAAA,CAAQ,CAAA,CAAE,CAAA,YACf,QAAA,EAAU,QAAA,GACT,IAAA,CAAO,YAAA,CAAa,QAAA,GAAW,UAAA,CAAW,QAAA;AAAA,cAuBhC,EAAA,EAGR,IAAA,QAAY,IAAA;EACf,KAAA,SAAc,KAAA;AAAA;;AAtFgD;;;;;;;;;;;;;;;;AAGD;cA4GlD,SAAA,SAAkB,KAAA;EAAA,SAIlB,IAAA,EAAM,aAAA;EAAA,SAEN,OAAA,GAAU,MAAA;EAAA,SALZ,IAAA;cAGE,IAAA,EAAM,aAAA,EACf,OAAA,WACS,OAAA,GAAU,MAAA;EAhHU;EAsH/B,aAAA,CAAA,GAAiB,WAAA;IAAc,IAAA,EAAM,aAAA;IAAe,OAAA;EAAA;AAAA"}
1
+ {"version":3,"file":"fx.d.ts","names":[],"sources":["../../src/server/fx.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;cAoIa,SAAA,SAAkB,KAAA;EAAA,SAIlB,IAAA,EAAM,aAAA;EAAA,SAEN,OAAA,GAAU,MAAA;EAAA,SALZ,IAAA;cAGE,IAAA,EAAM,aAAA,EACf,OAAA,WACS,OAAA,GAAU,MAAA;EAMsC;EAA3D,aAAA,CAAA,GAAiB,WAAA;IAAc,IAAA,EAAM,aAAA;IAAe,OAAA;EAAA;AAAA"}
package/dist/server/fx.js CHANGED
@@ -21,6 +21,7 @@ function match(value, tag, handlers) {
21
21
  if (tag === void 0 || handlers === void 0) return { on: (key, onHandlers) => Fx$1.match(value, String(value[key]), toFxHandlers(onHandlers)) };
22
22
  return Fx$1.match(value, tag, toFxHandlers(handlers));
23
23
  }
24
+ /** @internal */
24
25
  const Fx = {
25
26
  ...Fx$1,
26
27
  match
@@ -1 +1 @@
1
- {"version":3,"file":"fx.js","names":["BaseFx"],"sources":["../../src/server/fx.ts"],"sourcesContent":["/**\n * Fx utilities for Convex Auth.\n *\n * Provides the {@link AuthError} class for use with `Fx.fail()` and\n * small composable helpers that replace repeated imperative patterns\n * (null-check chains, throw-guards).\n *\n * @module\n */\n\nimport { Fx as BaseFx } from \"@robelest/fx\";\nimport type { Fx as FxType } from \"@robelest/fx\";\nimport { ConvexError } from \"convex/values\";\n\nimport { AUTH_ERRORS } from \"./errors\";\nimport type { AuthErrorCode } from \"./errors\";\n\ntype AnyFx = FxType<any, any>;\n\ntype MatchHandlers<T, K extends keyof T & string> = {\n [V in Extract<T[K], string>]: (value: Extract<T, Record<K, V>>) => unknown;\n};\n\ntype HandlerSuccess<T> = T extends FxType<infer A, any> ? A : T;\n\ntype HandlerError<T> = T extends FxType<any, infer E> ? E : never;\n\ntype MatchSuccess<Handlers> = {\n [V in keyof Handlers]: Handlers[V] extends (...args: any[]) => infer R\n ? HandlerSuccess<R>\n : never;\n}[keyof Handlers];\n\ntype MatchError<Handlers> = {\n [V in keyof Handlers]: Handlers[V] extends (...args: any[]) => infer R\n ? HandlerError<R>\n : never;\n}[keyof Handlers];\n\ntype MatchBuilder<T> = {\n on<K extends keyof T & string, Handlers extends MatchHandlers<T, K>>(\n key: K,\n handlers: Handlers,\n ): FxType<MatchSuccess<Handlers>, MatchError<Handlers>>;\n on(\n key: string,\n handlers: Record<string, (value: any) => unknown>,\n ): FxType<any, any>;\n};\n\nconst toFx = (value: unknown): AnyFx => {\n if (\n value !== null &&\n typeof value === \"object\" &&\n \"_run\" in value &&\n typeof (value as { _run?: unknown })._run === \"function\"\n ) {\n return value as AnyFx;\n }\n return BaseFx.succeed(value);\n};\n\nconst toFxHandlers = (handlers: Record<string, (value: any) => unknown>) =>\n Object.fromEntries(\n Object.entries(handlers).map(([name, handler]) => [\n name,\n (value: any) => toFx(handler(value)),\n ]),\n ) as Record<string, (value: any) => AnyFx>;\n\nfunction match<T>(value: T): MatchBuilder<T>;\nfunction match<\n T extends Record<string, unknown>,\n K extends keyof T & string,\n Handlers extends MatchHandlers<T, K>,\n>(\n value: T,\n tag: Extract<T[K], string>,\n handlers: Handlers,\n): FxType<MatchSuccess<Handlers>, MatchError<Handlers>>;\nfunction match<T>(\n value: T,\n tag?: string,\n handlers?: Record<string, (value: any) => unknown>,\n) {\n if (tag === undefined || handlers === undefined) {\n return {\n on: (key: string, onHandlers: Record<string, (value: any) => unknown>) =>\n BaseFx.match(\n value as Record<string, string>,\n String((value as Record<string, unknown>)[key]),\n toFxHandlers(onHandlers),\n ),\n } as MatchBuilder<T>;\n }\n return BaseFx.match(\n value as Record<string, string>,\n tag,\n toFxHandlers(handlers),\n );\n}\n\nexport const Fx = {\n ...BaseFx,\n match,\n} as Omit<typeof BaseFx, \"match\"> & {\n match: typeof match;\n};\n\n// ============================================================================\n// AuthError — typed error for the Fx error channel\n// ============================================================================\n\n/**\n * Typed error for the Fx error channel.\n *\n * Use with `Fx.fail(new AuthError(\"CODE\"))` in pipelines.\n * At Convex boundaries, {@link toConvexError} converts these to `ConvexError`.\n *\n * @example\n * ```ts\n * // In an Fx pipeline\n * Fx.fail(new AuthError(\"NOT_SIGNED_IN\"));\n *\n * // With custom message\n * Fx.fail(new AuthError(\"INTERNAL_ERROR\", \"Something specific went wrong\"));\n *\n * // With extra context\n * Fx.fail(new AuthError(\"MISSING_ENV_VAR\", undefined, { variable: \"SECRET\" }));\n * ```\n */\nexport class AuthError extends Error {\n readonly _tag = \"AuthError\" as const;\n\n constructor(\n readonly code: AuthErrorCode,\n message?: string,\n readonly context?: Record<string, unknown>,\n ) {\n super(message ?? AUTH_ERRORS[code]);\n }\n\n /** Convert to the `ConvexError` shape the Convex runtime expects. */\n toConvexError(): ConvexError<{ code: AuthErrorCode; message: string }> {\n return new ConvexError({\n code: this.code,\n message: this.message,\n ...this.context,\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAkDA,MAAM,QAAQ,UAA0B;AACtC,KACE,UAAU,QACV,OAAO,UAAU,YACjB,UAAU,SACV,OAAQ,MAA6B,SAAS,WAE9C,QAAO;AAET,QAAOA,KAAO,QAAQ,MAAM;;AAG9B,MAAM,gBAAgB,aACpB,OAAO,YACL,OAAO,QAAQ,SAAS,CAAC,KAAK,CAAC,MAAM,aAAa,CAChD,OACC,UAAe,KAAK,QAAQ,MAAM,CAAC,CACrC,CAAC,CACH;AAYH,SAAS,MACP,OACA,KACA,UACA;AACA,KAAI,QAAQ,UAAa,aAAa,OACpC,QAAO,EACL,KAAK,KAAa,eAChBA,KAAO,MACL,OACA,OAAQ,MAAkC,KAAK,EAC/C,aAAa,WAAW,CACzB,EACJ;AAEH,QAAOA,KAAO,MACZ,OACA,KACA,aAAa,SAAS,CACvB;;AAGH,MAAa,KAAK;CAChB,GAAGA;CACH;CACD;;;;;;;;;;;;;;;;;;;AA0BD,IAAa,YAAb,cAA+B,MAAM;CACnC,AAAS,OAAO;CAEhB,YACE,AAAS,MACT,SACA,AAAS,SACT;AACA,QAAM,WAAW,YAAY,MAAM;EAJ1B;EAEA;;;CAMX,gBAAuE;AACrE,SAAO,IAAI,YAAY;GACrB,MAAM,KAAK;GACX,SAAS,KAAK;GACd,GAAG,KAAK;GACT,CAAC"}
1
+ {"version":3,"file":"fx.js","names":["BaseFx"],"sources":["../../src/server/fx.ts"],"sourcesContent":["/**\n * Fx utilities for Convex Auth.\n *\n * Provides the {@link AuthError} class for use with `Fx.fail()` and\n * small composable helpers that replace repeated imperative patterns\n * (null-check chains, throw-guards).\n *\n * @module\n */\n\nimport { Fx as BaseFx } from \"@robelest/fx\";\nimport type { Fx as FxType } from \"@robelest/fx\";\nimport { ConvexError } from \"convex/values\";\n\nimport { AUTH_ERRORS } from \"./errors\";\nimport type { AuthErrorCode } from \"./errors\";\n\ntype AnyFx = FxType<any, any>;\n\ntype MatchHandlers<T, K extends keyof T & string> = {\n [V in Extract<T[K], string>]: (value: Extract<T, Record<K, V>>) => unknown;\n};\n\ntype HandlerSuccess<T> = T extends FxType<infer A, any> ? A : T;\n\ntype HandlerError<T> = T extends FxType<any, infer E> ? E : never;\n\ntype MatchSuccess<Handlers> = {\n [V in keyof Handlers]: Handlers[V] extends (...args: any[]) => infer R\n ? HandlerSuccess<R>\n : never;\n}[keyof Handlers];\n\ntype MatchError<Handlers> = {\n [V in keyof Handlers]: Handlers[V] extends (...args: any[]) => infer R\n ? HandlerError<R>\n : never;\n}[keyof Handlers];\n\ntype MatchBuilder<T> = {\n on<K extends keyof T & string, Handlers extends MatchHandlers<T, K>>(\n key: K,\n handlers: Handlers,\n ): FxType<MatchSuccess<Handlers>, MatchError<Handlers>>;\n on(\n key: string,\n handlers: Record<string, (value: any) => unknown>,\n ): FxType<any, any>;\n};\n\nconst toFx = (value: unknown): AnyFx => {\n if (\n value !== null &&\n typeof value === \"object\" &&\n \"_run\" in value &&\n typeof (value as { _run?: unknown })._run === \"function\"\n ) {\n return value as AnyFx;\n }\n return BaseFx.succeed(value);\n};\n\nconst toFxHandlers = (handlers: Record<string, (value: any) => unknown>) =>\n Object.fromEntries(\n Object.entries(handlers).map(([name, handler]) => [\n name,\n (value: any) => toFx(handler(value)),\n ]),\n ) as Record<string, (value: any) => AnyFx>;\n\nfunction match<T>(value: T): MatchBuilder<T>;\nfunction match<\n T extends Record<string, unknown>,\n K extends keyof T & string,\n Handlers extends MatchHandlers<T, K>,\n>(\n value: T,\n tag: Extract<T[K], string>,\n handlers: Handlers,\n): FxType<MatchSuccess<Handlers>, MatchError<Handlers>>;\nfunction match<T>(\n value: T,\n tag?: string,\n handlers?: Record<string, (value: any) => unknown>,\n) {\n if (tag === undefined || handlers === undefined) {\n return {\n on: (key: string, onHandlers: Record<string, (value: any) => unknown>) =>\n BaseFx.match(\n value as Record<string, string>,\n String((value as Record<string, unknown>)[key]),\n toFxHandlers(onHandlers),\n ),\n } as MatchBuilder<T>;\n }\n return BaseFx.match(\n value as Record<string, string>,\n tag,\n toFxHandlers(handlers),\n );\n}\n\n/** @internal */\nexport const Fx = {\n ...BaseFx,\n match,\n} as Omit<typeof BaseFx, \"match\"> & {\n match: typeof match;\n};\n\n// ============================================================================\n// AuthError — typed error for the Fx error channel\n// ============================================================================\n\n/**\n * Typed error for the Fx error channel.\n *\n * Use with `Fx.fail(new AuthError(\"CODE\"))` in pipelines.\n * At Convex boundaries, {@link toConvexError} converts these to `ConvexError`.\n *\n * @example\n * ```ts\n * // In an Fx pipeline\n * Fx.fail(new AuthError(\"NOT_SIGNED_IN\"));\n *\n * // With custom message\n * Fx.fail(new AuthError(\"INTERNAL_ERROR\", \"Something specific went wrong\"));\n *\n * // With extra context\n * Fx.fail(new AuthError(\"MISSING_ENV_VAR\", undefined, { variable: \"SECRET\" }));\n * ```\n */\nexport class AuthError extends Error {\n readonly _tag = \"AuthError\" as const;\n\n constructor(\n readonly code: AuthErrorCode,\n message?: string,\n readonly context?: Record<string, unknown>,\n ) {\n super(message ?? AUTH_ERRORS[code]);\n }\n\n /** Convert to the `ConvexError` shape the Convex runtime expects. */\n toConvexError(): ConvexError<{ code: AuthErrorCode; message: string }> {\n return new ConvexError({\n code: this.code,\n message: this.message,\n ...this.context,\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAkDA,MAAM,QAAQ,UAA0B;AACtC,KACE,UAAU,QACV,OAAO,UAAU,YACjB,UAAU,SACV,OAAQ,MAA6B,SAAS,WAE9C,QAAO;AAET,QAAOA,KAAO,QAAQ,MAAM;;AAG9B,MAAM,gBAAgB,aACpB,OAAO,YACL,OAAO,QAAQ,SAAS,CAAC,KAAK,CAAC,MAAM,aAAa,CAChD,OACC,UAAe,KAAK,QAAQ,MAAM,CAAC,CACrC,CAAC,CACH;AAYH,SAAS,MACP,OACA,KACA,UACA;AACA,KAAI,QAAQ,UAAa,aAAa,OACpC,QAAO,EACL,KAAK,KAAa,eAChBA,KAAO,MACL,OACA,OAAQ,MAAkC,KAAK,EAC/C,aAAa,WAAW,CACzB,EACJ;AAEH,QAAOA,KAAO,MACZ,OACA,KACA,aAAa,SAAS,CACvB;;;AAIH,MAAa,KAAK;CAChB,GAAGA;CACH;CACD;;;;;;;;;;;;;;;;;;;AA0BD,IAAa,YAAb,cAA+B,MAAM;CACnC,AAAS,OAAO;CAEhB,YACE,AAAS,MACT,SACA,AAAS,SACT;AACA,QAAM,WAAW,YAAY,MAAM;EAJ1B;EAEA;;;CAMX,gBAAuE;AACrE,SAAO,IAAI,YAAY;GACrB,MAAM,KAAK;GACX,SAAS,KAAK;GACd,GAAG,KAAK;GACT,CAAC"}
@@ -0,0 +1,59 @@
1
+ import { CorsConfig, HttpKeyContext } from "./types.js";
2
+ import * as convex_server65 from "convex/server";
3
+ import { GenericActionCtx, GenericDataModel, HttpRouter } from "convex/server";
4
+
5
+ //#region src/server/http.d.ts
6
+ declare function createHttpAction(auth: {
7
+ key: {
8
+ verify: (ctx: GenericActionCtx<any>, rawKey: string) => Promise<any>;
9
+ };
10
+ }): (handler: (ctx: GenericActionCtx<GenericDataModel> & HttpKeyContext, request: Request) => Promise<Response | Record<string, unknown>>, options?: {
11
+ scope?: {
12
+ resource: string;
13
+ action: string;
14
+ };
15
+ cors?: CorsConfig;
16
+ }) => convex_server65.PublicHttpAction;
17
+ declare function createHttpRoute(wrapAction: ReturnType<typeof createHttpAction>): (http: {
18
+ route: (config: any) => void;
19
+ }, routeConfig: {
20
+ path: string;
21
+ method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
22
+ handler: (ctx: GenericActionCtx<GenericDataModel> & HttpKeyContext, request: Request) => Promise<Response | Record<string, unknown>>;
23
+ scope?: {
24
+ resource: string;
25
+ action: string;
26
+ };
27
+ cors?: CorsConfig;
28
+ }) => void;
29
+ declare function convertErrorsToResponse(errorStatusCode: number, action: (ctx: GenericActionCtx<any>, request: Request) => Promise<Response>): (ctx: GenericActionCtx<any>, request: Request) => Promise<Response>;
30
+ declare function getCookies(request: Request): Record<string, string | undefined>;
31
+ type SSORuntimeRoute = {
32
+ pathname?: string;
33
+ enterpriseId: string;
34
+ protocol: "oidc" | "saml" | "scim";
35
+ rest: string[];
36
+ };
37
+ declare function addOpenIdRoutes(http: HttpRouter, deps: {
38
+ getIssuer: () => string;
39
+ getJwks: () => string;
40
+ }): void;
41
+ declare function addAuthRoutes(http: HttpRouter, deps: {
42
+ handleSignIn: (ctx: GenericActionCtx<any>, request: Request) => Promise<Response>;
43
+ handleCallback: (ctx: GenericActionCtx<any>, request: Request) => Promise<Response>;
44
+ }): void;
45
+ declare function addSSORoutes(http: HttpRouter, deps: {
46
+ routeBase: string;
47
+ convertErrorsToResponse: typeof convertErrorsToResponse;
48
+ handleSamlMetadata: (ctx: GenericActionCtx<any>, request: Request, route: SSORuntimeRoute) => Promise<Response>;
49
+ handleSamlSignIn: (ctx: GenericActionCtx<any>, request: Request, route: SSORuntimeRoute) => Promise<Response>;
50
+ handleOidcSignIn: (ctx: GenericActionCtx<any>, request: Request, route: SSORuntimeRoute) => Promise<Response>;
51
+ handleOidcCallback: (ctx: GenericActionCtx<any>, request: Request, route: SSORuntimeRoute) => Promise<Response>;
52
+ handleSamlAcs: (ctx: GenericActionCtx<any>, request: Request, route: SSORuntimeRoute) => Promise<Response>;
53
+ handleSamlSlo: (ctx: GenericActionCtx<any>, request: Request, route: SSORuntimeRoute) => Promise<Response>;
54
+ handleScimRequest: (ctx: GenericActionCtx<any>, request: Request) => Promise<Response>;
55
+ scimError: (status: number, scimType: string, detail: string) => Response;
56
+ }): void;
57
+ //#endregion
58
+ export { SSORuntimeRoute, addAuthRoutes, addOpenIdRoutes, addSSORoutes, convertErrorsToResponse, createHttpAction, createHttpRoute, getCookies };
59
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","names":[],"sources":["../../src/server/http.ts"],"mappings":";;;;;iBAcgB,gBAAA,CAAiB,IAAA;EAC/B,GAAA;IAAO,MAAA,GAAS,GAAA,EAAK,gBAAA,OAAuB,MAAA,aAAmB,OAAA;EAAA;AAAA,KAG7D,OAAA,GACE,GAAA,EAAK,gBAAA,CAAiB,gBAAA,IAAoB,cAAA,EAC1C,OAAA,EAAS,OAAA,KACN,OAAA,CAAQ,QAAA,GAAW,MAAA,oBACxB,OAAA;EACE,KAAA;IAAU,QAAA;IAAkB,MAAA;EAAA;EAC5B,IAAA,GAAO,UAAA;AAAA,MAAU,eAAA,CAClB,gBAAA;AAAA,iBA2IW,eAAA,CACd,UAAA,EAAY,UAAA,QAAkB,gBAAA,KAG5B,IAAA;EAAQ,KAAA,GAAQ,MAAA;AAAA,GAChB,WAAA;EACE,IAAA;EACA,MAAA;EACA,OAAA,GACE,GAAA,EAAK,gBAAA,CAAiB,gBAAA,IAAoB,cAAA,EAC1C,OAAA,EAAS,OAAA,KACN,OAAA,CAAQ,QAAA,GAAW,MAAA;EACxB,KAAA;IAAU,QAAA;IAAkB,MAAA;EAAA;EAC5B,IAAA,GAAO,UAAA;AAAA;AAAA,iBA+BG,uBAAA,CACd,eAAA,UACA,MAAA,GAAS,GAAA,EAAK,gBAAA,OAAuB,OAAA,EAAS,OAAA,KAAY,OAAA,CAAQ,QAAA,KAEpD,GAAA,EAAK,gBAAA,OAAuB,OAAA,EAAS,OAAA,KAAO,OAAA,CAAA,QAAA;AAAA,iBA2C5C,UAAA,CACd,OAAA,EAAS,OAAA,GACR,MAAA;AAAA,KAIS,eAAA;EACV,QAAA;EACA,YAAA;EACA,QAAA;EACA,IAAA;AAAA;AAAA,iBA2Bc,eAAA,CACd,IAAA,EAAM,UAAA,EACN,IAAA;EACE,SAAA;EACA,OAAA;AAAA;AAAA,iBA0CY,aAAA,CACd,IAAA,EAAM,UAAA,EACN,IAAA;EACE,YAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,KACN,OAAA,CAAQ,QAAA;EACb,cAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,KACN,OAAA,CAAQ,QAAA;AAAA;AAAA,iBAwBD,YAAA,CACd,IAAA,EAAM,UAAA,EACN,IAAA;EACE,SAAA;EACA,uBAAA,SAAgC,uBAAA;EAChC,kBAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,EACT,KAAA,EAAO,eAAA,KACJ,OAAA,CAAQ,QAAA;EACb,gBAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,EACT,KAAA,EAAO,eAAA,KACJ,OAAA,CAAQ,QAAA;EACb,gBAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,EACT,KAAA,EAAO,eAAA,KACJ,OAAA,CAAQ,QAAA;EACb,kBAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,EACT,KAAA,EAAO,eAAA,KACJ,OAAA,CAAQ,QAAA;EACb,aAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,EACT,KAAA,EAAO,eAAA,KACJ,OAAA,CAAQ,QAAA;EACb,aAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,EACT,KAAA,EAAO,eAAA,KACJ,OAAA,CAAQ,QAAA;EACb,iBAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,KACN,OAAA,CAAQ,QAAA;EACb,SAAA,GAAY,MAAA,UAAgB,QAAA,UAAkB,MAAA,aAAmB,QAAA;AAAA"}