@robelest/convex-auth 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (280) hide show
  1. package/README.md +6 -0
  2. package/dist/bin.cjs +27733 -0
  3. package/dist/client/index.d.ts +49 -0
  4. package/dist/client/index.d.ts.map +1 -0
  5. package/dist/client/index.js +283 -0
  6. package/dist/client/index.js.map +1 -0
  7. package/dist/component/_generated/api.d.ts +36 -0
  8. package/dist/component/_generated/api.d.ts.map +1 -0
  9. package/dist/component/_generated/api.js +31 -0
  10. package/dist/component/_generated/api.js.map +1 -0
  11. package/dist/component/_generated/component.d.ts +295 -0
  12. package/dist/component/_generated/component.d.ts.map +1 -0
  13. package/dist/component/_generated/component.js +11 -0
  14. package/dist/component/_generated/component.js.map +1 -0
  15. package/dist/component/_generated/dataModel.d.ts +46 -0
  16. package/dist/component/_generated/dataModel.d.ts.map +1 -0
  17. package/dist/component/_generated/dataModel.js +11 -0
  18. package/dist/component/_generated/dataModel.js.map +1 -0
  19. package/dist/component/_generated/server.d.ts +121 -0
  20. package/dist/component/_generated/server.d.ts.map +1 -0
  21. package/dist/component/_generated/server.js +78 -0
  22. package/dist/component/_generated/server.js.map +1 -0
  23. package/dist/component/convex.config.d.ts +3 -0
  24. package/dist/component/convex.config.d.ts.map +1 -0
  25. package/dist/component/convex.config.js +4 -0
  26. package/dist/component/convex.config.js.map +1 -0
  27. package/dist/component/index.d.ts +15 -0
  28. package/dist/component/index.d.ts.map +1 -0
  29. package/dist/component/index.js +13 -0
  30. package/dist/component/index.js.map +1 -0
  31. package/dist/component/public.d.ts +450 -0
  32. package/dist/component/public.d.ts.map +1 -0
  33. package/dist/component/public.js +528 -0
  34. package/dist/component/public.js.map +1 -0
  35. package/dist/component/schema.d.ts +107 -0
  36. package/dist/component/schema.d.ts.map +1 -0
  37. package/dist/component/schema.js +26 -0
  38. package/dist/component/schema.js.map +1 -0
  39. package/dist/providers/Anonymous.d.ts +50 -0
  40. package/dist/providers/Anonymous.d.ts.map +1 -0
  41. package/dist/providers/Anonymous.js +39 -0
  42. package/dist/providers/Anonymous.js.map +1 -0
  43. package/dist/providers/ConvexCredentials.d.ts +88 -0
  44. package/dist/providers/ConvexCredentials.d.ts.map +1 -0
  45. package/dist/providers/ConvexCredentials.js +37 -0
  46. package/dist/providers/ConvexCredentials.js.map +1 -0
  47. package/dist/providers/Email.d.ts +33 -0
  48. package/dist/providers/Email.d.ts.map +1 -0
  49. package/dist/providers/Email.js +50 -0
  50. package/dist/providers/Email.js.map +1 -0
  51. package/dist/providers/Password.d.ts +95 -0
  52. package/dist/providers/Password.d.ts.map +1 -0
  53. package/dist/providers/Password.js +174 -0
  54. package/dist/providers/Password.js.map +1 -0
  55. package/dist/providers/Phone.d.ts +22 -0
  56. package/dist/providers/Phone.d.ts.map +1 -0
  57. package/dist/providers/Phone.js +37 -0
  58. package/dist/providers/Phone.js.map +1 -0
  59. package/dist/server/convex_types.d.ts +17 -0
  60. package/dist/server/convex_types.d.ts.map +1 -0
  61. package/dist/server/convex_types.js +2 -0
  62. package/dist/server/convex_types.js.map +1 -0
  63. package/dist/server/cookies.d.ts +35 -0
  64. package/dist/server/cookies.d.ts.map +1 -0
  65. package/dist/server/cookies.js +34 -0
  66. package/dist/server/cookies.js.map +1 -0
  67. package/dist/server/implementation/db.d.ts +80 -0
  68. package/dist/server/implementation/db.d.ts.map +1 -0
  69. package/dist/server/implementation/db.js +59 -0
  70. package/dist/server/implementation/db.js.map +1 -0
  71. package/dist/server/implementation/index.d.ts +370 -0
  72. package/dist/server/implementation/index.d.ts.map +1 -0
  73. package/dist/server/implementation/index.js +521 -0
  74. package/dist/server/implementation/index.js.map +1 -0
  75. package/dist/server/implementation/mutations/createAccountFromCredentials.d.ts +33 -0
  76. package/dist/server/implementation/mutations/createAccountFromCredentials.d.ts.map +1 -0
  77. package/dist/server/implementation/mutations/createAccountFromCredentials.js +71 -0
  78. package/dist/server/implementation/mutations/createAccountFromCredentials.js.map +1 -0
  79. package/dist/server/implementation/mutations/createVerificationCode.d.ts +25 -0
  80. package/dist/server/implementation/mutations/createVerificationCode.d.ts.map +1 -0
  81. package/dist/server/implementation/mutations/createVerificationCode.js +84 -0
  82. package/dist/server/implementation/mutations/createVerificationCode.js.map +1 -0
  83. package/dist/server/implementation/mutations/index.d.ts +304 -0
  84. package/dist/server/implementation/mutations/index.d.ts.map +1 -0
  85. package/dist/server/implementation/mutations/index.js +108 -0
  86. package/dist/server/implementation/mutations/index.js.map +1 -0
  87. package/dist/server/implementation/mutations/invalidateSessions.d.ts +13 -0
  88. package/dist/server/implementation/mutations/invalidateSessions.d.ts.map +1 -0
  89. package/dist/server/implementation/mutations/invalidateSessions.js +35 -0
  90. package/dist/server/implementation/mutations/invalidateSessions.js.map +1 -0
  91. package/dist/server/implementation/mutations/modifyAccount.d.ts +23 -0
  92. package/dist/server/implementation/mutations/modifyAccount.d.ts.map +1 -0
  93. package/dist/server/implementation/mutations/modifyAccount.js +48 -0
  94. package/dist/server/implementation/mutations/modifyAccount.js.map +1 -0
  95. package/dist/server/implementation/mutations/refreshSession.d.ts +16 -0
  96. package/dist/server/implementation/mutations/refreshSession.d.ts.map +1 -0
  97. package/dist/server/implementation/mutations/refreshSession.js +116 -0
  98. package/dist/server/implementation/mutations/refreshSession.js.map +1 -0
  99. package/dist/server/implementation/mutations/retrieveAccountWithCredentials.d.ts +27 -0
  100. package/dist/server/implementation/mutations/retrieveAccountWithCredentials.d.ts.map +1 -0
  101. package/dist/server/implementation/mutations/retrieveAccountWithCredentials.js +55 -0
  102. package/dist/server/implementation/mutations/retrieveAccountWithCredentials.js.map +1 -0
  103. package/dist/server/implementation/mutations/signIn.d.ts +17 -0
  104. package/dist/server/implementation/mutations/signIn.d.ts.map +1 -0
  105. package/dist/server/implementation/mutations/signIn.js +26 -0
  106. package/dist/server/implementation/mutations/signIn.js.map +1 -0
  107. package/dist/server/implementation/mutations/signOut.d.ts +11 -0
  108. package/dist/server/implementation/mutations/signOut.d.ts.map +1 -0
  109. package/dist/server/implementation/mutations/signOut.js +24 -0
  110. package/dist/server/implementation/mutations/signOut.js.map +1 -0
  111. package/dist/server/implementation/mutations/userOAuth.d.ts +19 -0
  112. package/dist/server/implementation/mutations/userOAuth.d.ts.map +1 -0
  113. package/dist/server/implementation/mutations/userOAuth.js +84 -0
  114. package/dist/server/implementation/mutations/userOAuth.js.map +1 -0
  115. package/dist/server/implementation/mutations/verifier.d.ts +8 -0
  116. package/dist/server/implementation/mutations/verifier.d.ts.map +1 -0
  117. package/dist/server/implementation/mutations/verifier.js +19 -0
  118. package/dist/server/implementation/mutations/verifier.js.map +1 -0
  119. package/dist/server/implementation/mutations/verifierSignature.d.ts +15 -0
  120. package/dist/server/implementation/mutations/verifierSignature.d.ts.map +1 -0
  121. package/dist/server/implementation/mutations/verifierSignature.js +29 -0
  122. package/dist/server/implementation/mutations/verifierSignature.js.map +1 -0
  123. package/dist/server/implementation/mutations/verifyCodeAndSignIn.d.ts +21 -0
  124. package/dist/server/implementation/mutations/verifyCodeAndSignIn.d.ts.map +1 -0
  125. package/dist/server/implementation/mutations/verifyCodeAndSignIn.js +127 -0
  126. package/dist/server/implementation/mutations/verifyCodeAndSignIn.js.map +1 -0
  127. package/dist/server/implementation/provider.d.ts +6 -0
  128. package/dist/server/implementation/provider.d.ts.map +1 -0
  129. package/dist/server/implementation/provider.js +21 -0
  130. package/dist/server/implementation/provider.js.map +1 -0
  131. package/dist/server/implementation/rateLimit.d.ts +6 -0
  132. package/dist/server/implementation/rateLimit.d.ts.map +1 -0
  133. package/dist/server/implementation/rateLimit.js +76 -0
  134. package/dist/server/implementation/rateLimit.js.map +1 -0
  135. package/dist/server/implementation/redirects.d.ts +6 -0
  136. package/dist/server/implementation/redirects.d.ts.map +1 -0
  137. package/dist/server/implementation/redirects.js +40 -0
  138. package/dist/server/implementation/redirects.js.map +1 -0
  139. package/dist/server/implementation/refreshTokens.d.ts +40 -0
  140. package/dist/server/implementation/refreshTokens.d.ts.map +1 -0
  141. package/dist/server/implementation/refreshTokens.js +160 -0
  142. package/dist/server/implementation/refreshTokens.js.map +1 -0
  143. package/dist/server/implementation/sessions.d.ts +43 -0
  144. package/dist/server/implementation/sessions.d.ts.map +1 -0
  145. package/dist/server/implementation/sessions.js +94 -0
  146. package/dist/server/implementation/sessions.js.map +1 -0
  147. package/dist/server/implementation/signIn.d.ts +31 -0
  148. package/dist/server/implementation/signIn.d.ts.map +1 -0
  149. package/dist/server/implementation/signIn.js +148 -0
  150. package/dist/server/implementation/signIn.js.map +1 -0
  151. package/dist/server/implementation/tokens.d.ts +7 -0
  152. package/dist/server/implementation/tokens.d.ts.map +1 -0
  153. package/dist/server/implementation/tokens.js +18 -0
  154. package/dist/server/implementation/tokens.js.map +1 -0
  155. package/dist/server/implementation/types.d.ts +288 -0
  156. package/dist/server/implementation/types.d.ts.map +1 -0
  157. package/dist/server/implementation/types.js +182 -0
  158. package/dist/server/implementation/types.js.map +1 -0
  159. package/dist/server/implementation/users.d.ts +27 -0
  160. package/dist/server/implementation/users.d.ts.map +1 -0
  161. package/dist/server/implementation/users.js +181 -0
  162. package/dist/server/implementation/users.js.map +1 -0
  163. package/dist/server/implementation/utils.d.ts +17 -0
  164. package/dist/server/implementation/utils.d.ts.map +1 -0
  165. package/dist/server/implementation/utils.js +72 -0
  166. package/dist/server/implementation/utils.js.map +1 -0
  167. package/dist/server/index.d.ts +17 -0
  168. package/dist/server/index.d.ts.map +1 -0
  169. package/dist/server/index.js +54 -0
  170. package/dist/server/index.js.map +1 -0
  171. package/dist/server/oauth/authorizationUrl.d.ts +13 -0
  172. package/dist/server/oauth/authorizationUrl.d.ts.map +1 -0
  173. package/dist/server/oauth/authorizationUrl.js +91 -0
  174. package/dist/server/oauth/authorizationUrl.js.map +1 -0
  175. package/dist/server/oauth/callback.d.ts +19 -0
  176. package/dist/server/oauth/callback.d.ts.map +1 -0
  177. package/dist/server/oauth/callback.js +173 -0
  178. package/dist/server/oauth/callback.js.map +1 -0
  179. package/dist/server/oauth/checks.d.ts +52 -0
  180. package/dist/server/oauth/checks.d.ts.map +1 -0
  181. package/dist/server/oauth/checks.js +106 -0
  182. package/dist/server/oauth/checks.js.map +1 -0
  183. package/dist/server/oauth/convexAuth.d.ts +12 -0
  184. package/dist/server/oauth/convexAuth.d.ts.map +1 -0
  185. package/dist/server/oauth/convexAuth.js +137 -0
  186. package/dist/server/oauth/convexAuth.js.map +1 -0
  187. package/dist/server/oauth/lib/utils/customFetch.d.ts +9 -0
  188. package/dist/server/oauth/lib/utils/customFetch.d.ts.map +1 -0
  189. package/dist/server/oauth/lib/utils/customFetch.js +11 -0
  190. package/dist/server/oauth/lib/utils/customFetch.js.map +1 -0
  191. package/dist/server/oauth/lib/utils/providers.d.ts +3 -0
  192. package/dist/server/oauth/lib/utils/providers.d.ts.map +1 -0
  193. package/dist/server/oauth/lib/utils/providers.js +7 -0
  194. package/dist/server/oauth/lib/utils/providers.js.map +1 -0
  195. package/dist/server/oauth/providers/oauth.d.ts +43 -0
  196. package/dist/server/oauth/providers/oauth.d.ts.map +1 -0
  197. package/dist/server/oauth/providers/oauth.js +3 -0
  198. package/dist/server/oauth/providers/oauth.js.map +1 -0
  199. package/dist/server/oauth/types.d.ts +24 -0
  200. package/dist/server/oauth/types.d.ts.map +1 -0
  201. package/dist/server/oauth/types.js +5 -0
  202. package/dist/server/oauth/types.js.map +1 -0
  203. package/dist/server/provider_utils.d.ts +76 -0
  204. package/dist/server/provider_utils.d.ts.map +1 -0
  205. package/dist/server/provider_utils.js +177 -0
  206. package/dist/server/provider_utils.js.map +1 -0
  207. package/dist/server/types.d.ts +412 -0
  208. package/dist/server/types.d.ts.map +1 -0
  209. package/dist/server/types.js +2 -0
  210. package/dist/server/types.js.map +1 -0
  211. package/dist/server/utils.d.ts +3 -0
  212. package/dist/server/utils.d.ts.map +1 -0
  213. package/dist/server/utils.js +11 -0
  214. package/dist/server/utils.js.map +1 -0
  215. package/package.json +126 -0
  216. package/providers/Anonymous/package.json +6 -0
  217. package/providers/ConvexCredentials/package.json +6 -0
  218. package/providers/Email/package.json +6 -0
  219. package/providers/Password/package.json +6 -0
  220. package/providers/Phone/package.json +6 -0
  221. package/server/package.json +6 -0
  222. package/src/cli/command.ts +69 -0
  223. package/src/cli/generateKeys.ts +20 -0
  224. package/src/cli/index.ts +840 -0
  225. package/src/client/index.ts +415 -0
  226. package/src/component/_generated/api.ts +52 -0
  227. package/src/component/_generated/component.ts +586 -0
  228. package/src/component/_generated/dataModel.ts +60 -0
  229. package/src/component/_generated/server.ts +156 -0
  230. package/src/component/convex.config.ts +5 -0
  231. package/src/component/index.ts +40 -0
  232. package/src/component/public.ts +607 -0
  233. package/src/component/schema.ts +35 -0
  234. package/src/providers/Anonymous.ts +79 -0
  235. package/src/providers/ConvexCredentials.ts +108 -0
  236. package/src/providers/Email.ts +60 -0
  237. package/src/providers/Password.ts +253 -0
  238. package/src/providers/Phone.ts +46 -0
  239. package/src/server/convex_types.ts +55 -0
  240. package/src/server/cookies.ts +42 -0
  241. package/src/server/implementation/db.ts +125 -0
  242. package/src/server/implementation/index.ts +815 -0
  243. package/src/server/implementation/mutations/createAccountFromCredentials.ts +113 -0
  244. package/src/server/implementation/mutations/createVerificationCode.ts +139 -0
  245. package/src/server/implementation/mutations/index.ts +157 -0
  246. package/src/server/implementation/mutations/invalidateSessions.ts +47 -0
  247. package/src/server/implementation/mutations/modifyAccount.ts +65 -0
  248. package/src/server/implementation/mutations/refreshSession.ts +188 -0
  249. package/src/server/implementation/mutations/retrieveAccountWithCredentials.ts +87 -0
  250. package/src/server/implementation/mutations/signIn.ts +51 -0
  251. package/src/server/implementation/mutations/signOut.ts +38 -0
  252. package/src/server/implementation/mutations/userOAuth.ts +112 -0
  253. package/src/server/implementation/mutations/verifier.ts +29 -0
  254. package/src/server/implementation/mutations/verifierSignature.ts +44 -0
  255. package/src/server/implementation/mutations/verifyCodeAndSignIn.ts +205 -0
  256. package/src/server/implementation/provider.ts +38 -0
  257. package/src/server/implementation/rateLimit.ts +105 -0
  258. package/src/server/implementation/redirects.ts +58 -0
  259. package/src/server/implementation/refreshTokens.ts +221 -0
  260. package/src/server/implementation/sessions.ts +155 -0
  261. package/src/server/implementation/signIn.ts +253 -0
  262. package/src/server/implementation/tokens.ts +29 -0
  263. package/src/server/implementation/types.ts +220 -0
  264. package/src/server/implementation/users.ts +286 -0
  265. package/src/server/implementation/utils.ts +91 -0
  266. package/src/server/index.ts +74 -0
  267. package/src/server/oauth/NOTICE.txt +21 -0
  268. package/src/server/oauth/README.md +7 -0
  269. package/src/server/oauth/authorizationUrl.ts +113 -0
  270. package/src/server/oauth/callback.ts +243 -0
  271. package/src/server/oauth/checks.ts +136 -0
  272. package/src/server/oauth/convexAuth.ts +168 -0
  273. package/src/server/oauth/lib/utils/customFetch.ts +18 -0
  274. package/src/server/oauth/lib/utils/providers.ts +12 -0
  275. package/src/server/oauth/providers/oauth.ts +56 -0
  276. package/src/server/oauth/types.ts +60 -0
  277. package/src/server/provider_utils.ts +222 -0
  278. package/src/server/types.ts +470 -0
  279. package/src/server/utils.ts +12 -0
  280. package/src/test.ts +24 -0
