@better-auth/core 1.7.0-beta.3 → 1.7.0-beta.5

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 (188) hide show
  1. package/dist/api/index.d.mts +3 -3
  2. package/dist/context/global.mjs +1 -1
  3. package/dist/db/adapter/factory.mjs +62 -0
  4. package/dist/db/adapter/index.d.mts +35 -1
  5. package/dist/db/adapter/types.d.mts +1 -1
  6. package/dist/db/get-tables.mjs +3 -3
  7. package/dist/db/schema/account.d.mts +1 -1
  8. package/dist/db/schema/account.mjs +1 -1
  9. package/dist/db/type.d.mts +12 -0
  10. package/dist/env/env-impl.mjs +1 -1
  11. package/dist/error/codes.d.mts +6 -0
  12. package/dist/error/codes.mjs +6 -0
  13. package/dist/index.d.mts +2 -2
  14. package/dist/instrumentation/tracer.mjs +1 -1
  15. package/dist/oauth2/authorization-params.d.mts +12 -0
  16. package/dist/oauth2/authorization-params.mjs +12 -0
  17. package/dist/oauth2/basic-credentials.d.mts +30 -0
  18. package/dist/oauth2/basic-credentials.mjs +64 -0
  19. package/dist/oauth2/client-assertion.d.mts +38 -22
  20. package/dist/oauth2/client-assertion.mjs +63 -28
  21. package/dist/oauth2/client-credentials-token.d.mts +19 -40
  22. package/dist/oauth2/client-credentials-token.mjs +18 -29
  23. package/dist/oauth2/create-authorization-url.d.mts +13 -2
  24. package/dist/oauth2/create-authorization-url.mjs +28 -7
  25. package/dist/oauth2/index.d.mts +13 -8
  26. package/dist/oauth2/index.mjs +11 -7
  27. package/dist/oauth2/oauth-provider.d.mts +149 -11
  28. package/dist/oauth2/refresh-access-token.d.mts +20 -40
  29. package/dist/oauth2/refresh-access-token.mjs +20 -33
  30. package/dist/oauth2/scopes.d.mts +76 -0
  31. package/dist/oauth2/scopes.mjs +96 -0
  32. package/dist/oauth2/token-endpoint-auth.d.mts +17 -0
  33. package/dist/oauth2/token-endpoint-auth.mjs +89 -0
  34. package/dist/oauth2/utils.d.mts +9 -1
  35. package/dist/oauth2/utils.mjs +14 -2
  36. package/dist/oauth2/validate-authorization-code.d.mts +17 -52
  37. package/dist/oauth2/validate-authorization-code.mjs +17 -30
  38. package/dist/oauth2/verify-id-token.d.mts +26 -0
  39. package/dist/oauth2/verify-id-token.mjs +62 -0
  40. package/dist/oauth2/verify.d.mts +14 -0
  41. package/dist/oauth2/verify.mjs +38 -12
  42. package/dist/social-providers/apple.d.mts +18 -20
  43. package/dist/social-providers/apple.mjs +15 -28
  44. package/dist/social-providers/atlassian.d.mts +8 -2
  45. package/dist/social-providers/atlassian.mjs +9 -6
  46. package/dist/social-providers/cognito.d.mts +29 -3
  47. package/dist/social-providers/cognito.mjs +30 -34
  48. package/dist/social-providers/discord.d.mts +8 -2
  49. package/dist/social-providers/discord.mjs +20 -6
  50. package/dist/social-providers/dropbox.d.mts +8 -2
  51. package/dist/social-providers/dropbox.mjs +10 -9
  52. package/dist/social-providers/facebook.d.mts +24 -3
  53. package/dist/social-providers/facebook.mjs +51 -24
  54. package/dist/social-providers/figma.d.mts +8 -2
  55. package/dist/social-providers/figma.mjs +8 -7
  56. package/dist/social-providers/github.d.mts +8 -2
  57. package/dist/social-providers/github.mjs +9 -8
  58. package/dist/social-providers/gitlab.d.mts +8 -2
  59. package/dist/social-providers/gitlab.mjs +8 -7
  60. package/dist/social-providers/google.d.mts +32 -4
  61. package/dist/social-providers/google.mjs +26 -29
  62. package/dist/social-providers/huggingface.d.mts +8 -2
  63. package/dist/social-providers/huggingface.mjs +11 -10
  64. package/dist/social-providers/index.d.mts +322 -75
  65. package/dist/social-providers/kakao.d.mts +8 -2
  66. package/dist/social-providers/kakao.mjs +11 -10
  67. package/dist/social-providers/kick.d.mts +8 -2
  68. package/dist/social-providers/kick.mjs +7 -6
  69. package/dist/social-providers/line.d.mts +11 -3
  70. package/dist/social-providers/line.mjs +14 -15
  71. package/dist/social-providers/linear.d.mts +8 -2
  72. package/dist/social-providers/linear.mjs +7 -6
  73. package/dist/social-providers/linkedin.d.mts +8 -2
  74. package/dist/social-providers/linkedin.mjs +12 -11
  75. package/dist/social-providers/microsoft-entra-id.d.mts +33 -7
  76. package/dist/social-providers/microsoft-entra-id.mjs +28 -38
  77. package/dist/social-providers/naver.d.mts +8 -2
  78. package/dist/social-providers/naver.mjs +7 -6
  79. package/dist/social-providers/notion.d.mts +8 -2
  80. package/dist/social-providers/notion.mjs +9 -6
  81. package/dist/social-providers/paybin.d.mts +8 -2
  82. package/dist/social-providers/paybin.mjs +12 -11
  83. package/dist/social-providers/paypal.d.mts +8 -3
  84. package/dist/social-providers/paypal.mjs +10 -14
  85. package/dist/social-providers/polar.d.mts +8 -2
  86. package/dist/social-providers/polar.mjs +11 -10
  87. package/dist/social-providers/railway.d.mts +8 -2
  88. package/dist/social-providers/railway.mjs +11 -10
  89. package/dist/social-providers/reddit.d.mts +8 -2
  90. package/dist/social-providers/reddit.mjs +11 -9
  91. package/dist/social-providers/roblox.d.mts +8 -2
  92. package/dist/social-providers/roblox.mjs +15 -5
  93. package/dist/social-providers/salesforce.d.mts +8 -2
  94. package/dist/social-providers/salesforce.mjs +11 -10
  95. package/dist/social-providers/slack.d.mts +8 -2
  96. package/dist/social-providers/slack.mjs +18 -15
  97. package/dist/social-providers/spotify.d.mts +8 -2
  98. package/dist/social-providers/spotify.mjs +7 -6
  99. package/dist/social-providers/tiktok.d.mts +8 -2
  100. package/dist/social-providers/tiktok.mjs +21 -5
  101. package/dist/social-providers/twitch.d.mts +8 -2
  102. package/dist/social-providers/twitch.mjs +7 -6
  103. package/dist/social-providers/twitter.d.mts +7 -2
  104. package/dist/social-providers/twitter.mjs +11 -10
  105. package/dist/social-providers/vercel.d.mts +8 -2
  106. package/dist/social-providers/vercel.mjs +7 -9
  107. package/dist/social-providers/vk.d.mts +8 -2
  108. package/dist/social-providers/vk.mjs +7 -6
  109. package/dist/social-providers/wechat.d.mts +8 -2
  110. package/dist/social-providers/wechat.mjs +16 -6
  111. package/dist/social-providers/zoom.d.mts +10 -3
  112. package/dist/social-providers/zoom.mjs +14 -15
  113. package/dist/types/context.d.mts +33 -11
  114. package/dist/types/index.d.mts +1 -1
  115. package/dist/types/init-options.d.mts +121 -6
  116. package/dist/utils/ip.d.mts +5 -4
  117. package/dist/utils/ip.mjs +3 -3
  118. package/dist/utils/redirect-uri.d.mts +20 -0
  119. package/dist/utils/redirect-uri.mjs +48 -0
  120. package/dist/utils/string.d.mts +5 -1
  121. package/dist/utils/string.mjs +20 -1
  122. package/dist/utils/url.d.mts +18 -1
  123. package/dist/utils/url.mjs +30 -1
  124. package/package.json +13 -12
  125. package/src/db/adapter/factory.ts +126 -0
  126. package/src/db/adapter/index.ts +32 -0
  127. package/src/db/adapter/types.ts +1 -0
  128. package/src/db/get-tables.ts +8 -3
  129. package/src/db/schema/account.ts +14 -2
  130. package/src/db/type.ts +12 -0
  131. package/src/env/env-impl.ts +1 -2
  132. package/src/error/codes.ts +6 -0
  133. package/src/oauth2/authorization-params.ts +28 -0
  134. package/src/oauth2/basic-credentials.ts +87 -0
  135. package/src/oauth2/client-assertion.ts +131 -58
  136. package/src/oauth2/client-credentials-token.ts +48 -72
  137. package/src/oauth2/create-authorization-url.ts +30 -8
  138. package/src/oauth2/index.ts +42 -10
  139. package/src/oauth2/oauth-provider.ts +161 -12
  140. package/src/oauth2/refresh-access-token.ts +52 -78
  141. package/src/oauth2/scopes.ts +118 -0
  142. package/src/oauth2/token-endpoint-auth.ts +221 -0
  143. package/src/oauth2/utils.ts +21 -5
  144. package/src/oauth2/validate-authorization-code.ts +55 -85
  145. package/src/oauth2/verify-id-token.ts +111 -0
  146. package/src/oauth2/verify.ts +82 -15
  147. package/src/social-providers/apple.ts +32 -45
  148. package/src/social-providers/atlassian.ts +20 -9
  149. package/src/social-providers/cognito.ts +51 -48
  150. package/src/social-providers/discord.ts +37 -22
  151. package/src/social-providers/dropbox.ts +20 -12
  152. package/src/social-providers/facebook.ts +108 -57
  153. package/src/social-providers/figma.ts +21 -10
  154. package/src/social-providers/github.ts +16 -10
  155. package/src/social-providers/gitlab.ts +16 -8
  156. package/src/social-providers/google.ts +67 -46
  157. package/src/social-providers/huggingface.ts +20 -9
  158. package/src/social-providers/kakao.ts +18 -9
  159. package/src/social-providers/kick.ts +20 -8
  160. package/src/social-providers/line.ts +39 -37
  161. package/src/social-providers/linear.ts +20 -7
  162. package/src/social-providers/linkedin.ts +16 -10
  163. package/src/social-providers/microsoft-entra-id.ts +66 -64
  164. package/src/social-providers/naver.ts +14 -7
  165. package/src/social-providers/notion.ts +20 -7
  166. package/src/social-providers/paybin.ts +16 -11
  167. package/src/social-providers/paypal.ts +12 -25
  168. package/src/social-providers/polar.ts +20 -9
  169. package/src/social-providers/railway.ts +20 -9
  170. package/src/social-providers/reddit.ts +22 -10
  171. package/src/social-providers/roblox.ts +31 -15
  172. package/src/social-providers/salesforce.ts +21 -10
  173. package/src/social-providers/slack.ts +31 -16
  174. package/src/social-providers/spotify.ts +20 -7
  175. package/src/social-providers/tiktok.ts +32 -13
  176. package/src/social-providers/twitch.ts +14 -9
  177. package/src/social-providers/twitter.ts +18 -8
  178. package/src/social-providers/vercel.ts +24 -11
  179. package/src/social-providers/vk.ts +20 -7
  180. package/src/social-providers/wechat.ts +28 -8
  181. package/src/social-providers/zoom.ts +28 -19
  182. package/src/types/context.ts +33 -12
  183. package/src/types/index.ts +7 -0
  184. package/src/types/init-options.ts +148 -5
  185. package/src/utils/ip.ts +12 -13
  186. package/src/utils/redirect-uri.ts +54 -0
  187. package/src/utils/string.ts +37 -0
  188. package/src/utils/url.ts +28 -0
