@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
@@ -8,12 +8,16 @@ import type { UserIdentity } from "convex/server";
8
8
  import type { GenericId } from "convex/values";
9
9
 
10
10
  import type { AuthApiRefs } from "../client/index";
11
+ import { Auth as AuthFactory } from "./factory";
11
12
  import { Fx } from "./fx";
12
13
  import { AuthError } from "./fx";
13
- import { Auth as AuthFactory } from "./implementation";
14
14
  import type { Doc } from "./types";
15
15
  import type {
16
+ AuthAuthorizationConfig,
17
+ AuthGrant,
16
18
  AuthProviderConfig,
19
+ AuthRoleDefinition,
20
+ AuthRoleId,
17
21
  ConvexAuthConfig,
18
22
  HasDeviceProvider,
19
23
  HasPasskeyProvider,
@@ -31,8 +35,105 @@ import type {
31
35
  */
32
36
  export type AuthConfig = Omit<ConvexAuthConfig, "component">;
33
37
 
38
+ type MemberApiWithAuthorization<
39
+ TAuthorization extends AuthAuthorizationConfig | undefined,
40
+ > = Omit<
41
+ ReturnType<typeof AuthFactory>["auth"]["member"],
42
+ "create" | "list" | "update" | "inherit" | "require"
43
+ > & {
44
+ create: (
45
+ ctx: Parameters<
46
+ ReturnType<typeof AuthFactory>["auth"]["member"]["create"]
47
+ >[0],
48
+ data: {
49
+ groupId: string;
50
+ userId: string;
51
+ roleIds?: AuthRoleId<TAuthorization>[];
52
+ status?: string;
53
+ extend?: Record<string, unknown>;
54
+ },
55
+ ) => Promise<{ ok: true; memberId: string }>;
56
+ list: (
57
+ ctx: Parameters<
58
+ ReturnType<typeof AuthFactory>["auth"]["member"]["list"]
59
+ >[0],
60
+ opts?: {
61
+ where?: {
62
+ groupId?: string;
63
+ userId?: string;
64
+ roleId?: AuthRoleId<TAuthorization>;
65
+ status?: string;
66
+ };
67
+ limit?: number;
68
+ cursor?: string | null;
69
+ orderBy?: "_creationTime" | "status";
70
+ order?: "asc" | "desc";
71
+ },
72
+ ) => ReturnType<ReturnType<typeof AuthFactory>["auth"]["member"]["list"]>;
73
+ update: (
74
+ ctx: Parameters<
75
+ ReturnType<typeof AuthFactory>["auth"]["member"]["update"]
76
+ >[0],
77
+ memberId: string,
78
+ data: Record<string, unknown> & { roleIds?: AuthRoleId<TAuthorization>[] },
79
+ ) => Promise<{ ok: true; memberId: string }>;
80
+ inherit: (
81
+ ctx: Parameters<
82
+ ReturnType<typeof AuthFactory>["auth"]["member"]["inherit"]
83
+ >[0],
84
+ opts: {
85
+ userId: string;
86
+ groupId: string;
87
+ roleIds?: AuthRoleId<TAuthorization>[];
88
+ grants?: AuthGrant<TAuthorization>[];
89
+ maxDepth?: number;
90
+ },
91
+ ) => ReturnType<ReturnType<typeof AuthFactory>["auth"]["member"]["inherit"]>;
92
+ require: (
93
+ ctx: Parameters<
94
+ ReturnType<typeof AuthFactory>["auth"]["member"]["require"]
95
+ >[0],
96
+ opts: {
97
+ userId: string;
98
+ groupId: string;
99
+ roleIds?: AuthRoleId<TAuthorization>[];
100
+ grants?: AuthGrant<TAuthorization>[];
101
+ maxDepth?: number;
102
+ },
103
+ ) => ReturnType<ReturnType<typeof AuthFactory>["auth"]["member"]["require"]>;
104
+ };
105
+
106
+ type AccessApiWithAuthorization<
107
+ TAuthorization extends AuthAuthorizationConfig | undefined,
108
+ > = {
109
+ check: (
110
+ ctx: Parameters<
111
+ ReturnType<typeof AuthFactory>["auth"]["access"]["check"]
112
+ >[0],
113
+ opts: {
114
+ userId: string;
115
+ groupId: string;
116
+ grants: AuthGrant<TAuthorization>[];
117
+ maxDepth?: number;
118
+ },
119
+ ) => ReturnType<ReturnType<typeof AuthFactory>["auth"]["access"]["check"]>;
120
+ require: (
121
+ ctx: Parameters<
122
+ ReturnType<typeof AuthFactory>["auth"]["access"]["require"]
123
+ >[0],
124
+ opts: {
125
+ userId: string;
126
+ groupId: string;
127
+ grants: AuthGrant<TAuthorization>[];
128
+ maxDepth?: number;
129
+ },
130
+ ) => ReturnType<ReturnType<typeof AuthFactory>["auth"]["access"]["require"]>;
131
+ };
132
+
34
133
  /** The base auth API surface, without conditional namespaces. */
35
- export type AuthApiBase = {
134
+ export type AuthApiBase<
135
+ TAuthorization extends AuthAuthorizationConfig | undefined = undefined,
136
+ > = {
36
137
  signIn: ReturnType<typeof AuthFactory>["signIn"];
37
138
  signOut: ReturnType<typeof AuthFactory>["signOut"];
38
139
  store: ReturnType<typeof AuthFactory>["store"];
@@ -41,24 +142,115 @@ export type AuthApiBase = {
41
142
  provider: ReturnType<typeof AuthFactory>["auth"]["provider"];
42
143
  account: ReturnType<typeof AuthFactory>["auth"]["account"];
43
144
  group: ReturnType<typeof AuthFactory>["auth"]["group"];
44
- member: ReturnType<typeof AuthFactory>["auth"]["member"];
145
+ member: MemberApiWithAuthorization<TAuthorization>;
146
+ access: AccessApiWithAuthorization<TAuthorization>;
45
147
  invite: ReturnType<typeof AuthFactory>["auth"]["invite"];
46
148
  key: ReturnType<typeof AuthFactory>["auth"]["key"];
47
149
  http: ReturnType<typeof AuthFactory>["auth"]["http"];
48
150
  };
49
151
 
50
- /** Auth API with SSO namespace — present only when `new SSO()` is in providers. */
51
- export type AuthApi = AuthApiBase & {
52
- sso: ReturnType<typeof AuthFactory>["auth"]["sso"];
152
+ type InternalSsoApi = ReturnType<typeof AuthFactory>["auth"]["sso"];
153
+
154
+ type PublicSsoAdminApi = {
155
+ connection: InternalSsoApi["connection"] & {
156
+ domain: {
157
+ list: InternalSsoApi["domain"]["list"];
158
+ validate: InternalSsoApi["domain"]["validate"];
159
+ set: (
160
+ ctx: Parameters<InternalSsoApi["connection"]["create"]>[0],
161
+ enterpriseId: string,
162
+ domains: Array<{
163
+ domain: string;
164
+ isPrimary?: boolean;
165
+ }>,
166
+ ) => Promise<{
167
+ ok: true;
168
+ enterpriseId: string;
169
+ domains: Array<{
170
+ domainId: string;
171
+ domain: string;
172
+ isPrimary: boolean;
173
+ verified: boolean;
174
+ verifiedAt: number | null;
175
+ }>;
176
+ }>;
177
+ verification: {
178
+ request: (
179
+ ctx: Parameters<InternalSsoApi["connection"]["create"]>[0],
180
+ args: { enterpriseId: string; domain: string },
181
+ ) => Promise<{
182
+ ok: true;
183
+ enterpriseId: string;
184
+ domain: string;
185
+ requestedAt: number;
186
+ expiresAt: number;
187
+ challenge: {
188
+ recordType: "TXT";
189
+ recordName: string;
190
+ recordValue: string;
191
+ };
192
+ }>;
193
+ confirm: (
194
+ ctx: Parameters<InternalSsoApi["connection"]["create"]>[0],
195
+ args: { enterpriseId: string; domain: string },
196
+ ) => Promise<{
197
+ ok: boolean;
198
+ enterpriseId: string;
199
+ domain: string;
200
+ verifiedAt?: number;
201
+ checks: Array<{ name: string; ok: boolean; message?: string }>;
202
+ }>;
203
+ };
204
+ };
205
+ };
206
+ oidc: Omit<InternalSsoApi["oidc"], "signIn">;
207
+ saml: Omit<InternalSsoApi["saml"], "metadata">;
208
+ policy: InternalSsoApi["policy"];
209
+ audit: {
210
+ list: InternalSsoApi["audit"]["list"];
211
+ };
212
+ webhook: {
213
+ endpoint: InternalSsoApi["webhook"]["endpoint"];
214
+ delivery: {
215
+ list: InternalSsoApi["webhook"]["delivery"]["list"];
216
+ };
217
+ };
218
+ };
219
+
220
+ type PublicSsoClientApi = {
221
+ signIn: InternalSsoApi["oidc"]["signIn"];
222
+ metadata: InternalSsoApi["saml"]["metadata"];
223
+ };
224
+
225
+ type PublicSsoApi = {
226
+ admin: PublicSsoAdminApi;
227
+ client: PublicSsoClientApi;
228
+ };
229
+
230
+ type PublicScimApi = {
231
+ admin: Omit<InternalSsoApi["scim"], "getConfigByToken" | "identity">;
232
+ };
233
+
234
+ /** Auth API with enterprise namespaces — present only when `new SSO()` is in providers. */
235
+ export type AuthApi<
236
+ TAuthorization extends AuthAuthorizationConfig | undefined = undefined,
237
+ > = AuthApiBase<TAuthorization> & {
238
+ sso: PublicSsoApi;
239
+ scim: PublicScimApi;
53
240
  };
54
241
 
55
242
  /**
56
243
  * The return type of `createAuth`. Conditional namespaces:
57
- * - `auth.sso` — only when `new SSO()` is in providers
244
+ * - `auth.sso` and `auth.scim` — only when `new SSO()` is in providers
58
245
  * - `auth.clientApi` — typed API refs for the client SDK with capabilities
59
246
  */
60
- export type ConvexAuthResult<P extends AuthProviderConfig[]> =
61
- HasSSO<P> extends true ? AuthApi : AuthApiBase;
247
+ export type ConvexAuthResult<
248
+ P extends AuthProviderConfig[],
249
+ TAuthorization extends AuthAuthorizationConfig | undefined = undefined,
250
+ > =
251
+ HasSSO<P> extends true
252
+ ? AuthApi<TAuthorization>
253
+ : AuthApiBase<TAuthorization>;
62
254
 
63
255
  /**
64
256
  * Infer the typed `AuthApiRefs` for the client SDK from a `createAuth` call.
@@ -72,7 +264,7 @@ export type ConvexAuthResult<P extends AuthProviderConfig[]> =
72
264
  * // Frontend
73
265
  * import type { auth } from "../convex/auth";
74
266
  * import type { InferClientApi } from "@robelest/convex-auth/component";
75
- * const c = client<InferClientApi<typeof auth>>({ convex, api: { ... } });
267
+ * const c = client<InferClientApi<typeof auth>>({ convex, api: api.auth });
76
268
  * ```
77
269
  */
78
270
  export type InferClientApi<T> =
@@ -94,19 +286,182 @@ export type AuthLike = Pick<AuthApiBase, "user">;
94
286
  /**
95
287
  * Create an auth API object.
96
288
  *
97
- * When `new SSO()` is included in providers, `auth.sso` is available
98
- * on the returned object. Without it, `auth.sso` is absent and
99
- * accessing it is a TypeScript compile error.
289
+ * When `new SSO()` is included in providers, `auth.sso` and `auth.scim`
290
+ * are available on the returned object. Without it, those namespaces are
291
+ * absent and accessing them is a TypeScript compile error.
100
292
  */
101
- export function createAuth<P extends AuthProviderConfig[]>(
293
+ export function createAuth<
294
+ P extends AuthProviderConfig[],
295
+ TAuthorization extends AuthAuthorizationConfig | undefined = undefined,
296
+ >(
102
297
  component: ConvexAuthConfig["component"],
103
- config: Omit<AuthConfig, "providers"> & { providers: P },
104
- ): ConvexAuthResult<P> {
298
+ config: Omit<AuthConfig, "providers" | "authorization"> & {
299
+ providers: P;
300
+ authorization?: TAuthorization;
301
+ },
302
+ ): ConvexAuthResult<P, TAuthorization> {
105
303
  const authResult = AuthFactory({
106
304
  ...config,
107
305
  component,
108
306
  providers: [...config.providers],
109
307
  });
308
+ const {
309
+ domain: domainApi,
310
+ scim: scimApi,
311
+ connection: connectionApi,
312
+ audit: auditApi,
313
+ webhook: webhookApi,
314
+ oidc: oidcApi,
315
+ saml: samlApi,
316
+ ...restSso
317
+ } = authResult.auth.sso as InternalSsoApi;
318
+
319
+ type SetEnterpriseDomains = PublicSsoAdminApi["connection"]["domain"]["set"];
320
+ type EnterpriseDomainInput = Array<{
321
+ domain: string;
322
+ isPrimary?: boolean;
323
+ }>;
324
+ const setEnterpriseDomains: PublicSsoAdminApi["connection"]["domain"]["set"] =
325
+ async (
326
+ ctx: Parameters<SetEnterpriseDomains>[0],
327
+ enterpriseId: Parameters<SetEnterpriseDomains>[1],
328
+ domains: EnterpriseDomainInput,
329
+ ) => {
330
+ const enterprise = await connectionApi.get(ctx, enterpriseId);
331
+ if (enterprise === null) {
332
+ throw new AuthError(
333
+ "INVALID_PARAMETERS",
334
+ "Enterprise not found.",
335
+ ).toConvexError();
336
+ }
337
+
338
+ const normalized = domains.map((entry: (typeof domains)[number]) => ({
339
+ ...entry,
340
+ domain: entry.domain.trim().toLowerCase(),
341
+ }));
342
+ const deduped = new Map<string, (typeof normalized)[number]>();
343
+ for (const entry of normalized) {
344
+ if (entry.domain.length === 0) {
345
+ throw new AuthError(
346
+ "INVALID_PARAMETERS",
347
+ "Domain must not be empty.",
348
+ ).toConvexError();
349
+ }
350
+ if (deduped.has(entry.domain)) {
351
+ throw new AuthError(
352
+ "INVALID_PARAMETERS",
353
+ `Duplicate domain: ${entry.domain}`,
354
+ ).toConvexError();
355
+ }
356
+ deduped.set(entry.domain, entry);
357
+ }
358
+
359
+ const nextDomains = [...deduped.values()];
360
+ const primaryCount = nextDomains.filter(
361
+ (entry) => entry.isPrimary,
362
+ ).length;
363
+ if (primaryCount > 1) {
364
+ throw new AuthError(
365
+ "INVALID_PARAMETERS",
366
+ "Only one primary domain may be set.",
367
+ ).toConvexError();
368
+ }
369
+ if (nextDomains.length > 0 && primaryCount === 0) {
370
+ nextDomains[0] = { ...nextDomains[0], isPrimary: true };
371
+ }
372
+
373
+ const currentDomains = await domainApi.list(ctx, enterpriseId);
374
+ const currentByDomain = new Map<string, (typeof currentDomains)[number]>(
375
+ currentDomains.map((entry: (typeof currentDomains)[number]) => [
376
+ entry.domain.toLowerCase(),
377
+ entry,
378
+ ]),
379
+ );
380
+
381
+ for (const existing of currentDomains) {
382
+ if (!deduped.has(existing.domain.toLowerCase())) {
383
+ await domainApi.remove(ctx, existing._id);
384
+ }
385
+ }
386
+
387
+ for (const nextDomain of nextDomains) {
388
+ const current = currentByDomain.get(nextDomain.domain);
389
+ if (current && current.isPrimary === Boolean(nextDomain.isPrimary)) {
390
+ continue;
391
+ }
392
+ if (current) {
393
+ await domainApi.remove(ctx, current._id);
394
+ }
395
+ const domainId = await domainApi.add(ctx, {
396
+ enterpriseId: enterprise._id,
397
+ groupId: enterprise.groupId,
398
+ domain: nextDomain.domain,
399
+ isPrimary: nextDomain.isPrimary,
400
+ });
401
+ if (current?.verifiedAt !== undefined) {
402
+ await (ctx as any).runMutation(
403
+ component.public.enterpriseDomainVerify,
404
+ {
405
+ domainId,
406
+ verifiedAt: current.verifiedAt,
407
+ },
408
+ );
409
+ }
410
+ }
411
+
412
+ const updatedDomains = await domainApi.list(ctx, enterpriseId);
413
+ return {
414
+ ok: true as const,
415
+ enterpriseId,
416
+ domains: updatedDomains.map(
417
+ (domain: (typeof updatedDomains)[number]) => ({
418
+ domainId: domain._id,
419
+ domain: domain.domain,
420
+ isPrimary: domain.isPrimary,
421
+ verified: domain.verifiedAt !== undefined,
422
+ verifiedAt: domain.verifiedAt ?? null,
423
+ }),
424
+ ),
425
+ };
426
+ };
427
+
428
+ const publicSso: PublicSsoApi = {
429
+ admin: {
430
+ ...restSso,
431
+ oidc: {
432
+ ...oidcApi,
433
+ },
434
+ saml: {
435
+ ...samlApi,
436
+ },
437
+ connection: {
438
+ ...connectionApi,
439
+ domain: {
440
+ list: domainApi.list,
441
+ validate: domainApi.validate,
442
+ set: setEnterpriseDomains,
443
+ verification: {
444
+ request: domainApi.verification.request,
445
+ confirm: domainApi.verification.confirm,
446
+ },
447
+ },
448
+ },
449
+ policy: restSso.policy,
450
+ audit: {
451
+ list: auditApi.list,
452
+ },
453
+ webhook: {
454
+ endpoint: webhookApi.endpoint,
455
+ delivery: {
456
+ list: webhookApi.delivery.list,
457
+ },
458
+ },
459
+ },
460
+ client: {
461
+ signIn: oidcApi.signIn,
462
+ metadata: samlApi.metadata,
463
+ },
464
+ };
110
465
 
111
466
  return {
112
467
  signIn: authResult.signIn,
@@ -118,11 +473,51 @@ export function createAuth<P extends AuthProviderConfig[]>(
118
473
  account: authResult.auth.account,
119
474
  group: authResult.auth.group,
120
475
  member: authResult.auth.member,
476
+ access: authResult.auth.access,
121
477
  invite: authResult.auth.invite,
122
478
  key: authResult.auth.key,
123
- sso: authResult.auth.sso,
479
+ sso: publicSso,
480
+ scim: {
481
+ admin: {
482
+ configure: scimApi.configure,
483
+ get: scimApi.get,
484
+ validate: scimApi.validate,
485
+ },
486
+ },
124
487
  http: authResult.auth.http,
125
- } as ConvexAuthResult<P>;
488
+ } as unknown as ConvexAuthResult<P, TAuthorization>;
489
+ }
490
+
491
+ export function defineRoles<
492
+ const TRoles extends Record<
493
+ string,
494
+ { label?: string; grants: readonly string[] }
495
+ >,
496
+ >(
497
+ roles: TRoles,
498
+ ): {
499
+ [K in keyof TRoles]: {
500
+ id: K & string;
501
+ label?: TRoles[K]["label"];
502
+ grants: Array<TRoles[K]["grants"][number] & string>;
503
+ };
504
+ } {
505
+ return Object.fromEntries(
506
+ Object.entries(roles).map(([id, role]) => [
507
+ id,
508
+ {
509
+ id,
510
+ ...(role.label ? { label: role.label } : {}),
511
+ grants: [...role.grants],
512
+ },
513
+ ]),
514
+ ) as {
515
+ [K in keyof TRoles]: {
516
+ id: K & string;
517
+ label?: TRoles[K]["label"];
518
+ grants: Array<TRoles[K]["grants"][number] & string>;
519
+ };
520
+ };
126
521
  }
127
522
 
128
523
  // ============================================================================
@@ -1,5 +1,6 @@
1
1
  import { isLocalHost } from "./utils";
2
2
 
3
+ /** @internal */
3
4
  export const SHARED_COOKIE_OPTIONS = {
4
5
  httpOnly: true,
5
6
  sameSite: "none" as const,
@@ -9,6 +10,7 @@ export const SHARED_COOKIE_OPTIONS = {
9
10
  };
10
11
 
11
12
  const REDIRECT_MAX_AGE = 60 * 15; // 15 minutes in seconds
13
+ /** @internal */
12
14
  export function redirectToParamCookie(providerId: string, redirectTo: string) {
13
15
  return {
14
16
  name: redirectToParamCookieName(providerId),
@@ -17,6 +19,7 @@ export function redirectToParamCookie(providerId: string, redirectTo: string) {
17
19
  };
18
20
  }
19
21
 
22
+ /** @internal */
20
23
  export function useRedirectToParam(
21
24
  providerId: string,
22
25
  cookies: Record<string, string | undefined>,
package/src/server/db.ts CHANGED
@@ -56,10 +56,13 @@ type AuthComponentApiLike = {
56
56
  };
57
57
  };
58
58
 
59
+ /** @internal */
59
60
  export type AuthDbConfig = { component: AuthComponentApiLike };
60
61
 
62
+ /** @internal */
61
63
  export type AuthDb = ReturnType<typeof authDb>;
62
64
 
65
+ /** @internal */
63
66
  export function authDb(ctx: CtxLike, config: AuthDbConfig) {
64
67
  const component = config.component;
65
68
  return {
@@ -13,6 +13,7 @@
13
13
  import { Fx } from "@robelest/fx";
14
14
 
15
15
  import { AuthError } from "./fx";
16
+ import { userIdFromIdentitySubject } from "./identity";
16
17
  import { callSignIn } from "./mutations/index";
17
18
  import { DeviceProviderConfig, GenericActionCtxWithAuthConfig } from "./types";
18
19
  import {
@@ -63,6 +64,7 @@ type DeviceResult =
63
64
  }
64
65
  | { kind: "signedIn"; signedIn: SessionInfo | null };
65
66
 
67
+ /** @internal */
66
68
  export const handleDevice = (
67
69
  ctx: EnrichedActionCtx,
68
70
  provider: DeviceProviderConfig,
@@ -187,7 +189,7 @@ export const handleDevice = (
187
189
  );
188
190
  }
189
191
 
190
- const userId = identity.subject.split("|")[0]!;
192
+ const userId = userIdFromIdentitySubject(identity.subject);
191
193
  const doc = await queryDeviceByUserCode(ctx, params.userCode);
192
194
  if (doc === null) {
193
195
  throw new AuthError("DEVICE_INVALID_USER_CODE");