@@ -0,0 +1,222 @@
1
+ // Some code adapted from Auth.js. Original license:
2
+ //
3
+ // ISC License
4
+ //
5
+ // Copyright (c) 2022-2024, Balázs Orbán
6
+ //
7
+ // Permission to use, copy, modify, and/or distribute this software for any
8
+ // purpose with or without fee is hereby granted, provided that the above
9
+ // copyright notice and this permission notice appear in all copies.
10
+ //
11
+ // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
+ // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
+ // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
+ // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
+ // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
+ // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
+ // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
+
19
+ import { setEnvDefaults } from "@auth/core";
20
+ import {
21
+ AccountCallback,
22
+ OAuth2Config,
23
+ OAuthConfig,
24
+ OAuthEndpointType,
25
+ OIDCConfig,
26
+ ProfileCallback,
27
+ } from "@auth/core/providers";
28
+ import { Profile } from "@auth/core/types";
29
+ import {
30
+ AuthProviderConfig,
31
+ AuthProviderMaterializedConfig,
32
+ ConvexAuthConfig,
33
+ } from "./types.js";
34
+
35
+ /**
36
+ * @internal
37
+ */
38
+ export function configDefaults(config_: ConvexAuthConfig) {
39
+ const config = materializeAndDefaultProviders(config_);
40
+ // Collect extra providers
41
+ const extraProviders = config.providers
42
+ .filter((p) => p.type === "credentials")
43
+ .map((p) => p.extraProviders)
44
+ .flat()
45
+ .filter((p) => p !== undefined);
46
+ return {
47
+ ...config,
48
+ extraProviders: materializeProviders(extraProviders),
49
+ theme: config.theme ?? {
50
+ colorScheme: "auto",
51
+ logo: "",
52
+ brandColor: "",
53
+ buttonText: "",
54
+ },
55
+ };
56
+ }
57
+
58
+ /**
59
+ * @internal
60
+ */
61
+ export function materializeProvider(provider: AuthProviderConfig) {
62
+ const config = { providers: [provider] };
63
+ materializeAndDefaultProviders(config);
64
+ return config.providers[0] as AuthProviderMaterializedConfig;
65
+ }
66
+
67
+ function materializeProviders(providers: AuthProviderConfig[]) {
68
+ const config = { providers };
69
+ materializeAndDefaultProviders(config);
70
+ return config.providers as AuthProviderMaterializedConfig[];
71
+ }
72
+
73
+ function materializeAndDefaultProviders(config_: ConvexAuthConfig) {
74
+ // Have to materialize first so that the correct env variables are used
75
+ const providers = config_.providers.map((provider) =>
76
+ providerDefaults(
77
+ typeof provider === "function" ? provider() : (provider as any),
78
+ ),
79
+ );
80
+ const config = { ...config_, providers };
81
+
82
+ // Unfortunately mutates its argument
83
+ setEnvDefaults(process.env, config as any);
84
+ // Manually do this for new provider type
85
+ config.providers.forEach((provider) => {
86
+ if (provider.type === "phone") {
87
+ const ID = provider.id.toUpperCase().replace(/-/g, "_");
88
+ // Should not require this env var at push time, as the provider's
89
+ // implementation might not use it
90
+ provider.apiKey ??= process.env[`AUTH_${ID}_KEY`];
91
+ }
92
+ });
93
+ return config;
94
+ }
95
+
96
+ function providerDefaults(provider: AuthProviderMaterializedConfig) {
97
+ // TODO: Add `redirectProxyUrl` to oauth providers
98
+ const merged = merge(
99
+ provider,
100
+ (provider as any).options,
101
+ ) as AuthProviderMaterializedConfig;
102
+ return merged.type === "oauth" || merged.type === "oidc"
103
+ ? normalizeOAuth(merged)
104
+ : merged;
105
+ }
106
+
107
+ const defaultProfile: ProfileCallback<Profile> = (profile) => {
108
+ return stripUndefined({
109
+ id: profile.sub ?? profile.id ?? crypto.randomUUID(),
110
+ name: profile.name ?? profile.nickname ?? profile.preferred_username,
111
+ email: profile.email ?? undefined,
112
+ image: profile.picture ?? undefined,
113
+ });
114
+ };
115
+
116
+ const defaultAccount: AccountCallback = (account) => {
117
+ return stripUndefined({
118
+ access_token: account.access_token,
119
+ id_token: account.id_token,
120
+ refresh_token: account.refresh_token,
121
+ expires_at: account.expires_at,
122
+ scope: account.scope,
123
+ token_type: account.token_type,
124
+ session_state: account.session_state,
125
+ });
126
+ };
127
+
128
+ function stripUndefined<T extends object>(o: T): T {
129
+ const result = {} as any;
130
+ for (const [k, v] of Object.entries(o)) v !== undefined && (result[k] = v);
131
+ return result as T;
132
+ }
133
+
134
+ function normalizeOAuth<T extends OIDCConfig<any> | OAuth2Config<any>>(
135
+ c: T,
136
+ ): T {
137
+ if (c.issuer) c.wellKnown ??= `${c.issuer}/.well-known/openid-configuration`;
138
+
139
+ const checks = c.checks ?? ["pkce"];
140
+ if (c.redirectProxyUrl) {
141
+ if (!checks.includes("state")) checks.push("state");
142
+ c.redirectProxyUrl = `${c.redirectProxyUrl}/callback/${c.id}`;
143
+ }
144
+
145
+ return {
146
+ ...c,
147
+ checks,
148
+ profile: c.profile ?? defaultProfile,
149
+ account: c.account ?? defaultAccount,
150
+ };
151
+ }
152
+
153
+ export const PLACEHOLDER_URL_HOST = "convexauth.mumbojumbo";
154
+
155
+ const PLACEHOLDER_URL = `https://${PLACEHOLDER_URL_HOST}`;
156
+
157
+ export function normalizeEndpoint(
158
+ e?: OAuthConfig<any>[OAuthEndpointType],
159
+ issuer?: string,
160
+ ) {
161
+ if (!e && issuer) return undefined;
162
+ if (typeof e === "string") {
163
+ return { url: new URL(e) };
164
+ }
165
+ // Placeholder URL is used to pass around the URL object
166
+ // even if the URL hasn't been specified: the `issuer`
167
+ // is used instead.
168
+ const url = new URL(e?.url ?? PLACEHOLDER_URL);
169
+ if (e?.params != null) {
170
+ for (const [key, value] of Object.entries(e.params)) {
171
+ url.searchParams.set(
172
+ key,
173
+ String(key === "claims" ? JSON.stringify(value) : value),
174
+ );
175
+ }
176
+ }
177
+ return { url, request: e?.request, conform: e?.conform };
178
+ }
179
+
180
+ // Source: https://stackoverflow.com/a/34749873/5364135
181
+
182
+ /**
183
+ * Deep merge two objects
184
+ *
185
+ * @internal
186
+ */
187
+ export function merge(target: any, ...sources: any[]): any {
188
+ if (!sources.length) return target;
189
+ const source = sources.shift();
190
+
191
+ if (isObject(target) && isObject(source)) {
192
+ for (const key in source) {
193
+ if (isObject(source[key])) {
194
+ if (!target[key]) Object.assign(target, { [key]: {} });
195
+ merge(target[key], source[key]);
196
+ } else {
197
+ Object.assign(target, { [key]: source[key] });
198
+ }
199
+ }
200
+ }
201
+
202
+ return merge(target, ...sources);
203
+ }
204
+
205
+ /** Simple object check */
206
+ function isObject(item: any): boolean {
207
+ return item && typeof item === "object" && !Array.isArray(item);
208
+ }
209
+ /**
210
+ * @internal
211
+ */
212
+ export function listAvailableProviders(
213
+ config: ReturnType<typeof configDefaults>,
214
+ allowExtraProviders: boolean,
215
+ ) {
216
+ const availableProviders = config.providers
217
+ .concat(allowExtraProviders ? config.extraProviders : [])
218
+ .map((provider) => `\`${provider.id}\``);
219
+ return availableProviders.length > 0
220
+ ? availableProviders.join(", ")
221
+ : "no providers have been configured";
222
+ }
@@ -0,0 +1,470 @@
1
+ import {
2
+ Provider as AuthjsProviderConfig,
3
+ CredentialsConfig,
4
+ EmailConfig as AuthjsEmailConfig,
5
+ OAuth2Config,
6
+ OIDCConfig,
7
+ } from "@auth/core/providers";
8
+ import { Theme } from "@auth/core/types";
9
+ import {
10
+ AnyDataModel,
11
+ FunctionReference,
12
+ GenericActionCtx,
13
+ GenericDataModel,
14
+ GenericMutationCtx,
15
+ } from "convex/server";
16
+ import { GenericId, Value } from "convex/values";
17
+ import { ConvexCredentialsUserConfig } from "../providers/ConvexCredentials.js";
18
+ import { GenericDoc } from "./convex_types.js";
19
+
20
+ /**
21
+ * The config for the Convex Auth library, passed to `convexAuth`.
22
+ */
23
+ export type ConvexAuthConfig = {
24
+ /**
25
+ * A list of authentication provider configs.
26
+ *
27
+ * You can import existing configs from
28
+ * - `@auth/core/providers/<provider-name>`
29
+ * - `@robelest/convex-auth/providers/<provider-name>`
30
+ */
31
+ providers: AuthProviderConfig[];
32
+ /**
33
+ * Optional auth component reference from `components.auth`.
34
+ *
35
+ * When provided, core auth storage operations are executed through
36
+ * the component API boundary instead of direct table access.
37
+ */
38
+ component?: AuthComponentApi;
39
+ /**
40
+ * Theme used for emails.
41
+ * See [Auth.js theme docs](https://authjs.dev/reference/core/types#theme).
42
+ */
43
+ theme?: Theme;
44
+ /**
45
+ * Session configuration.
46
+ */
47
+ session?: {
48
+ /**
49
+ * How long can a user session last without the user reauthenticating.
50
+ *
51
+ * Defaults to 30 days.
52
+ */
53
+ totalDurationMs?: number;
54
+ /**
55
+ * How long can a user session last without the user being active.
56
+ *
57
+ * Defaults to 30 days.
58
+ */
59
+ inactiveDurationMs?: number;
60
+ };
61
+ /**
62
+ * JWT configuration.
63
+ */
64
+ jwt?: {
65
+ /**
66
+ * How long is the JWT valid for after it is signed initially.
67
+ *
68
+ * Defaults to 1 hour.
69
+ */
70
+ durationMs?: number;
71
+ };
72
+ /**
73
+ * Sign-in configuration.
74
+ */
75
+ signIn?: {
76
+ /**
77
+ * How many times can the user fail to provide the correct credentials
78
+ * (password, OTP) per hour.
79
+ *
80
+ * Defaults to 10 times per hour (that is 10 failed attempts, and then
81
+ * allow another one every 6 minutes).
82
+ */
83
+ maxFailedAttempsPerHour?: number;
84
+ };
85
+ callbacks?: {
86
+ /**
87
+ * Control which URLs are allowed as a destination after OAuth sign-in
88
+ * and for magic links:
89
+ *
90
+ * ```ts
91
+ * import GitHub from "@auth/core/providers/github";
92
+ * import { convexAuth } from "@robelest/convex-auth/component";
93
+ *
94
+ * export const { auth, signIn, signOut, store } = convexAuth({
95
+ * providers: [GitHub],
96
+ * callbacks: {
97
+ * async redirect({ redirectTo }) {
98
+ * // Check that `redirectTo` is valid
99
+ * // and return the relative or absolute URL
100
+ * // to redirect to.
101
+ * },
102
+ * },
103
+ * });
104
+ * ```
105
+ *
106
+ * Convex Auth performs redirect only during OAuth sign-in. By default,
107
+ * it redirects back to the URL specified via the `SITE_URL` environment
108
+ * variable. Similarly magic links link to `SITE_URL`.
109
+ *
110
+ * You can customize that behavior by providing a `redirectTo` param
111
+ * to the `signIn` function:
112
+ *
113
+ * ```ts
114
+ * signIn("google", { redirectTo: "/dashboard" })
115
+ * ```
116
+ *
117
+ * You can even redirect to a different site.
118
+ *
119
+ * This callback, if specified, is then called with the provided
120
+ * `redirectTo` param. Otherwise, only query params, relative paths
121
+ * and URLs starting with `SITE_URL` are allowed.
122
+ */
123
+ redirect?: (params: {
124
+ /**
125
+ * The param value passed to the `signIn` function.
126
+ */
127
+ redirectTo: string;
128
+ }) => Promise<string>;
129
+ /**
130
+ * Completely control account linking via this callback.
131
+ *
132
+ * This callback is called during the sign-in process,
133
+ * before account creation and token generation.
134
+ * If specified, this callback is responsible for creating
135
+ * or updating the user document.
136
+ *
137
+ * For "credentials" providers, the callback is only called
138
+ * when `createAccount` is called.
139
+ */
140
+ createOrUpdateUser?: (
141
+ ctx: GenericMutationCtx<AnyDataModel>,
142
+ args: {
143
+ /**
144
+ * If this is a sign-in to an existing account,
145
+ * this is the existing user ID linked to that account.
146
+ */
147
+ existingUserId: GenericId<"user"> | null;
148
+ /**
149
+ * The provider type or "verification" if this callback is called
150
+ * after an email or phone token verification.
151
+ */
152
+ type: "oauth" | "credentials" | "email" | "phone" | "verification";
153
+ /**
154
+ * The provider used for the sign-in, or the provider
155
+ * tied to the account which is having the email or phone verified.
156
+ */
157
+ provider: AuthProviderMaterializedConfig;
158
+ /**
159
+ * - The profile returned by the OAuth provider's `profile` method.
160
+ * - The profile passed to `createAccount` from a ConvexCredentials
161
+ * config.
162
+ * - The email address to which an email will be sent.
163
+ * - The phone number to which a text will be sent.
164
+ */
165
+ profile: Record<string, unknown> & {
166
+ email?: string;
167
+ phone?: string;
168
+ emailVerified?: boolean;
169
+ phoneVerified?: boolean;
170
+ };
171
+ /**
172
+ * The `shouldLink` argument passed to `createAccount`.
173
+ */
174
+ shouldLink?: boolean;
175
+ },
176
+ ) => Promise<GenericId<"user">>;
177
+ /**
178
+ * Perform additional writes after a user is created.
179
+ *
180
+ * This callback is called during the sign-in process,
181
+ * after the user is created or updated,
182
+ * before account creation and token generation.
183
+ *
184
+ * **This callback is only called if `createOrUpdateUser`
185
+ * is not specified.** If `createOrUpdateUser` is specified,
186
+ * you can perform any additional writes in that callback.
187
+ *
188
+ * For "credentials" providers, the callback is only called
189
+ * when `createAccount` is called.
190
+ */
191
+ afterUserCreatedOrUpdated?: (
192
+ ctx: GenericMutationCtx<AnyDataModel>,
193
+ args: {
194
+ /**
195
+ * The ID of the user that is being signed in.
196
+ */
197
+ userId: GenericId<"user">;
198
+ /**
199
+ * If this is a sign-in to an existing account,
200
+ * this is the existing user ID linked to that account.
201
+ */
202
+ existingUserId: GenericId<"user"> | null;
203
+ /**
204
+ * The provider type or "verification" if this callback is called
205
+ * after an email or phone token verification.
206
+ */
207
+ type: "oauth" | "credentials" | "email" | "phone" | "verification";
208
+ /**
209
+ * The provider used for the sign-in, or the provider
210
+ * tied to the account which is having the email or phone verified.
211
+ */
212
+ provider: AuthProviderMaterializedConfig;
213
+ /**
214
+ * - The profile returned by the OAuth provider's `profile` method.
215
+ * - The profile passed to `createAccount` from a ConvexCredentials
216
+ * config.
217
+ * - The email address to which an email will be sent.
218
+ * - The phone number to which a text will be sent.
219
+ */
220
+ profile: Record<string, unknown> & {
221
+ email?: string;
222
+ phone?: string;
223
+ emailVerified?: boolean;
224
+ phoneVerified?: boolean;
225
+ };
226
+ /**
227
+ * The `shouldLink` argument passed to `createAccount`.
228
+ */
229
+ shouldLink?: boolean;
230
+ },
231
+ ) => Promise<void>;
232
+ };
233
+ };
234
+
235
+ /**
236
+ * Same as Auth.js provider configs, but adds phone provider
237
+ * for verification via SMS or another phone-number-connected messaging
238
+ * service.
239
+ */
240
+ export type AuthProviderConfig =
241
+ | Exclude<
242
+ AuthjsProviderConfig,
243
+ CredentialsConfig | ((...args: any) => CredentialsConfig)
244
+ >
245
+ | ConvexCredentialsConfig
246
+ | ((...args: any) => ConvexCredentialsConfig)
247
+ | PhoneConfig
248
+ | ((...args: any) => PhoneConfig);
249
+
250
+ /**
251
+ * Extends the standard Auth.js email provider config
252
+ * to allow additional checks during token verification.
253
+ */
254
+ export interface EmailConfig<
255
+ DataModel extends GenericDataModel = GenericDataModel,
256
+ > extends AuthjsEmailConfig {
257
+ /**
258
+ * Before the token is verified, check other
259
+ * provided parameters.
260
+ *
261
+ * Used to make sure tha OTPs are accompanied
262
+ * with the correct email address.
263
+ */
264
+ authorize?: (
265
+ /**
266
+ * The values passed to the `signIn` function.
267
+ */
268
+ params: Record<string, Value | undefined>,
269
+ account: GenericDoc<DataModel, "account">,
270
+ ) => Promise<void>;
271
+ }
272
+
273
+ /**
274
+ * Configurable options for an email provider config.
275
+ */
276
+ export type EmailUserConfig<
277
+ DataModel extends GenericDataModel = GenericDataModel,
278
+ > = Omit<Partial<EmailConfig<DataModel>>, "options" | "type">;
279
+
280
+ /**
281
+ * Same as email provider config, but verifies
282
+ * phone number instead of the email address.
283
+ */
284
+ export interface PhoneConfig<
285
+ DataModel extends GenericDataModel = GenericDataModel,
286
+ > {
287
+ id: string;
288
+ type: "phone";
289
+ /**
290
+ * Token expiration in seconds.
291
+ */
292
+ maxAge: number;
293
+ /**
294
+ * Send the phone number verification request.
295
+ */
296
+ sendVerificationRequest: (
297
+ params: {
298
+ identifier: string;
299
+ url: string;
300
+ expires: Date;
301
+ provider: PhoneConfig;
302
+ token: string;
303
+ },
304
+ ctx: GenericActionCtxWithAuthConfig<DataModel>,
305
+ ) => Promise<void>;
306
+ /**
307
+ * Defaults to `process.env.AUTH_<PROVIDER_ID>_KEY`.
308
+ */
309
+ apiKey?: string;
310
+ /**
311
+ * Override this to generate a custom token.
312
+ * Note that the tokens are assumed to be cryptographically secure.
313
+ * Any tokens shorter than 24 characters are assumed to not
314
+ * be secure enough on their own, and require providing
315
+ * the original `phone` used in the initial `signIn` call.
316
+ * @returns
317
+ */
318
+ generateVerificationToken?: () => Promise<string>;
319
+ /**
320
+ * Normalize the phone number.
321
+ * @param identifier Passed as `phone` in params of `signIn`.
322
+ * @returns The phone number used in `sendVerificationRequest`.
323
+ */
324
+ normalizeIdentifier?: (identifier: string) => string;
325
+ /**
326
+ * Before the token is verified, check other
327
+ * provided parameters.
328
+ *
329
+ * Used to make sure tha OTPs are accompanied
330
+ * with the correct phone number.
331
+ */
332
+ authorize?: (
333
+ /**
334
+ * The values passed to the `signIn` function.
335
+ */
336
+ params: Record<string, Value | undefined>,
337
+ account: GenericDoc<DataModel, "account">,
338
+ ) => Promise<void>;
339
+ options: PhoneUserConfig<DataModel>;
340
+ }
341
+
342
+ /**
343
+ * Configurable options for a phone provider config.
344
+ */
345
+ export type PhoneUserConfig<
346
+ DataModel extends GenericDataModel = GenericDataModel,
347
+ > = Omit<Partial<PhoneConfig<DataModel>>, "options" | "type">;
348
+
349
+ /**
350
+ * Similar to Auth.js Credentials config.
351
+ */
352
+ export type ConvexCredentialsConfig = ConvexCredentialsUserConfig<any> & {
353
+ type: "credentials";
354
+ id: string;
355
+ };
356
+
357
+ /**
358
+ * Your `ActionCtx` enriched with `ctx.auth.config` field with
359
+ * the config passed to `convexAuth`.
360
+ */
361
+ export type GenericActionCtxWithAuthConfig<DataModel extends GenericDataModel> =
362
+ GenericActionCtx<DataModel> & {
363
+ auth: { config: ConvexAuthMaterializedConfig };
364
+ };
365
+
366
+ /**
367
+ * The config for the Convex Auth library, passed to `convexAuth`,
368
+ * with defaults and initialized providers.
369
+ *
370
+ * See {@link ConvexAuthConfig}
371
+ */
372
+ export type ConvexAuthMaterializedConfig = {
373
+ providers: AuthProviderMaterializedConfig[];
374
+ theme: Theme;
375
+ } & Pick<
376
+ ConvexAuthConfig,
377
+ "component" | "session" | "jwt" | "signIn" | "callbacks"
378
+ >;
379
+
380
+ /**
381
+ * Materialized Auth.js provider config.
382
+ */
383
+ export type AuthProviderMaterializedConfig =
384
+ | OIDCConfig<any>
385
+ | OAuth2Config<any>
386
+ | EmailConfig
387
+ | PhoneConfig
388
+ | ConvexCredentialsConfig;
389
+
390
+ /**
391
+ * Component function references required by core auth runtime.
392
+ */
393
+ export type AuthComponentApi = {
394
+ public: {
395
+ userGetById: FunctionReference<"query", "internal">;
396
+ userFindByVerifiedEmail: FunctionReference<"query", "internal">;
397
+ userFindByVerifiedPhone: FunctionReference<"query", "internal">;
398
+ userInsert: FunctionReference<"mutation", "internal">;
399
+ userUpsert: FunctionReference<"mutation", "internal">;
400
+ userPatch: FunctionReference<"mutation", "internal">;
401
+ accountGet: FunctionReference<"query", "internal">;
402
+ accountGetById: FunctionReference<"query", "internal">;
403
+ accountInsert: FunctionReference<"mutation", "internal">;
404
+ accountPatch: FunctionReference<"mutation", "internal">;
405
+ accountDelete: FunctionReference<"mutation", "internal">;
406
+ sessionCreate: FunctionReference<"mutation", "internal">;
407
+ sessionGetById: FunctionReference<"query", "internal">;
408
+ sessionDelete: FunctionReference<"mutation", "internal">;
409
+ sessionListByUser: FunctionReference<"query", "internal">;
410
+ verifierCreate: FunctionReference<"mutation", "internal">;
411
+ verifierGetById: FunctionReference<"query", "internal">;
412
+ verifierGetBySignature: FunctionReference<"query", "internal">;
413
+ verifierPatch: FunctionReference<"mutation", "internal">;
414
+ verifierDelete: FunctionReference<"mutation", "internal">;
415
+ verificationCodeGetByAccountId: FunctionReference<"query", "internal">;
416
+ verificationCodeGetByCode: FunctionReference<"query", "internal">;
417
+ verificationCodeCreate: FunctionReference<"mutation", "internal">;
418
+ verificationCodeDelete: FunctionReference<"mutation", "internal">;
419
+ verificationGetByAccountId?: FunctionReference<"query", "internal">;
420
+ verificationGetByCode?: FunctionReference<"query", "internal">;
421
+ verificationCreate?: FunctionReference<"mutation", "internal">;
422
+ verificationDelete?: FunctionReference<"mutation", "internal">;
423
+ refreshTokenCreate: FunctionReference<"mutation", "internal">;
424
+ refreshTokenGetById: FunctionReference<"query", "internal">;
425
+ refreshTokenPatch: FunctionReference<"mutation", "internal">;
426
+ refreshTokenGetChildren: FunctionReference<"query", "internal">;
427
+ refreshTokenListBySession: FunctionReference<"query", "internal">;
428
+ refreshTokenDeleteAll: FunctionReference<"mutation", "internal">;
429
+ refreshTokenGetActive: FunctionReference<"query", "internal">;
430
+ tokenCreate?: FunctionReference<"mutation", "internal">;
431
+ tokenGetById?: FunctionReference<"query", "internal">;
432
+ tokenPatch?: FunctionReference<"mutation", "internal">;
433
+ tokenGetChildren?: FunctionReference<"query", "internal">;
434
+ tokenListBySession?: FunctionReference<"query", "internal">;
435
+ tokenDeleteAll?: FunctionReference<"mutation", "internal">;
436
+ tokenGetActive?: FunctionReference<"query", "internal">;
437
+ rateLimitGet: FunctionReference<"query", "internal">;
438
+ rateLimitCreate: FunctionReference<"mutation", "internal">;
439
+ rateLimitPatch: FunctionReference<"mutation", "internal">;
440
+ rateLimitDelete: FunctionReference<"mutation", "internal">;
441
+ limitGet?: FunctionReference<"query", "internal">;
442
+ limitCreate?: FunctionReference<"mutation", "internal">;
443
+ limitPatch?: FunctionReference<"mutation", "internal">;
444
+ limitDelete?: FunctionReference<"mutation", "internal">;
445
+ organizationCreate?: FunctionReference<"mutation", "internal">;
446
+ organizationGet?: FunctionReference<"query", "internal">;
447
+ organizationList?: FunctionReference<"query", "internal">;
448
+ organizationUpdate?: FunctionReference<"mutation", "internal">;
449
+ organizationDelete?: FunctionReference<"mutation", "internal">;
450
+ teamCreate?: FunctionReference<"mutation", "internal">;
451
+ teamGet?: FunctionReference<"query", "internal">;
452
+ teamListByOrganization?: FunctionReference<"query", "internal">;
453
+ teamUpdate?: FunctionReference<"mutation", "internal">;
454
+ teamDelete?: FunctionReference<"mutation", "internal">;
455
+ teamRelationCreate?: FunctionReference<"mutation", "internal">;
456
+ teamRelationGet?: FunctionReference<"query", "internal">;
457
+ teamRelationListByParent?: FunctionReference<"query", "internal">;
458
+ teamRelationDelete?: FunctionReference<"mutation", "internal">;
459
+ memberAdd?: FunctionReference<"mutation", "internal">;
460
+ memberRemove?: FunctionReference<"mutation", "internal">;
461
+ memberList?: FunctionReference<"query", "internal">;
462
+ memberRoleSet?: FunctionReference<"mutation", "internal">;
463
+ memberRoleGet?: FunctionReference<"query", "internal">;
464
+ inviteCreate?: FunctionReference<"mutation", "internal">;
465
+ inviteGet?: FunctionReference<"query", "internal">;
466
+ inviteList?: FunctionReference<"query", "internal">;
467
+ inviteAccept?: FunctionReference<"mutation", "internal">;
468
+ inviteRevoke?: FunctionReference<"mutation", "internal">;
469
+ };
470
+ };
@@ -0,0 +1,12 @@
1
+ export function requireEnv(name: string) {
2
+ const value = process.env[name];
3
+ if (value === undefined) {
4
+ throw new Error(`Missing environment variable \`${name}\``);
5
+ }
6
+ return value;
7
+ }
8
+
9
+ export function isLocalHost(host?: string) {
10
+ return /(localhost|127\.0\.0\.1):\d+/.test(
11
+ host ?? "");
12
+ }