@@ -1,26 +1,29 @@
1
+ import { resolveRequestedScopes } from "../oauth2/scopes.mjs";
1
2
  import { createAuthorizationURL } from "../oauth2/create-authorization-url.mjs";
2
3
  import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
3
4
  import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
4
5
  import { betterFetch } from "@better-fetch/fetch";
5
6
  //#region src/social-providers/notion.ts
7
+ const NOTION_DEFAULT_SCOPES = [];
6
8
  const notion = (options) => {
7
9
  const tokenEndpoint = "https://api.notion.com/v1/oauth/token";
8
10
  return {
9
11
  id: "notion",
10
12
  name: "Notion",
11
- createAuthorizationURL({ state, scopes, loginHint, redirectURI }) {
12
- const _scopes = options.disableDefaultScope ? [] : [];
13
- if (options.scope) _scopes.push(...options.scope);
14
- if (scopes) _scopes.push(...scopes);
13
+ callbackPath: "/callback/notion",
14
+ createAuthorizationURL({ state, scopes, loginHint, redirectURI, additionalParams }) {
15
15
  return createAuthorizationURL({
16
16
  id: "notion",
17
17
  options,
18
18
  authorizationEndpoint: "https://api.notion.com/v1/oauth/authorize",
19
- scopes: _scopes,
19
+ scopes: resolveRequestedScopes(options, NOTION_DEFAULT_SCOPES, scopes),
20
20
  state,
21
21
  redirectURI,
22
22
  loginHint,
23
- additionalParams: { owner: "user" }
23
+ additionalParams: {
24
+ ...additionalParams ?? {},
25
+ owner: "user"
26
+ }
24
27
  });
25
28
  },
26
29
  validateAuthorizationCode: async ({ code, redirectURI }) => {
@@ -21,12 +21,14 @@ interface PaybinOptions extends ProviderOptions<PaybinProfile> {
21
21
  declare const paybin: (options: PaybinOptions) => {
22
22
  id: "paybin";
23
23
  name: string;
24
+ callbackPath: string;
24
25
  createAuthorizationURL({
25
26
  state,
26
27
  scopes,
27
28
  codeVerifier,
28
29
  redirectURI,
29
- loginHint
30
+ loginHint,
31
+ additionalParams
30
32
  }: {
31
33
  state: string;
32
34
  codeVerifier: string;
@@ -34,7 +36,11 @@ declare const paybin: (options: PaybinOptions) => {
34
36
  redirectURI: string;
35
37
  display?: string | undefined;
36
38
  loginHint?: string | undefined;
37
- }): Promise<URL>;
39
+ additionalParams?: Record<string, string> | undefined;
40
+ }): Promise<{
41
+ url: URL;
42
+ requestedScopes: string[];
43
+ }>;
38
44
  validateAuthorizationCode: ({
39
45
  code,
40
46
  codeVerifier,
@@ -1,10 +1,16 @@
1
1
  import { BetterAuthError } from "../error/index.mjs";
2
2
  import { logger } from "../env/logger.mjs";
3
+ import { resolveRequestedScopes } from "../oauth2/scopes.mjs";
3
4
  import { createAuthorizationURL } from "../oauth2/create-authorization-url.mjs";
4
5
  import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
5
6
  import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
6
7
  import { decodeJwt } from "jose";
7
8
  //#region src/social-providers/paybin.ts
9
+ const PAYBIN_DEFAULT_SCOPES = [
10
+ "openid",
11
+ "email",
12
+ "profile"
13
+ ];
8
14
  const paybin = (options) => {
9
15
  const issuer = options.issuer || "https://idp.paybin.io";
10
16
  const authorizationEndpoint = `${issuer}/oauth2/authorize`;
@@ -12,29 +18,24 @@ const paybin = (options) => {
12
18
  return {
13
19
  id: "paybin",
14
20
  name: "Paybin",
15
- async createAuthorizationURL({ state, scopes, codeVerifier, redirectURI, loginHint }) {
21
+ callbackPath: "/callback/paybin",
22
+ createAuthorizationURL({ state, scopes, codeVerifier, redirectURI, loginHint, additionalParams }) {
16
23
  if (!options.clientId || !options.clientSecret) {
17
24
  logger.error("Client Id and Client Secret is required for Paybin. Make sure to provide them in the options.");
18
25
  throw new BetterAuthError("CLIENT_ID_AND_SECRET_REQUIRED");
19
26
  }
20
27
  if (!codeVerifier) throw new BetterAuthError("codeVerifier is required for Paybin");
21
- const _scopes = options.disableDefaultScope ? [] : [
22
- "openid",
23
- "email",
24
- "profile"
25
- ];
26
- if (options.scope) _scopes.push(...options.scope);
27
- if (scopes) _scopes.push(...scopes);
28
- return await createAuthorizationURL({
28
+ return createAuthorizationURL({
29
29
  id: "paybin",
30
30
  options,
31
31
  authorizationEndpoint,
32
- scopes: _scopes,
32
+ scopes: resolveRequestedScopes(options, PAYBIN_DEFAULT_SCOPES, scopes),
33
33
  state,
34
34
  codeVerifier,
35
35
  redirectURI,
36
36
  prompt: options.prompt,
37
- loginHint
37
+ loginHint,
38
+ additionalParams
38
39
  });
39
40
  },
40
41
  validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
@@ -51,10 +51,12 @@ interface PayPalOptions extends ProviderOptions<PayPalProfile> {
51
51
  declare const paypal: (options: PayPalOptions) => {
52
52
  id: "paypal";
53
53
  name: string;
54
+ callbackPath: string;
54
55
  createAuthorizationURL({
55
56
  state,
56
57
  codeVerifier,
57
- redirectURI
58
+ redirectURI,
59
+ additionalParams
58
60
  }: {
59
61
  state: string;
60
62
  codeVerifier: string;
@@ -62,7 +64,11 @@ declare const paypal: (options: PayPalOptions) => {
62
64
  redirectURI: string;
63
65
  display?: string | undefined;
64
66
  loginHint?: string | undefined;
65
- }): Promise<URL>;
67
+ additionalParams?: Record<string, string> | undefined;
68
+ }): Promise<{
69
+ url: URL;
70
+ requestedScopes: string[];
71
+ }>;
66
72
  validateAuthorizationCode: ({
67
73
  code,
68
74
  redirectURI
@@ -82,7 +88,6 @@ declare const paypal: (options: PayPalOptions) => {
82
88
  refreshToken: any;
83
89
  accessTokenExpiresAt: Date | undefined;
84
90
  }>);
85
- verifyIdToken(token: string, nonce: string | undefined): Promise<boolean>;
86
91
  getUserInfo(token: OAuth2Tokens & {
87
92
  user?: {
88
93
  name?: {
@@ -1,7 +1,6 @@
1
1
  import { BetterAuthError } from "../error/index.mjs";
2
2
  import { logger } from "../env/logger.mjs";
3
3
  import { createAuthorizationURL } from "../oauth2/create-authorization-url.mjs";
4
- import { decodeJwt } from "jose";
5
4
  import { base64 } from "@better-auth/utils/base64";
6
5
  import { betterFetch } from "@better-fetch/fetch";
7
6
  //#region src/social-providers/paypal.ts
@@ -13,12 +12,18 @@ const paypal = (options) => {
13
12
  return {
14
13
  id: "paypal",
15
14
  name: "PayPal",
16
- async createAuthorizationURL({ state, codeVerifier, redirectURI }) {
15
+ callbackPath: "/callback/paypal",
16
+ createAuthorizationURL({ state, codeVerifier, redirectURI, additionalParams }) {
17
17
  if (!options.clientId || !options.clientSecret) {
18
18
  logger.error("Client Id and Client Secret is required for PayPal. Make sure to provide them in the options.");
19
19
  throw new BetterAuthError("CLIENT_ID_AND_SECRET_REQUIRED");
20
20
  }
21
- return await createAuthorizationURL({
21
+ /**
22
+ * Log in with PayPal doesn't use traditional OAuth2 scopes
23
+ * Instead, permissions are configured in the PayPal Developer Dashboard
24
+ * We don't pass any scopes to avoid "invalid scope" errors
25
+ **/
26
+ return createAuthorizationURL({
22
27
  id: "paypal",
23
28
  options,
24
29
  authorizationEndpoint,
@@ -26,7 +31,8 @@ const paypal = (options) => {
26
31
  state,
27
32
  codeVerifier,
28
33
  redirectURI,
29
- prompt: options.prompt
34
+ prompt: options.prompt,
35
+ additionalParams
30
36
  });
31
37
  },
32
38
  validateAuthorizationCode: async ({ code, redirectURI }) => {
@@ -90,16 +96,6 @@ const paypal = (options) => {
90
96
  throw new BetterAuthError("FAILED_TO_REFRESH_ACCESS_TOKEN");
91
97
  }
92
98
  },
93
- async verifyIdToken(token, nonce) {
94
- if (options.disableIdTokenSignIn) return false;
95
- if (options.verifyIdToken) return options.verifyIdToken(token, nonce);
96
- try {
97
- return !!decodeJwt(token).sub;
98
- } catch (error) {
99
- logger.error("Failed to verify PayPal ID token:", error);
100
- return false;
101
- }
102
- },
103
99
  async getUserInfo(token) {
104
100
  if (options.getUserInfo) return options.getUserInfo(token);
105
101
  if (!token.accessToken) {
@@ -25,11 +25,13 @@ interface PolarOptions extends ProviderOptions<PolarProfile> {}
25
25
  declare const polar: (options: PolarOptions) => {
26
26
  id: "polar";
27
27
  name: string;
28
+ callbackPath: string;
28
29
  createAuthorizationURL({
29
30
  state,
30
31
  scopes,
31
32
  codeVerifier,
32
- redirectURI
33
+ redirectURI,
34
+ additionalParams
33
35
  }: {
34
36
  state: string;
35
37
  codeVerifier: string;
@@ -37,7 +39,11 @@ declare const polar: (options: PolarOptions) => {
37
39
  redirectURI: string;
38
40
  display?: string | undefined;
39
41
  loginHint?: string | undefined;
40
- }): Promise<URL>;
42
+ additionalParams?: Record<string, string> | undefined;
43
+ }): Promise<{
44
+ url: URL;
45
+ requestedScopes: string[];
46
+ }>;
41
47
  validateAuthorizationCode: ({
42
48
  code,
43
49
  codeVerifier,
@@ -1,30 +1,31 @@
1
+ import { resolveRequestedScopes } from "../oauth2/scopes.mjs";
1
2
  import { createAuthorizationURL } from "../oauth2/create-authorization-url.mjs";
2
3
  import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
3
4
  import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
4
5
  import { betterFetch } from "@better-fetch/fetch";
5
6
  //#region src/social-providers/polar.ts
7
+ const POLAR_DEFAULT_SCOPES = [
8
+ "openid",
9
+ "profile",
10
+ "email"
11
+ ];
6
12
  const polar = (options) => {
7
13
  const tokenEndpoint = "https://api.polar.sh/v1/oauth2/token";
8
14
  return {
9
15
  id: "polar",
10
16
  name: "Polar",
11
- createAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {
12
- const _scopes = options.disableDefaultScope ? [] : [
13
- "openid",
14
- "profile",
15
- "email"
16
- ];
17
- if (options.scope) _scopes.push(...options.scope);
18
- if (scopes) _scopes.push(...scopes);
17
+ callbackPath: "/callback/polar",
18
+ createAuthorizationURL({ state, scopes, codeVerifier, redirectURI, additionalParams }) {
19
19
  return createAuthorizationURL({
20
20
  id: "polar",
21
21
  options,
22
22
  authorizationEndpoint: "https://polar.sh/oauth2/authorize",
23
- scopes: _scopes,
23
+ scopes: resolveRequestedScopes(options, POLAR_DEFAULT_SCOPES, scopes),
24
24
  state,
25
25
  codeVerifier,
26
26
  redirectURI,
27
- prompt: options.prompt
27
+ prompt: options.prompt,
28
+ additionalParams
28
29
  });
29
30
  },
30
31
  validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
@@ -16,11 +16,13 @@ interface RailwayOptions extends ProviderOptions<RailwayProfile> {
16
16
  declare const railway: (options: RailwayOptions) => {
17
17
  id: "railway";
18
18
  name: string;
19
+ callbackPath: string;
19
20
  createAuthorizationURL({
20
21
  state,
21
22
  scopes,
22
23
  codeVerifier,
23
- redirectURI
24
+ redirectURI,
25
+ additionalParams
24
26
  }: {
25
27
  state: string;
26
28
  codeVerifier: string;
@@ -28,7 +30,11 @@ declare const railway: (options: RailwayOptions) => {
28
30
  redirectURI: string;
29
31
  display?: string | undefined;
30
32
  loginHint?: string | undefined;
31
- }): Promise<URL>;
33
+ additionalParams?: Record<string, string> | undefined;
34
+ }): Promise<{
35
+ url: URL;
36
+ requestedScopes: string[];
37
+ }>;
32
38
  validateAuthorizationCode: ({
33
39
  code,
34
40
  codeVerifier,
@@ -1,3 +1,4 @@
1
+ import { resolveRequestedScopes } from "../oauth2/scopes.mjs";
1
2
  import { createAuthorizationURL } from "../oauth2/create-authorization-url.mjs";
2
3
  import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
3
4
  import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
@@ -6,26 +7,26 @@ import { betterFetch } from "@better-fetch/fetch";
6
7
  const authorizationEndpoint = "https://backboard.railway.com/oauth/auth";
7
8
  const tokenEndpoint = "https://backboard.railway.com/oauth/token";
8
9
  const userinfoEndpoint = "https://backboard.railway.com/oauth/me";
10
+ const RAILWAY_DEFAULT_SCOPES = [
11
+ "openid",
12
+ "email",
13
+ "profile"
14
+ ];
9
15
  const railway = (options) => {
10
16
  return {
11
17
  id: "railway",
12
18
  name: "Railway",
13
- createAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {
14
- const _scopes = options.disableDefaultScope ? [] : [
15
- "openid",
16
- "email",
17
- "profile"
18
- ];
19
- if (options.scope) _scopes.push(...options.scope);
20
- if (scopes) _scopes.push(...scopes);
19
+ callbackPath: "/callback/railway",
20
+ async createAuthorizationURL({ state, scopes, codeVerifier, redirectURI, additionalParams }) {
21
21
  return createAuthorizationURL({
22
22
  id: "railway",
23
23
  options,
24
24
  authorizationEndpoint,
25
- scopes: _scopes,
25
+ scopes: resolveRequestedScopes(options, RAILWAY_DEFAULT_SCOPES, scopes),
26
26
  state,
27
27
  codeVerifier,
28
- redirectURI
28
+ redirectURI,
29
+ additionalParams
29
30
  });
30
31
  },
31
32
  validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
@@ -15,10 +15,12 @@ interface RedditOptions extends ProviderOptions<RedditProfile> {
15
15
  declare const reddit: (options: RedditOptions) => {
16
16
  id: "reddit";
17
17
  name: string;
18
+ callbackPath: string;
18
19
  createAuthorizationURL({
19
20
  state,
20
21
  scopes,
21
- redirectURI
22
+ redirectURI,
23
+ additionalParams
22
24
  }: {
23
25
  state: string;
24
26
  codeVerifier: string;
@@ -26,7 +28,11 @@ declare const reddit: (options: RedditOptions) => {
26
28
  redirectURI: string;
27
29
  display?: string | undefined;
28
30
  loginHint?: string | undefined;
29
- }): Promise<URL>;
31
+ additionalParams?: Record<string, string> | undefined;
32
+ }): Promise<{
33
+ url: URL;
34
+ requestedScopes: string[];
35
+ }>;
30
36
  validateAuthorizationCode: ({
31
37
  code,
32
38
  redirectURI
@@ -1,25 +1,26 @@
1
+ import { resolveRequestedScopes } from "../oauth2/scopes.mjs";
1
2
  import { getOAuth2Tokens } from "../oauth2/utils.mjs";
2
3
  import { createAuthorizationURL } from "../oauth2/create-authorization-url.mjs";
3
4
  import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
4
5
  import { base64 } from "@better-auth/utils/base64";
5
6
  import { betterFetch } from "@better-fetch/fetch";
6
7
  //#region src/social-providers/reddit.ts
8
+ const REDDIT_DEFAULT_SCOPES = ["identity"];
7
9
  const reddit = (options) => {
8
10
  return {
9
11
  id: "reddit",
10
12
  name: "Reddit",
11
- createAuthorizationURL({ state, scopes, redirectURI }) {
12
- const _scopes = options.disableDefaultScope ? [] : ["identity"];
13
- if (options.scope) _scopes.push(...options.scope);
14
- if (scopes) _scopes.push(...scopes);
13
+ callbackPath: "/callback/reddit",
14
+ async createAuthorizationURL({ state, scopes, redirectURI, additionalParams }) {
15
15
  return createAuthorizationURL({
16
16
  id: "reddit",
17
17
  options,
18
18
  authorizationEndpoint: "https://www.reddit.com/api/v1/authorize",
19
- scopes: _scopes,
19
+ scopes: resolveRequestedScopes(options, REDDIT_DEFAULT_SCOPES, scopes),
20
20
  state,
21
21
  redirectURI,
22
- duration: options.duration
22
+ duration: options.duration,
23
+ additionalParams
23
24
  });
24
25
  },
25
26
  validateAuthorizationCode: async ({ code, redirectURI }) => {
@@ -61,14 +62,15 @@ const reddit = (options) => {
61
62
  } });
62
63
  if (error) return null;
63
64
  const userMap = await options.mapProfileToUser?.(profile);
65
+ const email = userMap?.email || `${profile.id}@reddit.com`;
64
66
  return {
65
67
  user: {
66
68
  id: profile.id,
67
69
  name: profile.name,
68
- email: profile.oauth_client_id,
69
- emailVerified: profile.has_verified_email,
70
70
  image: profile.icon_img?.split("?")[0],
71
- ...userMap
71
+ ...userMap,
72
+ email,
73
+ emailVerified: userMap?.emailVerified ?? false
72
74
  },
73
75
  data: profile
74
76
  };
@@ -23,10 +23,12 @@ interface RobloxOptions extends ProviderOptions<RobloxProfile> {
23
23
  declare const roblox: (options: RobloxOptions) => {
24
24
  id: "roblox";
25
25
  name: string;
26
+ callbackPath: string;
26
27
  createAuthorizationURL({
27
28
  state,
28
29
  scopes,
29
- redirectURI
30
+ redirectURI,
31
+ additionalParams
30
32
  }: {
31
33
  state: string;
32
34
  codeVerifier: string;
@@ -34,7 +36,11 @@ declare const roblox: (options: RobloxOptions) => {
34
36
  redirectURI: string;
35
37
  display?: string | undefined;
36
38
  loginHint?: string | undefined;
37
- }): URL;
39
+ additionalParams?: Record<string, string> | undefined;
40
+ }): Promise<{
41
+ url: URL;
42
+ requestedScopes: string[];
43
+ }>;
38
44
  validateAuthorizationCode: ({
39
45
  code,
40
46
  redirectURI
@@ -1,17 +1,27 @@
1
+ import { resolveRequestedScopes } from "../oauth2/scopes.mjs";
2
+ import { createAuthorizationURL } from "../oauth2/create-authorization-url.mjs";
1
3
  import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
2
4
  import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
3
5
  import { betterFetch } from "@better-fetch/fetch";
4
6
  //#region src/social-providers/roblox.ts
7
+ const ROBLOX_DEFAULT_SCOPES = ["openid", "profile"];
5
8
  const roblox = (options) => {
6
9
  const tokenEndpoint = "https://apis.roblox.com/oauth/v1/token";
7
10
  return {
8
11
  id: "roblox",
9
12
  name: "Roblox",
10
- createAuthorizationURL({ state, scopes, redirectURI }) {
11
- const _scopes = options.disableDefaultScope ? [] : ["openid", "profile"];
12
- if (options.scope) _scopes.push(...options.scope);
13
- if (scopes) _scopes.push(...scopes);
14
- return new URL(`https://apis.roblox.com/oauth/v1/authorize?scope=${_scopes.join("+")}&response_type=code&client_id=${options.clientId}&redirect_uri=${encodeURIComponent(options.redirectURI || redirectURI)}&state=${state}&prompt=${options.prompt || "select_account consent"}`);
13
+ callbackPath: "/callback/roblox",
14
+ async createAuthorizationURL({ state, scopes, redirectURI, additionalParams }) {
15
+ return createAuthorizationURL({
16
+ id: "roblox",
17
+ options,
18
+ authorizationEndpoint: "https://apis.roblox.com/oauth/v1/authorize",
19
+ scopes: resolveRequestedScopes(options, ROBLOX_DEFAULT_SCOPES, scopes),
20
+ state,
21
+ redirectURI,
22
+ prompt: options.prompt || "select_account consent",
23
+ additionalParams
24
+ });
15
25
  },
16
26
  validateAuthorizationCode: async ({ code, redirectURI }) => {
17
27
  return validateAuthorizationCode({
@@ -30,11 +30,13 @@ interface SalesforceOptions extends ProviderOptions<SalesforceProfile> {
30
30
  declare const salesforce: (options: SalesforceOptions) => {
31
31
  id: "salesforce";
32
32
  name: string;
33
+ callbackPath: string;
33
34
  createAuthorizationURL({
34
35
  state,
35
36
  scopes,
36
37
  codeVerifier,
37
- redirectURI
38
+ redirectURI,
39
+ additionalParams
38
40
  }: {
39
41
  state: string;
40
42
  codeVerifier: string;
@@ -42,7 +44,11 @@ declare const salesforce: (options: SalesforceOptions) => {
42
44
  redirectURI: string;
43
45
  display?: string | undefined;
44
46
  loginHint?: string | undefined;
45
- }): Promise<URL>;
47
+ additionalParams?: Record<string, string> | undefined;
48
+ }): Promise<{
49
+ url: URL;
50
+ requestedScopes: string[];
51
+ }>;
46
52
  validateAuthorizationCode: ({
47
53
  code,
48
54
  codeVerifier,
@@ -1,10 +1,16 @@
1
1
  import { BetterAuthError } from "../error/index.mjs";
2
2
  import { logger } from "../env/logger.mjs";
3
+ import { resolveRequestedScopes } from "../oauth2/scopes.mjs";
3
4
  import { createAuthorizationURL } from "../oauth2/create-authorization-url.mjs";
4
5
  import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
5
6
  import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
6
7
  import { betterFetch } from "@better-fetch/fetch";
7
8
  //#region src/social-providers/salesforce.ts
9
+ const SALESFORCE_DEFAULT_SCOPES = [
10
+ "openid",
11
+ "email",
12
+ "profile"
13
+ ];
8
14
  const salesforce = (options) => {
9
15
  const isSandbox = (options.environment ?? "production") === "sandbox";
10
16
  const authorizationEndpoint = options.loginUrl ? `https://${options.loginUrl}/services/oauth2/authorize` : isSandbox ? "https://test.salesforce.com/services/oauth2/authorize" : "https://login.salesforce.com/services/oauth2/authorize";
@@ -13,27 +19,22 @@ const salesforce = (options) => {
13
19
  return {
14
20
  id: "salesforce",
15
21
  name: "Salesforce",
16
- async createAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {
22
+ callbackPath: "/callback/salesforce",
23
+ async createAuthorizationURL({ state, scopes, codeVerifier, redirectURI, additionalParams }) {
17
24
  if (!options.clientId || !options.clientSecret) {
18
25
  logger.error("Client Id and Client Secret are required for Salesforce. Make sure to provide them in the options.");
19
26
  throw new BetterAuthError("CLIENT_ID_AND_SECRET_REQUIRED");
20
27
  }
21
28
  if (!codeVerifier) throw new BetterAuthError("codeVerifier is required for Salesforce");
22
- const _scopes = options.disableDefaultScope ? [] : [
23
- "openid",
24
- "email",
25
- "profile"
26
- ];
27
- if (options.scope) _scopes.push(...options.scope);
28
- if (scopes) _scopes.push(...scopes);
29
29
  return createAuthorizationURL({
30
30
  id: "salesforce",
31
31
  options,
32
32
  authorizationEndpoint,
33
- scopes: _scopes,
33
+ scopes: resolveRequestedScopes(options, SALESFORCE_DEFAULT_SCOPES, scopes),
34
34
  state,
35
35
  codeVerifier,
36
- redirectURI: options.redirectURI || redirectURI
36
+ redirectURI: options.redirectURI || redirectURI,
37
+ additionalParams
37
38
  });
38
39
  },
39
40
  validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
@@ -36,10 +36,12 @@ interface SlackOptions extends ProviderOptions<SlackProfile> {
36
36
  declare const slack: (options: SlackOptions) => {
37
37
  id: "slack";
38
38
  name: string;
39
+ callbackPath: string;
39
40
  createAuthorizationURL({
40
41
  state,
41
42
  scopes,
42
- redirectURI
43
+ redirectURI,
44
+ additionalParams
43
45
  }: {
44
46
  state: string;
45
47
  codeVerifier: string;
@@ -47,7 +49,11 @@ declare const slack: (options: SlackOptions) => {
47
49
  redirectURI: string;
48
50
  display?: string | undefined;
49
51
  loginHint?: string | undefined;
50
- }): URL;
52
+ additionalParams?: Record<string, string> | undefined;
53
+ }): Promise<{
54
+ url: URL;
55
+ requestedScopes: string[];
56
+ }>;
51
57
  validateAuthorizationCode: ({
52
58
  code,
53
59
  redirectURI
@@ -1,27 +1,30 @@
1
+ import { resolveRequestedScopes } from "../oauth2/scopes.mjs";
2
+ import { createAuthorizationURL } from "../oauth2/create-authorization-url.mjs";
1
3
  import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
2
4
  import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
3
5
  import { betterFetch } from "@better-fetch/fetch";
4
6
  //#region src/social-providers/slack.ts
7
+ const SLACK_DEFAULT_SCOPES = [
8
+ "openid",
9
+ "profile",
10
+ "email"
11
+ ];
5
12
  const slack = (options) => {
6
13
  const tokenEndpoint = "https://slack.com/api/openid.connect.token";
7
14
  return {
8
15
  id: "slack",
9
16
  name: "Slack",
10
- createAuthorizationURL({ state, scopes, redirectURI }) {
11
- const _scopes = options.disableDefaultScope ? [] : [
12
- "openid",
13
- "profile",
14
- "email"
15
- ];
16
- if (scopes) _scopes.push(...scopes);
17
- if (options.scope) _scopes.push(...options.scope);
18
- const url = new URL("https://slack.com/openid/connect/authorize");
19
- url.searchParams.set("scope", _scopes.join(" "));
20
- url.searchParams.set("response_type", "code");
21
- url.searchParams.set("client_id", options.clientId);
22
- url.searchParams.set("redirect_uri", options.redirectURI || redirectURI);
23
- url.searchParams.set("state", state);
24
- return url;
17
+ callbackPath: "/callback/slack",
18
+ async createAuthorizationURL({ state, scopes, redirectURI, additionalParams }) {
19
+ return createAuthorizationURL({
20
+ id: "slack",
21
+ options,
22
+ authorizationEndpoint: "https://slack.com/openid/connect/authorize",
23
+ scopes: resolveRequestedScopes(options, SLACK_DEFAULT_SCOPES, scopes),
24
+ state,
25
+ redirectURI,
26
+ additionalParams
27
+ });
25
28
  },
26
29
  validateAuthorizationCode: async ({ code, redirectURI }) => {
27
30
  return validateAuthorizationCode({