@better-auth/core 1.7.0-beta.6 → 1.7.0-beta.8

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 (142) hide show
  1. package/dist/api/index.d.mts +3 -3
  2. package/dist/context/global.mjs +1 -1
  3. package/dist/db/get-tables.mjs +3 -3
  4. package/dist/db/schema/account.d.mts +1 -1
  5. package/dist/db/schema/account.mjs +1 -1
  6. package/dist/error/codes.d.mts +0 -5
  7. package/dist/error/codes.mjs +0 -5
  8. package/dist/instrumentation/tracer.mjs +1 -1
  9. package/dist/oauth2/create-authorization-url.d.mts +4 -5
  10. package/dist/oauth2/create-authorization-url.mjs +4 -5
  11. package/dist/oauth2/index.d.mts +3 -4
  12. package/dist/oauth2/index.mjs +2 -3
  13. package/dist/oauth2/oauth-provider.d.mts +44 -48
  14. package/dist/oauth2/refresh-access-token.mjs +17 -2
  15. package/dist/oauth2/utils.d.mts +6 -1
  16. package/dist/oauth2/utils.mjs +24 -2
  17. package/dist/oauth2/verify-id-token.d.mts +6 -5
  18. package/dist/oauth2/verify-id-token.mjs +2 -2
  19. package/dist/social-providers/apple.d.mts +3 -5
  20. package/dist/social-providers/apple.mjs +5 -5
  21. package/dist/social-providers/atlassian.d.mts +3 -5
  22. package/dist/social-providers/atlassian.mjs +4 -4
  23. package/dist/social-providers/cognito.d.mts +3 -5
  24. package/dist/social-providers/cognito.mjs +11 -18
  25. package/dist/social-providers/discord.d.mts +3 -5
  26. package/dist/social-providers/discord.mjs +6 -7
  27. package/dist/social-providers/dropbox.d.mts +3 -5
  28. package/dist/social-providers/dropbox.mjs +5 -5
  29. package/dist/social-providers/facebook.d.mts +3 -5
  30. package/dist/social-providers/facebook.mjs +5 -5
  31. package/dist/social-providers/figma.d.mts +3 -5
  32. package/dist/social-providers/figma.mjs +5 -5
  33. package/dist/social-providers/github.d.mts +3 -5
  34. package/dist/social-providers/github.mjs +4 -4
  35. package/dist/social-providers/gitlab.d.mts +3 -5
  36. package/dist/social-providers/gitlab.mjs +6 -6
  37. package/dist/social-providers/google.d.mts +10 -10
  38. package/dist/social-providers/google.mjs +12 -13
  39. package/dist/social-providers/huggingface.d.mts +3 -5
  40. package/dist/social-providers/huggingface.mjs +8 -8
  41. package/dist/social-providers/index.d.mts +105 -177
  42. package/dist/social-providers/kakao.d.mts +3 -5
  43. package/dist/social-providers/kakao.mjs +8 -8
  44. package/dist/social-providers/kick.d.mts +3 -5
  45. package/dist/social-providers/kick.mjs +4 -4
  46. package/dist/social-providers/line.d.mts +3 -5
  47. package/dist/social-providers/line.mjs +10 -10
  48. package/dist/social-providers/linear.d.mts +3 -5
  49. package/dist/social-providers/linear.mjs +4 -4
  50. package/dist/social-providers/linkedin.d.mts +3 -5
  51. package/dist/social-providers/linkedin.mjs +10 -10
  52. package/dist/social-providers/microsoft-entra-id.d.mts +3 -5
  53. package/dist/social-providers/microsoft-entra-id.mjs +10 -11
  54. package/dist/social-providers/naver.d.mts +3 -5
  55. package/dist/social-providers/naver.mjs +4 -4
  56. package/dist/social-providers/notion.d.mts +3 -5
  57. package/dist/social-providers/notion.mjs +4 -4
  58. package/dist/social-providers/paybin.d.mts +3 -5
  59. package/dist/social-providers/paybin.mjs +10 -10
  60. package/dist/social-providers/paypal.d.mts +3 -5
  61. package/dist/social-providers/paypal.mjs +2 -8
  62. package/dist/social-providers/polar.d.mts +3 -5
  63. package/dist/social-providers/polar.mjs +8 -8
  64. package/dist/social-providers/railway.d.mts +3 -5
  65. package/dist/social-providers/railway.mjs +9 -9
  66. package/dist/social-providers/reddit.d.mts +3 -5
  67. package/dist/social-providers/reddit.mjs +5 -5
  68. package/dist/social-providers/roblox.d.mts +3 -5
  69. package/dist/social-providers/roblox.mjs +5 -5
  70. package/dist/social-providers/salesforce.d.mts +3 -5
  71. package/dist/social-providers/salesforce.mjs +8 -8
  72. package/dist/social-providers/slack.d.mts +3 -5
  73. package/dist/social-providers/slack.mjs +9 -9
  74. package/dist/social-providers/spotify.d.mts +3 -5
  75. package/dist/social-providers/spotify.mjs +5 -5
  76. package/dist/social-providers/tiktok.d.mts +3 -5
  77. package/dist/social-providers/tiktok.mjs +5 -9
  78. package/dist/social-providers/twitch.d.mts +3 -5
  79. package/dist/social-providers/twitch.mjs +4 -4
  80. package/dist/social-providers/twitter.d.mts +3 -5
  81. package/dist/social-providers/twitter.mjs +9 -9
  82. package/dist/social-providers/vercel.d.mts +3 -5
  83. package/dist/social-providers/vercel.mjs +7 -4
  84. package/dist/social-providers/vk.d.mts +3 -5
  85. package/dist/social-providers/vk.mjs +5 -5
  86. package/dist/social-providers/wechat.d.mts +3 -5
  87. package/dist/social-providers/wechat.mjs +5 -9
  88. package/dist/social-providers/zoom.d.mts +3 -6
  89. package/dist/social-providers/zoom.mjs +9 -15
  90. package/dist/types/context.d.mts +6 -2
  91. package/dist/utils/host.d.mts +1 -1
  92. package/dist/utils/host.mjs +3 -0
  93. package/package.json +1 -1
  94. package/src/db/get-tables.ts +3 -8
  95. package/src/db/schema/account.ts +5 -14
  96. package/src/error/codes.ts +0 -5
  97. package/src/oauth2/create-authorization-url.ts +5 -1
  98. package/src/oauth2/index.ts +3 -12
  99. package/src/oauth2/oauth-provider.ts +46 -53
  100. package/src/oauth2/refresh-access-token.ts +30 -5
  101. package/src/oauth2/utils.ts +39 -1
  102. package/src/oauth2/verify-id-token.ts +9 -5
  103. package/src/social-providers/apple.ts +8 -13
  104. package/src/social-providers/atlassian.ts +8 -12
  105. package/src/social-providers/cognito.ts +11 -18
  106. package/src/social-providers/discord.ts +8 -19
  107. package/src/social-providers/dropbox.ts +7 -13
  108. package/src/social-providers/facebook.ts +9 -13
  109. package/src/social-providers/figma.ts +9 -13
  110. package/src/social-providers/github.ts +8 -12
  111. package/src/social-providers/gitlab.ts +8 -14
  112. package/src/social-providers/google.ts +23 -29
  113. package/src/social-providers/huggingface.ts +8 -12
  114. package/src/social-providers/kakao.ts +8 -16
  115. package/src/social-providers/kick.ts +7 -12
  116. package/src/social-providers/line.ts +10 -14
  117. package/src/social-providers/linear.ts +6 -12
  118. package/src/social-providers/linkedin.ts +10 -14
  119. package/src/social-providers/microsoft-entra-id.ts +8 -18
  120. package/src/social-providers/naver.ts +6 -12
  121. package/src/social-providers/notion.ts +6 -12
  122. package/src/social-providers/paybin.ts +11 -14
  123. package/src/social-providers/paypal.ts +8 -6
  124. package/src/social-providers/polar.ts +8 -12
  125. package/src/social-providers/railway.ts +9 -13
  126. package/src/social-providers/reddit.ts +7 -18
  127. package/src/social-providers/roblox.ts +7 -18
  128. package/src/social-providers/salesforce.ts +8 -12
  129. package/src/social-providers/slack.ts +9 -18
  130. package/src/social-providers/spotify.ts +7 -13
  131. package/src/social-providers/tiktok.ts +7 -13
  132. package/src/social-providers/twitch.ts +8 -12
  133. package/src/social-providers/twitter.ts +8 -17
  134. package/src/social-providers/vercel.ts +10 -16
  135. package/src/social-providers/vk.ts +7 -13
  136. package/src/social-providers/wechat.ts +8 -20
  137. package/src/social-providers/zoom.ts +6 -19
  138. package/src/types/context.ts +8 -2
  139. package/src/utils/host.ts +10 -1
  140. package/dist/oauth2/scopes.d.mts +0 -76
  141. package/dist/oauth2/scopes.mjs +0 -96
  142. package/src/oauth2/scopes.ts +0 -118
@@ -1,9 +1,8 @@
1
1
  import { betterFetch } from "@better-fetch/fetch";
2
- import type { ProviderOptions, UpstreamProvider } from "../oauth2";
2
+ import type { OAuthProvider, ProviderOptions } from "../oauth2";
3
3
  import {
4
4
  createAuthorizationURL,
5
5
  refreshAccessToken,
6
- resolveRequestedScopes,
7
6
  validateAuthorizationCode,
8
7
  } from "../oauth2";
9
8
 
@@ -74,8 +73,6 @@ const issuerToEndpoints = (issuer?: string | undefined) => {
74
73
  };
75
74
  };
76
75
 
77
- const GITLAB_DEFAULT_SCOPES = ["read_user"];
78
-
79
76
  export const gitlab = (options: GitlabOptions) => {
80
77
  const { authorizationEndpoint, tokenEndpoint, userinfoEndpoint } =
81
78
  issuerToEndpoints(options.issuer);
@@ -84,8 +81,7 @@ export const gitlab = (options: GitlabOptions) => {
84
81
  return {
85
82
  id: issuerId,
86
83
  name: issuerName,
87
- callbackPath: "/callback/gitlab",
88
- createAuthorizationURL: ({
84
+ createAuthorizationURL: async ({
89
85
  state,
90
86
  scopes,
91
87
  codeVerifier,
@@ -93,16 +89,14 @@ export const gitlab = (options: GitlabOptions) => {
93
89
  redirectURI,
94
90
  additionalParams,
95
91
  }) => {
96
- const requestedScopes = resolveRequestedScopes(
97
- options,
98
- GITLAB_DEFAULT_SCOPES,
99
- scopes,
100
- );
101
- return createAuthorizationURL({
92
+ const _scopes = options.disableDefaultScope ? [] : ["read_user"];
93
+ if (options.scope) _scopes.push(...options.scope);
94
+ if (scopes) _scopes.push(...scopes);
95
+ return await createAuthorizationURL({
102
96
  id: issuerId,
103
97
  options,
104
98
  authorizationEndpoint,
105
- scopes: requestedScopes,
99
+ scopes: _scopes,
106
100
  state,
107
101
  redirectURI,
108
102
  codeVerifier,
@@ -159,5 +153,5 @@ export const gitlab = (options: GitlabOptions) => {
159
153
  };
160
154
  },
161
155
  options,
162
- } satisfies UpstreamProvider<GitlabProfile>;
156
+ } satisfies OAuthProvider<GitlabProfile>;
163
157
  };
@@ -2,12 +2,11 @@ import { betterFetch } from "@better-fetch/fetch";
2
2
  import { decodeJwt, importJWK } from "jose";
3
3
  import { logger } from "../env";
4
4
  import { APIError, BetterAuthError } from "../error";
5
- import type { ProviderOptions, UpstreamProvider } from "../oauth2";
5
+ import type { OAuthProvider, ProviderOptions } from "../oauth2";
6
6
  import {
7
7
  createAuthorizationURL,
8
8
  getPrimaryClientId,
9
9
  refreshAccessToken,
10
- resolveRequestedScopes,
11
10
  validateAuthorizationCode,
12
11
  } from "../oauth2";
13
12
 
@@ -58,24 +57,22 @@ export interface GoogleOptions extends ProviderOptions<GoogleProfile> {
58
57
  */
59
58
  hd?: string | undefined;
60
59
  /**
61
- * Enable incremental authorization via Google's `include_granted_scopes`
62
- * parameter. When enabled, Google reports the user's full granted scope set
63
- * in the token response.
60
+ * Whether to send `include_granted_scopes=true` to Google's authorization
61
+ * endpoint, which lets new access tokens cover scopes from prior grants
62
+ * in addition to the ones requested for this flow. Set to `false` when
63
+ * each OAuth flow should request only its own scopes.
64
64
  *
65
- * @default true
65
+ * Defaults to `true`.
66
+ *
67
+ * @see https://developers.google.com/identity/protocols/oauth2/web-server#incrementalAuth
66
68
  */
67
69
  includeGrantedScopes?: boolean | undefined;
68
70
  }
69
71
 
70
- const GOOGLE_DEFAULT_SCOPES = ["email", "profile", "openid"];
71
-
72
72
  export const google = (options: GoogleOptions) => {
73
73
  return {
74
74
  id: "google",
75
75
  name: "Google",
76
- callbackPath: "/callback/google",
77
- grantAuthority:
78
- options.includeGrantedScopes !== false ? "full-grant" : "projection",
79
76
  async createAuthorizationURL({
80
77
  state,
81
78
  scopes,
@@ -94,16 +91,16 @@ export const google = (options: GoogleOptions) => {
94
91
  if (!codeVerifier) {
95
92
  throw new BetterAuthError("codeVerifier is required for Google");
96
93
  }
97
- const requestedScopes = resolveRequestedScopes(
98
- options,
99
- GOOGLE_DEFAULT_SCOPES,
100
- scopes,
101
- );
102
- return createAuthorizationURL({
94
+ const _scopes = options.disableDefaultScope
95
+ ? []
96
+ : ["email", "profile", "openid"];
97
+ if (options.scope) _scopes.push(...options.scope);
98
+ if (scopes) _scopes.push(...scopes);
99
+ const url = await createAuthorizationURL({
103
100
  id: "google",
104
101
  options,
105
102
  authorizationEndpoint: "https://accounts.google.com/o/oauth2/v2/auth",
106
- scopes: requestedScopes,
103
+ scopes: _scopes,
107
104
  state,
108
105
  codeVerifier,
109
106
  redirectURI,
@@ -112,17 +109,14 @@ export const google = (options: GoogleOptions) => {
112
109
  display: display || options.display,
113
110
  loginHint,
114
111
  hd: options.hd,
115
- additionalParams:
116
- options.includeGrantedScopes === false
117
- ? { ...(additionalParams ?? {}) }
118
- : {
119
- ...(additionalParams ?? {}),
120
- // Not caller-overridable: the emitted param must stay in
121
- // lockstep with `grantAuthority` (driven by the option), or
122
- // the callback would treat a non-authoritative grant as full.
123
- include_granted_scopes: "true",
124
- },
112
+ additionalParams: {
113
+ ...(options.includeGrantedScopes === false
114
+ ? {}
115
+ : { include_granted_scopes: "true" }),
116
+ ...(additionalParams ?? {}),
117
+ },
125
118
  });
119
+ return url;
126
120
  },
127
121
  validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
128
122
  return validateAuthorizationCode({
@@ -195,7 +189,7 @@ export const google = (options: GoogleOptions) => {
195
189
  };
196
190
  },
197
191
  options,
198
- } satisfies UpstreamProvider<GoogleProfile>;
192
+ } satisfies OAuthProvider<GoogleProfile>;
199
193
  };
200
194
 
201
195
  export const getGooglePublicKey = async (kid: string) => {
@@ -1,9 +1,8 @@
1
1
  import { betterFetch } from "@better-fetch/fetch";
2
- import type { ProviderOptions, UpstreamProvider } from "../oauth2";
2
+ import type { OAuthProvider, ProviderOptions } from "../oauth2";
3
3
  import {
4
4
  createAuthorizationURL,
5
5
  refreshAccessToken,
6
- resolveRequestedScopes,
7
6
  validateAuthorizationCode,
8
7
  } from "../oauth2";
9
8
 
@@ -43,14 +42,11 @@ export interface HuggingFaceOptions
43
42
  clientId: string;
44
43
  }
45
44
 
46
- const HUGGINGFACE_DEFAULT_SCOPES = ["openid", "profile", "email"];
47
-
48
45
  export const huggingface = (options: HuggingFaceOptions) => {
49
46
  const tokenEndpoint = "https://huggingface.co/oauth/token";
50
47
  return {
51
48
  id: "huggingface",
52
49
  name: "Hugging Face",
53
- callbackPath: "/callback/huggingface",
54
50
  createAuthorizationURL({
55
51
  state,
56
52
  scopes,
@@ -58,16 +54,16 @@ export const huggingface = (options: HuggingFaceOptions) => {
58
54
  redirectURI,
59
55
  additionalParams,
60
56
  }) {
61
- const requestedScopes = resolveRequestedScopes(
62
- options,
63
- HUGGINGFACE_DEFAULT_SCOPES,
64
- scopes,
65
- );
57
+ const _scopes = options.disableDefaultScope
58
+ ? []
59
+ : ["openid", "profile", "email"];
60
+ if (options.scope) _scopes.push(...options.scope);
61
+ if (scopes) _scopes.push(...scopes);
66
62
  return createAuthorizationURL({
67
63
  id: "huggingface",
68
64
  options,
69
65
  authorizationEndpoint: "https://huggingface.co/oauth/authorize",
70
- scopes: requestedScopes,
66
+ scopes: _scopes,
71
67
  state,
72
68
  codeVerifier,
73
69
  redirectURI,
@@ -126,5 +122,5 @@ export const huggingface = (options: HuggingFaceOptions) => {
126
122
  };
127
123
  },
128
124
  options,
129
- } satisfies UpstreamProvider<HuggingFaceProfile>;
125
+ } satisfies OAuthProvider<HuggingFaceProfile>;
130
126
  };
@@ -1,9 +1,8 @@
1
1
  import { betterFetch } from "@better-fetch/fetch";
2
- import type { ProviderOptions, UpstreamProvider } from "../oauth2";
2
+ import type { OAuthProvider, ProviderOptions } from "../oauth2";
3
3
  import {
4
4
  createAuthorizationURL,
5
5
  refreshAccessToken,
6
- resolveRequestedScopes,
7
6
  validateAuthorizationCode,
8
7
  } from "../oauth2";
9
8
 
@@ -102,29 +101,22 @@ export interface KakaoOptions extends ProviderOptions<KakaoProfile> {
102
101
  clientId: string;
103
102
  }
104
103
 
105
- const KAKAO_DEFAULT_SCOPES = [
106
- "account_email",
107
- "profile_image",
108
- "profile_nickname",
109
- ];
110
-
111
104
  export const kakao = (options: KakaoOptions) => {
112
105
  const tokenEndpoint = "https://kauth.kakao.com/oauth/token";
113
106
  return {
114
107
  id: "kakao",
115
108
  name: "Kakao",
116
- callbackPath: "/callback/kakao",
117
109
  createAuthorizationURL({ state, scopes, redirectURI, additionalParams }) {
118
- const requestedScopes = resolveRequestedScopes(
119
- options,
120
- KAKAO_DEFAULT_SCOPES,
121
- scopes,
122
- );
110
+ const _scopes = options.disableDefaultScope
111
+ ? []
112
+ : ["account_email", "profile_image", "profile_nickname"];
113
+ if (options.scope) _scopes.push(...options.scope);
114
+ if (scopes) _scopes.push(...scopes);
123
115
  return createAuthorizationURL({
124
116
  id: "kakao",
125
117
  options,
126
118
  authorizationEndpoint: "https://kauth.kakao.com/oauth/authorize",
127
- scopes: requestedScopes,
119
+ scopes: _scopes,
128
120
  state,
129
121
  redirectURI,
130
122
  additionalParams,
@@ -184,5 +176,5 @@ export const kakao = (options: KakaoOptions) => {
184
176
  };
185
177
  },
186
178
  options,
187
- } satisfies UpstreamProvider<KakaoProfile>;
179
+ } satisfies OAuthProvider<KakaoProfile>;
188
180
  };
@@ -1,9 +1,8 @@
1
1
  import { betterFetch } from "@better-fetch/fetch";
2
- import type { ProviderOptions, UpstreamProvider } from "../oauth2";
2
+ import type { OAuthProvider, ProviderOptions } from "../oauth2";
3
3
  import {
4
4
  createAuthorizationURL,
5
5
  refreshAccessToken,
6
- resolveRequestedScopes,
7
6
  validateAuthorizationCode,
8
7
  } from "../oauth2";
9
8
 
@@ -30,13 +29,10 @@ export interface KickOptions extends ProviderOptions<KickProfile> {
30
29
  clientId: string;
31
30
  }
32
31
 
33
- const KICK_DEFAULT_SCOPES = ["user:read"];
34
-
35
32
  export const kick = (options: KickOptions) => {
36
33
  return {
37
34
  id: "kick",
38
35
  name: "Kick",
39
- callbackPath: "/callback/kick",
40
36
  createAuthorizationURL({
41
37
  state,
42
38
  scopes,
@@ -44,17 +40,16 @@ export const kick = (options: KickOptions) => {
44
40
  codeVerifier,
45
41
  additionalParams,
46
42
  }) {
47
- const requestedScopes = resolveRequestedScopes(
48
- options,
49
- KICK_DEFAULT_SCOPES,
50
- scopes,
51
- );
43
+ const _scopes = options.disableDefaultScope ? [] : ["user:read"];
44
+ if (options.scope) _scopes.push(...options.scope);
45
+ if (scopes) _scopes.push(...scopes);
46
+
52
47
  return createAuthorizationURL({
53
48
  id: "kick",
54
49
  redirectURI,
55
50
  options,
56
51
  authorizationEndpoint: "https://id.kick.com/oauth/authorize",
57
- scopes: requestedScopes,
52
+ scopes: _scopes,
58
53
  codeVerifier,
59
54
  state,
60
55
  additionalParams,
@@ -117,5 +112,5 @@ export const kick = (options: KickOptions) => {
117
112
  };
118
113
  },
119
114
  options,
120
- } satisfies UpstreamProvider<KickProfile>;
115
+ } satisfies OAuthProvider<KickProfile>;
121
116
  };
@@ -1,10 +1,9 @@
1
1
  import { betterFetch } from "@better-fetch/fetch";
2
2
  import { decodeJwt } from "jose";
3
- import type { ProviderOptions, UpstreamProvider } from "../oauth2";
3
+ import type { OAuthProvider, ProviderOptions } from "../oauth2";
4
4
  import {
5
5
  createAuthorizationURL,
6
6
  refreshAccessToken,
7
- resolveRequestedScopes,
8
7
  validateAuthorizationCode,
9
8
  } from "../oauth2";
10
9
 
@@ -33,8 +32,6 @@ export interface LineOptions
33
32
  clientId: string;
34
33
  }
35
34
 
36
- const LINE_DEFAULT_SCOPES = ["openid", "profile", "email"];
37
-
38
35
  /**
39
36
  * LINE Login v2.1
40
37
  * - Authorization endpoint: https://access.line.me/oauth2/v2.1/authorize
@@ -53,8 +50,7 @@ export const line = (options: LineOptions) => {
53
50
  return {
54
51
  id: "line",
55
52
  name: "LINE",
56
- callbackPath: "/callback/line",
57
- createAuthorizationURL({
53
+ async createAuthorizationURL({
58
54
  state,
59
55
  scopes,
60
56
  codeVerifier,
@@ -62,16 +58,16 @@ export const line = (options: LineOptions) => {
62
58
  loginHint,
63
59
  additionalParams,
64
60
  }) {
65
- const requestedScopes = resolveRequestedScopes(
66
- options,
67
- LINE_DEFAULT_SCOPES,
68
- scopes,
69
- );
70
- return createAuthorizationURL({
61
+ const _scopes = options.disableDefaultScope
62
+ ? []
63
+ : ["openid", "profile", "email"];
64
+ if (options.scope) _scopes.push(...options.scope);
65
+ if (scopes) _scopes.push(...scopes);
66
+ return await createAuthorizationURL({
71
67
  id: "line",
72
68
  options,
73
69
  authorizationEndpoint,
74
- scopes: requestedScopes,
70
+ scopes: _scopes,
75
71
  state,
76
72
  codeVerifier,
77
73
  redirectURI,
@@ -167,5 +163,5 @@ export const line = (options: LineOptions) => {
167
163
  };
168
164
  },
169
165
  options,
170
- } satisfies UpstreamProvider<LineUserInfo | LineIdTokenPayload, LineOptions>;
166
+ } satisfies OAuthProvider<LineUserInfo | LineIdTokenPayload, LineOptions>;
171
167
  };
@@ -1,9 +1,8 @@
1
1
  import { betterFetch } from "@better-fetch/fetch";
2
- import type { ProviderOptions, UpstreamProvider } from "../oauth2";
2
+ import type { OAuthProvider, ProviderOptions } from "../oauth2";
3
3
  import {
4
4
  createAuthorizationURL,
5
5
  refreshAccessToken,
6
- resolveRequestedScopes,
7
6
  validateAuthorizationCode,
8
7
  } from "../oauth2";
9
8
 
@@ -27,14 +26,11 @@ export interface LinearOptions extends ProviderOptions<LinearUser> {
27
26
  clientId: string;
28
27
  }
29
28
 
30
- const LINEAR_DEFAULT_SCOPES = ["read"];
31
-
32
29
  export const linear = (options: LinearOptions) => {
33
30
  const tokenEndpoint = "https://api.linear.app/oauth/token";
34
31
  return {
35
32
  id: "linear",
36
33
  name: "Linear",
37
- callbackPath: "/callback/linear",
38
34
  createAuthorizationURL({
39
35
  state,
40
36
  scopes,
@@ -42,16 +38,14 @@ export const linear = (options: LinearOptions) => {
42
38
  redirectURI,
43
39
  additionalParams,
44
40
  }) {
45
- const requestedScopes = resolveRequestedScopes(
46
- options,
47
- LINEAR_DEFAULT_SCOPES,
48
- scopes,
49
- );
41
+ const _scopes = options.disableDefaultScope ? [] : ["read"];
42
+ if (options.scope) _scopes.push(...options.scope);
43
+ if (scopes) _scopes.push(...scopes);
50
44
  return createAuthorizationURL({
51
45
  id: "linear",
52
46
  options,
53
47
  authorizationEndpoint: "https://linear.app/oauth/authorize",
54
- scopes: requestedScopes,
48
+ scopes: _scopes,
55
49
  state,
56
50
  redirectURI,
57
51
  loginHint,
@@ -130,5 +124,5 @@ export const linear = (options: LinearOptions) => {
130
124
  };
131
125
  },
132
126
  options,
133
- } satisfies UpstreamProvider<LinearUser>;
127
+ } satisfies OAuthProvider<LinearUser>;
134
128
  };
@@ -1,9 +1,8 @@
1
1
  import { betterFetch } from "@better-fetch/fetch";
2
- import type { ProviderOptions, UpstreamProvider } from "../oauth2";
2
+ import type { OAuthProvider, ProviderOptions } from "../oauth2";
3
3
  import {
4
4
  createAuthorizationURL,
5
5
  refreshAccessToken,
6
- resolveRequestedScopes,
7
6
  validateAuthorizationCode,
8
7
  } from "../oauth2";
9
8
 
@@ -25,8 +24,6 @@ export interface LinkedInOptions extends ProviderOptions<LinkedInProfile> {
25
24
  clientId: string;
26
25
  }
27
26
 
28
- const LINKEDIN_DEFAULT_SCOPES = ["profile", "email", "openid"];
29
-
30
27
  export const linkedin = (options: LinkedInOptions) => {
31
28
  const authorizationEndpoint =
32
29
  "https://www.linkedin.com/oauth/v2/authorization";
@@ -35,24 +32,23 @@ export const linkedin = (options: LinkedInOptions) => {
35
32
  return {
36
33
  id: "linkedin",
37
34
  name: "Linkedin",
38
- callbackPath: "/callback/linkedin",
39
- createAuthorizationURL: ({
35
+ createAuthorizationURL: async ({
40
36
  state,
41
37
  scopes,
42
38
  redirectURI,
43
39
  loginHint,
44
40
  additionalParams,
45
41
  }) => {
46
- const requestedScopes = resolveRequestedScopes(
47
- options,
48
- LINKEDIN_DEFAULT_SCOPES,
49
- scopes,
50
- );
51
- return createAuthorizationURL({
42
+ const _scopes = options.disableDefaultScope
43
+ ? []
44
+ : ["profile", "email", "openid"];
45
+ if (options.scope) _scopes.push(...options.scope);
46
+ if (scopes) _scopes.push(...scopes);
47
+ return await createAuthorizationURL({
52
48
  id: "linkedin",
53
49
  options,
54
50
  authorizationEndpoint,
55
- scopes: requestedScopes,
51
+ scopes: _scopes,
56
52
  state,
57
53
  loginHint,
58
54
  redirectURI,
@@ -112,5 +108,5 @@ export const linkedin = (options: LinkedInOptions) => {
112
108
  };
113
109
  },
114
110
  options,
115
- } satisfies UpstreamProvider<LinkedInProfile>;
111
+ } satisfies OAuthProvider<LinkedInProfile>;
116
112
  };
@@ -5,15 +5,14 @@ import { logger } from "../env";
5
5
  import { APIError, BetterAuthError } from "../error";
6
6
  import type {
7
7
  ClientAssertionGetter,
8
+ OAuthProvider,
8
9
  ProviderOptions,
9
10
  TokenEndpointAuth,
10
- UpstreamProvider,
11
11
  } from "../oauth2";
12
12
  import {
13
13
  createAuthorizationURL,
14
14
  getPrimaryClientId,
15
15
  refreshAccessToken,
16
- resolveRequestedScopes,
17
16
  validateAuthorizationCode,
18
17
  } from "../oauth2";
19
18
 
@@ -161,14 +160,6 @@ export interface MicrosoftOptions
161
160
  disableProfilePhoto?: boolean;
162
161
  }
163
162
 
164
- const MICROSOFT_ENTRA_ID_DEFAULT_SCOPES = [
165
- "openid",
166
- "profile",
167
- "email",
168
- "User.Read",
169
- "offline_access",
170
- ];
171
-
172
163
  export const microsoft = (options: MicrosoftOptions) => {
173
164
  const tenant = options.tenantId || "common";
174
165
  // Trim any trailing slash so endpoint URLs and the issuer comparison below
@@ -196,7 +187,6 @@ export const microsoft = (options: MicrosoftOptions) => {
196
187
  return {
197
188
  id: "microsoft",
198
189
  name: "Microsoft EntraID",
199
- callbackPath: "/callback/microsoft",
200
190
  createAuthorizationURL(data) {
201
191
  // Microsoft Entra supports public clients (SPA / native apps with
202
192
  // PKCE only), so clientSecret is intentionally not required here.
@@ -207,18 +197,18 @@ export const microsoft = (options: MicrosoftOptions) => {
207
197
  );
208
198
  throw new BetterAuthError("CLIENT_ID_AND_SECRET_REQUIRED");
209
199
  }
210
- const requestedScopes = resolveRequestedScopes(
211
- options,
212
- MICROSOFT_ENTRA_ID_DEFAULT_SCOPES,
213
- data.scopes,
214
- );
200
+ const scopes = options.disableDefaultScope
201
+ ? []
202
+ : ["openid", "profile", "email", "User.Read", "offline_access"];
203
+ if (options.scope) scopes.push(...options.scope);
204
+ if (data.scopes) scopes.push(...data.scopes);
215
205
  return createAuthorizationURL({
216
206
  id: "microsoft",
217
207
  options,
218
208
  authorizationEndpoint,
219
209
  state: data.state,
220
210
  codeVerifier: data.codeVerifier,
221
- scopes: requestedScopes,
211
+ scopes,
222
212
  redirectURI: data.redirectURI,
223
213
  prompt: options.prompt,
224
214
  loginHint: data.loginHint,
@@ -361,7 +351,7 @@ export const microsoft = (options: MicrosoftOptions) => {
361
351
  });
362
352
  },
363
353
  options,
364
- } satisfies UpstreamProvider;
354
+ } satisfies OAuthProvider;
365
355
  };
366
356
 
367
357
  export const getMicrosoftPublicKey = async (
@@ -1,9 +1,8 @@
1
1
  import { betterFetch } from "@better-fetch/fetch";
2
- import type { ProviderOptions, UpstreamProvider } from "../oauth2";
2
+ import type { OAuthProvider, ProviderOptions } from "../oauth2";
3
3
  import {
4
4
  createAuthorizationURL,
5
5
  refreshAccessToken,
6
- resolveRequestedScopes,
7
6
  validateAuthorizationCode,
8
7
  } from "../oauth2";
9
8
 
@@ -40,25 +39,20 @@ export interface NaverOptions extends ProviderOptions<NaverProfile> {
40
39
  clientId: string;
41
40
  }
42
41
 
43
- const NAVER_DEFAULT_SCOPES = ["profile", "email"];
44
-
45
42
  export const naver = (options: NaverOptions) => {
46
43
  const tokenEndpoint = "https://nid.naver.com/oauth2.0/token";
47
44
  return {
48
45
  id: "naver",
49
46
  name: "Naver",
50
- callbackPath: "/callback/naver",
51
47
  createAuthorizationURL({ state, scopes, redirectURI, additionalParams }) {
52
- const requestedScopes = resolveRequestedScopes(
53
- options,
54
- NAVER_DEFAULT_SCOPES,
55
- scopes,
56
- );
48
+ const _scopes = options.disableDefaultScope ? [] : ["profile", "email"];
49
+ if (options.scope) _scopes.push(...options.scope);
50
+ if (scopes) _scopes.push(...scopes);
57
51
  return createAuthorizationURL({
58
52
  id: "naver",
59
53
  options,
60
54
  authorizationEndpoint: "https://nid.naver.com/oauth2.0/authorize",
61
- scopes: requestedScopes,
55
+ scopes: _scopes,
62
56
  state,
63
57
  redirectURI,
64
58
  additionalParams,
@@ -116,5 +110,5 @@ export const naver = (options: NaverOptions) => {
116
110
  };
117
111
  },
118
112
  options,
119
- } satisfies UpstreamProvider<NaverProfile>;
113
+ } satisfies OAuthProvider<NaverProfile>;
120
114
  };
@@ -1,9 +1,8 @@
1
1
  import { betterFetch } from "@better-fetch/fetch";
2
- import type { ProviderOptions, UpstreamProvider } from "../oauth2";
2
+ import type { OAuthProvider, ProviderOptions } from "../oauth2";
3
3
  import {
4
4
  createAuthorizationURL,
5
5
  refreshAccessToken,
6
- resolveRequestedScopes,
7
6
  validateAuthorizationCode,
8
7
  } from "../oauth2";
9
8
 
@@ -24,14 +23,11 @@ export interface NotionOptions extends ProviderOptions<NotionProfile> {
24
23
  clientId: string;
25
24
  }
26
25
 
27
- const NOTION_DEFAULT_SCOPES: string[] = [];
28
-
29
26
  export const notion = (options: NotionOptions) => {
30
27
  const tokenEndpoint = "https://api.notion.com/v1/oauth/token";
31
28
  return {
32
29
  id: "notion",
33
30
  name: "Notion",
34
- callbackPath: "/callback/notion",
35
31
  createAuthorizationURL({
36
32
  state,
37
33
  scopes,
@@ -39,16 +35,14 @@ export const notion = (options: NotionOptions) => {
39
35
  redirectURI,
40
36
  additionalParams,
41
37
  }) {
42
- const requestedScopes = resolveRequestedScopes(
43
- options,
44
- NOTION_DEFAULT_SCOPES,
45
- scopes,
46
- );
38
+ const _scopes: string[] = options.disableDefaultScope ? [] : [];
39
+ if (options.scope) _scopes.push(...options.scope);
40
+ if (scopes) _scopes.push(...scopes);
47
41
  return createAuthorizationURL({
48
42
  id: "notion",
49
43
  options,
50
44
  authorizationEndpoint: "https://api.notion.com/v1/oauth/authorize",
51
- scopes: requestedScopes,
45
+ scopes: _scopes,
52
46
  state,
53
47
  redirectURI,
54
48
  loginHint,
@@ -117,5 +111,5 @@ export const notion = (options: NotionOptions) => {
117
111
  };
118
112
  },
119
113
  options,
120
- } satisfies UpstreamProvider<NotionProfile>;
114
+ } satisfies OAuthProvider<NotionProfile>;
121
115
  };