@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
@@ -93,10 +93,12 @@ interface KakaoOptions extends ProviderOptions<KakaoProfile> {
93
93
  declare const kakao: (options: KakaoOptions) => {
94
94
  id: "kakao";
95
95
  name: string;
96
+ callbackPath: string;
96
97
  createAuthorizationURL({
97
98
  state,
98
99
  scopes,
99
- redirectURI
100
+ redirectURI,
101
+ additionalParams
100
102
  }: {
101
103
  state: string;
102
104
  codeVerifier: string;
@@ -104,7 +106,11 @@ declare const kakao: (options: KakaoOptions) => {
104
106
  redirectURI: string;
105
107
  display?: string | undefined;
106
108
  loginHint?: string | undefined;
107
- }): Promise<URL>;
109
+ additionalParams?: Record<string, string> | undefined;
110
+ }): Promise<{
111
+ url: URL;
112
+ requestedScopes: string[];
113
+ }>;
108
114
  validateAuthorizationCode: ({
109
115
  code,
110
116
  redirectURI
@@ -1,28 +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/kakao.ts
7
+ const KAKAO_DEFAULT_SCOPES = [
8
+ "account_email",
9
+ "profile_image",
10
+ "profile_nickname"
11
+ ];
6
12
  const kakao = (options) => {
7
13
  const tokenEndpoint = "https://kauth.kakao.com/oauth/token";
8
14
  return {
9
15
  id: "kakao",
10
16
  name: "Kakao",
11
- createAuthorizationURL({ state, scopes, redirectURI }) {
12
- const _scopes = options.disableDefaultScope ? [] : [
13
- "account_email",
14
- "profile_image",
15
- "profile_nickname"
16
- ];
17
- if (options.scope) _scopes.push(...options.scope);
18
- if (scopes) _scopes.push(...scopes);
17
+ callbackPath: "/callback/kakao",
18
+ createAuthorizationURL({ state, scopes, redirectURI, additionalParams }) {
19
19
  return createAuthorizationURL({
20
20
  id: "kakao",
21
21
  options,
22
22
  authorizationEndpoint: "https://kauth.kakao.com/oauth/authorize",
23
- scopes: _scopes,
23
+ scopes: resolveRequestedScopes(options, KAKAO_DEFAULT_SCOPES, scopes),
24
24
  state,
25
- redirectURI
25
+ redirectURI,
26
+ additionalParams
26
27
  });
27
28
  },
28
29
  validateAuthorizationCode: async ({ code, redirectURI }) => {
@@ -24,11 +24,13 @@ interface KickOptions extends ProviderOptions<KickProfile> {
24
24
  declare const kick: (options: KickOptions) => {
25
25
  id: "kick";
26
26
  name: string;
27
+ callbackPath: string;
27
28
  createAuthorizationURL({
28
29
  state,
29
30
  scopes,
30
31
  redirectURI,
31
- codeVerifier
32
+ codeVerifier,
33
+ additionalParams
32
34
  }: {
33
35
  state: string;
34
36
  codeVerifier: string;
@@ -36,7 +38,11 @@ declare const kick: (options: KickOptions) => {
36
38
  redirectURI: string;
37
39
  display?: string | undefined;
38
40
  loginHint?: string | undefined;
39
- }): Promise<URL>;
41
+ additionalParams?: Record<string, string> | undefined;
42
+ }): Promise<{
43
+ url: URL;
44
+ requestedScopes: string[];
45
+ }>;
40
46
  validateAuthorizationCode({
41
47
  code,
42
48
  redirectURI,
@@ -1,24 +1,25 @@
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/kick.ts
7
+ const KICK_DEFAULT_SCOPES = ["user:read"];
6
8
  const kick = (options) => {
7
9
  return {
8
10
  id: "kick",
9
11
  name: "Kick",
10
- createAuthorizationURL({ state, scopes, redirectURI, codeVerifier }) {
11
- const _scopes = options.disableDefaultScope ? [] : ["user:read"];
12
- if (options.scope) _scopes.push(...options.scope);
13
- if (scopes) _scopes.push(...scopes);
12
+ callbackPath: "/callback/kick",
13
+ createAuthorizationURL({ state, scopes, redirectURI, codeVerifier, additionalParams }) {
14
14
  return createAuthorizationURL({
15
15
  id: "kick",
16
16
  redirectURI,
17
17
  options,
18
18
  authorizationEndpoint: "https://id.kick.com/oauth/authorize",
19
- scopes: _scopes,
19
+ scopes: resolveRequestedScopes(options, KICK_DEFAULT_SCOPES, scopes),
20
20
  codeVerifier,
21
- state
21
+ state,
22
+ additionalParams
22
23
  });
23
24
  },
24
25
  async validateAuthorizationCode({ code, redirectURI, codeVerifier }) {
@@ -33,12 +33,14 @@ interface LineOptions extends ProviderOptions<LineUserInfo | LineIdTokenPayload>
33
33
  declare const line: (options: LineOptions) => {
34
34
  id: "line";
35
35
  name: string;
36
+ callbackPath: string;
36
37
  createAuthorizationURL({
37
38
  state,
38
39
  scopes,
39
40
  codeVerifier,
40
41
  redirectURI,
41
- loginHint
42
+ loginHint,
43
+ additionalParams
42
44
  }: {
43
45
  state: string;
44
46
  codeVerifier: string;
@@ -46,7 +48,11 @@ declare const line: (options: LineOptions) => {
46
48
  redirectURI: string;
47
49
  display?: string | undefined;
48
50
  loginHint?: string | undefined;
49
- }): Promise<URL>;
51
+ additionalParams?: Record<string, string> | undefined;
52
+ }): Promise<{
53
+ url: URL;
54
+ requestedScopes: string[];
55
+ }>;
50
56
  validateAuthorizationCode: ({
51
57
  code,
52
58
  codeVerifier,
@@ -58,7 +64,9 @@ declare const line: (options: LineOptions) => {
58
64
  deviceId?: string | undefined;
59
65
  }) => Promise<OAuth2Tokens>;
60
66
  refreshAccessToken: (refreshToken: string) => Promise<OAuth2Tokens>;
61
- verifyIdToken(token: string, nonce: string | undefined): Promise<boolean>;
67
+ idToken: {
68
+ verify: (token: string, nonce: string | undefined) => Promise<boolean>;
69
+ };
62
70
  getUserInfo(token: OAuth2Tokens & {
63
71
  user?: {
64
72
  name?: {
@@ -1,9 +1,15 @@
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 { decodeJwt } from "jose";
5
6
  import { betterFetch } from "@better-fetch/fetch";
6
7
  //#region src/social-providers/line.ts
8
+ const LINE_DEFAULT_SCOPES = [
9
+ "openid",
10
+ "profile",
11
+ "email"
12
+ ];
7
13
  /**
8
14
  * LINE Login v2.1
9
15
  * - Authorization endpoint: https://access.line.me/oauth2/v2.1/authorize
@@ -21,23 +27,18 @@ const line = (options) => {
21
27
  return {
22
28
  id: "line",
23
29
  name: "LINE",
24
- async createAuthorizationURL({ state, scopes, codeVerifier, redirectURI, loginHint }) {
25
- const _scopes = options.disableDefaultScope ? [] : [
26
- "openid",
27
- "profile",
28
- "email"
29
- ];
30
- if (options.scope) _scopes.push(...options.scope);
31
- if (scopes) _scopes.push(...scopes);
32
- return await createAuthorizationURL({
30
+ callbackPath: "/callback/line",
31
+ createAuthorizationURL({ state, scopes, codeVerifier, redirectURI, loginHint, additionalParams }) {
32
+ return createAuthorizationURL({
33
33
  id: "line",
34
34
  options,
35
35
  authorizationEndpoint,
36
- scopes: _scopes,
36
+ scopes: resolveRequestedScopes(options, LINE_DEFAULT_SCOPES, scopes),
37
37
  state,
38
38
  codeVerifier,
39
39
  redirectURI,
40
- loginHint
40
+ loginHint,
41
+ additionalParams
41
42
  });
42
43
  },
43
44
  validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
@@ -59,9 +60,7 @@ const line = (options) => {
59
60
  tokenEndpoint
60
61
  });
61
62
  },
62
- async verifyIdToken(token, nonce) {
63
- if (options.disableIdTokenSignIn) return false;
64
- if (options.verifyIdToken) return options.verifyIdToken(token, nonce);
63
+ idToken: { verify: async (token, nonce) => {
65
64
  const body = new URLSearchParams();
66
65
  body.set("id_token", token);
67
66
  body.set("client_id", options.clientId);
@@ -75,7 +74,7 @@ const line = (options) => {
75
74
  if (data.aud !== options.clientId) return false;
76
75
  if (data.nonce && data.nonce !== nonce) return false;
77
76
  return true;
78
- },
77
+ } },
79
78
  async getUserInfo(token) {
80
79
  if (options.getUserInfo) return options.getUserInfo(token);
81
80
  let profile = null;
@@ -20,11 +20,13 @@ interface LinearOptions extends ProviderOptions<LinearUser> {
20
20
  declare const linear: (options: LinearOptions) => {
21
21
  id: "linear";
22
22
  name: string;
23
+ callbackPath: string;
23
24
  createAuthorizationURL({
24
25
  state,
25
26
  scopes,
26
27
  loginHint,
27
- redirectURI
28
+ redirectURI,
29
+ additionalParams
28
30
  }: {
29
31
  state: string;
30
32
  codeVerifier: string;
@@ -32,7 +34,11 @@ declare const linear: (options: LinearOptions) => {
32
34
  redirectURI: string;
33
35
  display?: string | undefined;
34
36
  loginHint?: string | undefined;
35
- }): Promise<URL>;
37
+ additionalParams?: Record<string, string> | undefined;
38
+ }): Promise<{
39
+ url: URL;
40
+ requestedScopes: string[];
41
+ }>;
36
42
  validateAuthorizationCode: ({
37
43
  code,
38
44
  redirectURI
@@ -1,25 +1,26 @@
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/linear.ts
7
+ const LINEAR_DEFAULT_SCOPES = ["read"];
6
8
  const linear = (options) => {
7
9
  const tokenEndpoint = "https://api.linear.app/oauth/token";
8
10
  return {
9
11
  id: "linear",
10
12
  name: "Linear",
11
- createAuthorizationURL({ state, scopes, loginHint, redirectURI }) {
12
- const _scopes = options.disableDefaultScope ? [] : ["read"];
13
- if (options.scope) _scopes.push(...options.scope);
14
- if (scopes) _scopes.push(...scopes);
13
+ callbackPath: "/callback/linear",
14
+ createAuthorizationURL({ state, scopes, loginHint, redirectURI, additionalParams }) {
15
15
  return createAuthorizationURL({
16
16
  id: "linear",
17
17
  options,
18
18
  authorizationEndpoint: "https://linear.app/oauth/authorize",
19
- scopes: _scopes,
19
+ scopes: resolveRequestedScopes(options, LINEAR_DEFAULT_SCOPES, scopes),
20
20
  state,
21
21
  redirectURI,
22
- loginHint
22
+ loginHint,
23
+ additionalParams
23
24
  });
24
25
  },
25
26
  validateAuthorizationCode: async ({ code, redirectURI }) => {
@@ -19,11 +19,13 @@ interface LinkedInOptions extends ProviderOptions<LinkedInProfile> {
19
19
  declare const linkedin: (options: LinkedInOptions) => {
20
20
  id: "linkedin";
21
21
  name: string;
22
+ callbackPath: string;
22
23
  createAuthorizationURL: ({
23
24
  state,
24
25
  scopes,
25
26
  redirectURI,
26
- loginHint
27
+ loginHint,
28
+ additionalParams
27
29
  }: {
28
30
  state: string;
29
31
  codeVerifier: string;
@@ -31,7 +33,11 @@ declare const linkedin: (options: LinkedInOptions) => {
31
33
  redirectURI: string;
32
34
  display?: string | undefined;
33
35
  loginHint?: string | undefined;
34
- }) => Promise<URL>;
36
+ additionalParams?: Record<string, string> | undefined;
37
+ }) => Promise<{
38
+ url: URL;
39
+ requestedScopes: string[];
40
+ }>;
35
41
  validateAuthorizationCode: ({
36
42
  code,
37
43
  redirectURI
@@ -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/linkedin.ts
7
+ const LINKEDIN_DEFAULT_SCOPES = [
8
+ "profile",
9
+ "email",
10
+ "openid"
11
+ ];
6
12
  const linkedin = (options) => {
7
13
  const authorizationEndpoint = "https://www.linkedin.com/oauth/v2/authorization";
8
14
  const tokenEndpoint = "https://www.linkedin.com/oauth/v2/accessToken";
9
15
  return {
10
16
  id: "linkedin",
11
17
  name: "Linkedin",
12
- createAuthorizationURL: async ({ state, scopes, redirectURI, loginHint }) => {
13
- const _scopes = options.disableDefaultScope ? [] : [
14
- "profile",
15
- "email",
16
- "openid"
17
- ];
18
- if (options.scope) _scopes.push(...options.scope);
19
- if (scopes) _scopes.push(...scopes);
20
- return await createAuthorizationURL({
18
+ callbackPath: "/callback/linkedin",
19
+ createAuthorizationURL: ({ state, scopes, redirectURI, loginHint, additionalParams }) => {
20
+ return createAuthorizationURL({
21
21
  id: "linkedin",
22
22
  options,
23
23
  authorizationEndpoint,
24
- scopes: _scopes,
24
+ scopes: resolveRequestedScopes(options, LINKEDIN_DEFAULT_SCOPES, scopes),
25
25
  state,
26
26
  loginHint,
27
- redirectURI
27
+ redirectURI,
28
+ additionalParams
28
29
  });
29
30
  },
30
31
  validateAuthorizationCode: async ({ code, redirectURI }) => {
@@ -1,4 +1,7 @@
1
+ import { ClientAssertionGetter } from "../oauth2/client-assertion.mjs";
1
2
  import { OAuth2Tokens, ProviderOptions } from "../oauth2/oauth-provider.mjs";
3
+ import * as jose from "jose";
4
+
2
5
  //#region src/social-providers/microsoft-entra-id.d.ts
3
6
  /**
4
7
  * @see [Microsoft Identity Platform - Optional claims reference](https://learn.microsoft.com/en-us/entra/identity-platform/optional-claims-reference)
@@ -109,25 +112,34 @@ interface MicrosoftOptions extends ProviderOptions<MicrosoftEntraIDProfile> {
109
112
  * The tenant ID of the Microsoft account
110
113
  * @default "common"
111
114
  */
112
- tenantId?: string | undefined;
115
+ tenantId?: string;
113
116
  /**
114
117
  * The authentication authority URL. Use the default "https://login.microsoftonline.com" for standard Entra ID or "https://<tenant-id>.ciamlogin.com" for CIAM scenarios.
115
118
  * @default "https://login.microsoftonline.com"
116
119
  */
117
- authority?: string | undefined;
120
+ authority?: string;
121
+ /**
122
+ * Function that returns a JWT client assertion for token endpoint authentication.
123
+ *
124
+ * Use this instead of `clientSecret` when your Microsoft Entra ID app is
125
+ * configured for client authentication with assertions (private_key_jwt or
126
+ * workload identity federation).
127
+ */
128
+ clientAssertion?: ClientAssertionGetter;
118
129
  /**
119
130
  * The size of the profile photo
120
131
  * @default 48
121
132
  */
122
- profilePhotoSize?: (48 | 64 | 96 | 120 | 240 | 360 | 432 | 504 | 648) | undefined;
133
+ profilePhotoSize?: 48 | 64 | 96 | 120 | 240 | 360 | 432 | 504 | 648;
123
134
  /**
124
135
  * Disable profile photo
125
136
  */
126
- disableProfilePhoto?: boolean | undefined;
137
+ disableProfilePhoto?: boolean;
127
138
  }
128
139
  declare const microsoft: (options: MicrosoftOptions) => {
129
140
  id: "microsoft";
130
141
  name: string;
142
+ callbackPath: string;
131
143
  createAuthorizationURL(data: {
132
144
  state: string;
133
145
  codeVerifier: string;
@@ -135,7 +147,11 @@ declare const microsoft: (options: MicrosoftOptions) => {
135
147
  redirectURI: string;
136
148
  display?: string | undefined;
137
149
  loginHint?: string | undefined;
138
- }): Promise<URL>;
150
+ additionalParams?: Record<string, string> | undefined;
151
+ }): Promise<{
152
+ url: URL;
153
+ requestedScopes: string[];
154
+ }>;
139
155
  validateAuthorizationCode({
140
156
  code,
141
157
  codeVerifier,
@@ -146,12 +162,22 @@ declare const microsoft: (options: MicrosoftOptions) => {
146
162
  codeVerifier?: string | undefined;
147
163
  deviceId?: string | undefined;
148
164
  }): Promise<OAuth2Tokens>;
149
- verifyIdToken(token: string, nonce: string | undefined): Promise<boolean>;
165
+ idToken: {
166
+ jwks: (header: jose.JWTHeaderParameters) => Promise<Uint8Array<ArrayBufferLike> | CryptoKey>;
167
+ audience: string | string[];
168
+ maxTokenAge: string;
169
+ /**
170
+ * Issuer varies per tenant for multi-tenant endpoints, so only validate it for
171
+ * specific tenants.
172
+ * @see https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols#endpoints
173
+ */
174
+ issuer: string | undefined;
175
+ };
150
176
  getUserInfo(token: OAuth2Tokens & {
151
177
  user?: {
152
178
  name?: {
153
179
  firstName?: string;
154
- lastName? /** The primary username that represents the user */: string;
180
+ lastName?: string;
155
181
  };
156
182
  email?: string;
157
183
  } | undefined;
@@ -1,45 +1,52 @@
1
1
  import { APIError, BetterAuthError } from "../error/index.mjs";
2
2
  import { logger } from "../env/logger.mjs";
3
+ import { resolveRequestedScopes } from "../oauth2/scopes.mjs";
3
4
  import { getPrimaryClientId } from "../oauth2/utils.mjs";
4
5
  import { createAuthorizationURL } from "../oauth2/create-authorization-url.mjs";
5
6
  import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
6
7
  import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
7
- import { decodeJwt, decodeProtectedHeader, importJWK, jwtVerify } from "jose";
8
8
  import { base64 } from "@better-auth/utils/base64";
9
+ import { decodeJwt, importJWK } from "jose";
9
10
  import { betterFetch } from "@better-fetch/fetch";
10
11
  //#region src/social-providers/microsoft-entra-id.ts
12
+ const MICROSOFT_ENTRA_ID_DEFAULT_SCOPES = [
13
+ "openid",
14
+ "profile",
15
+ "email",
16
+ "User.Read",
17
+ "offline_access"
18
+ ];
11
19
  const microsoft = (options) => {
12
20
  const tenant = options.tenantId || "common";
13
21
  const authority = options.authority || "https://login.microsoftonline.com";
14
22
  const authorizationEndpoint = `${authority}/${tenant}/oauth2/v2.0/authorize`;
15
23
  const tokenEndpoint = `${authority}/${tenant}/oauth2/v2.0/token`;
24
+ if (options.clientSecret && options.clientAssertion) throw new BetterAuthError("Microsoft Entra ID clientAssertion cannot be combined with clientSecret");
25
+ const tokenEndpointAuth = options.clientAssertion ? {
26
+ method: "private_key_jwt",
27
+ getClientAssertion: options.clientAssertion
28
+ } : void 0;
16
29
  return {
17
30
  id: "microsoft",
18
31
  name: "Microsoft EntraID",
32
+ callbackPath: "/callback/microsoft",
19
33
  createAuthorizationURL(data) {
20
34
  if (!getPrimaryClientId(options.clientId)) {
21
35
  logger.error("Client Id is required for Microsoft Entra ID. Make sure to provide it in the options.");
22
36
  throw new BetterAuthError("CLIENT_ID_AND_SECRET_REQUIRED");
23
37
  }
24
- const scopes = options.disableDefaultScope ? [] : [
25
- "openid",
26
- "profile",
27
- "email",
28
- "User.Read",
29
- "offline_access"
30
- ];
31
- if (options.scope) scopes.push(...options.scope);
32
- if (data.scopes) scopes.push(...data.scopes);
38
+ const requestedScopes = resolveRequestedScopes(options, MICROSOFT_ENTRA_ID_DEFAULT_SCOPES, data.scopes);
33
39
  return createAuthorizationURL({
34
40
  id: "microsoft",
35
41
  options,
36
42
  authorizationEndpoint,
37
43
  state: data.state,
38
44
  codeVerifier: data.codeVerifier,
39
- scopes,
45
+ scopes: requestedScopes,
40
46
  redirectURI: data.redirectURI,
41
47
  prompt: options.prompt,
42
- loginHint: data.loginHint
48
+ loginHint: data.loginHint,
49
+ additionalParams: data.additionalParams
43
50
  });
44
51
  },
45
52
  validateAuthorizationCode({ code, codeVerifier, redirectURI }) {
@@ -48,33 +55,15 @@ const microsoft = (options) => {
48
55
  codeVerifier,
49
56
  redirectURI,
50
57
  options,
51
- tokenEndpoint
58
+ tokenEndpoint,
59
+ tokenEndpointAuth
52
60
  });
53
61
  },
54
- async verifyIdToken(token, nonce) {
55
- if (options.disableIdTokenSignIn) return false;
56
- if (options.verifyIdToken) return options.verifyIdToken(token, nonce);
57
- try {
58
- const { kid, alg: jwtAlg } = decodeProtectedHeader(token);
59
- if (!kid || !jwtAlg) return false;
60
- const publicKey = await getMicrosoftPublicKey(kid, tenant, authority);
61
- const verifyOptions = {
62
- algorithms: [jwtAlg],
63
- audience: options.clientId,
64
- maxTokenAge: "1h"
65
- };
66
- /**
67
- * Issuer varies per user's tenant for multi-tenant endpoints, so only validate for specific tenants.
68
- * @see https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols#endpoints
69
- */
70
- if (tenant !== "common" && tenant !== "organizations" && tenant !== "consumers") verifyOptions.issuer = `${authority}/${tenant}/v2.0`;
71
- const { payload: jwtClaims } = await jwtVerify(token, publicKey, verifyOptions);
72
- if (nonce && jwtClaims.nonce !== nonce) return false;
73
- return true;
74
- } catch (error) {
75
- logger.error("Failed to verify ID token:", error);
76
- return false;
77
- }
62
+ idToken: {
63
+ jwks: (header) => getMicrosoftPublicKey(header.kid, tenant, authority),
64
+ audience: options.clientId,
65
+ maxTokenAge: "1h",
66
+ issuer: tenant !== "common" && tenant !== "organizations" && tenant !== "consumers" ? `${authority}/${tenant}/v2.0` : void 0
78
67
  },
79
68
  async getUserInfo(token) {
80
69
  if (options.getUserInfo) return options.getUserInfo(token);
@@ -123,7 +112,8 @@ const microsoft = (options) => {
123
112
  clientSecret: options.clientSecret
124
113
  },
125
114
  extraParams: { scope: scopes.join(" ") },
126
- tokenEndpoint
115
+ tokenEndpoint,
116
+ tokenEndpointAuth
127
117
  });
128
118
  },
129
119
  options
@@ -24,10 +24,12 @@ interface NaverOptions extends ProviderOptions<NaverProfile> {
24
24
  declare const naver: (options: NaverOptions) => {
25
25
  id: "naver";
26
26
  name: string;
27
+ callbackPath: string;
27
28
  createAuthorizationURL({
28
29
  state,
29
30
  scopes,
30
- redirectURI
31
+ redirectURI,
32
+ additionalParams
31
33
  }: {
32
34
  state: string;
33
35
  codeVerifier: string;
@@ -35,7 +37,11 @@ declare const naver: (options: NaverOptions) => {
35
37
  redirectURI: string;
36
38
  display?: string | undefined;
37
39
  loginHint?: string | undefined;
38
- }): Promise<URL>;
40
+ additionalParams?: Record<string, string> | undefined;
41
+ }): Promise<{
42
+ url: URL;
43
+ requestedScopes: string[];
44
+ }>;
39
45
  validateAuthorizationCode: ({
40
46
  code,
41
47
  redirectURI
@@ -1,24 +1,25 @@
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/naver.ts
7
+ const NAVER_DEFAULT_SCOPES = ["profile", "email"];
6
8
  const naver = (options) => {
7
9
  const tokenEndpoint = "https://nid.naver.com/oauth2.0/token";
8
10
  return {
9
11
  id: "naver",
10
12
  name: "Naver",
11
- createAuthorizationURL({ state, scopes, redirectURI }) {
12
- const _scopes = options.disableDefaultScope ? [] : ["profile", "email"];
13
- if (options.scope) _scopes.push(...options.scope);
14
- if (scopes) _scopes.push(...scopes);
13
+ callbackPath: "/callback/naver",
14
+ createAuthorizationURL({ state, scopes, redirectURI, additionalParams }) {
15
15
  return createAuthorizationURL({
16
16
  id: "naver",
17
17
  options,
18
18
  authorizationEndpoint: "https://nid.naver.com/oauth2.0/authorize",
19
- scopes: _scopes,
19
+ scopes: resolveRequestedScopes(options, NAVER_DEFAULT_SCOPES, scopes),
20
20
  state,
21
- redirectURI
21
+ redirectURI,
22
+ additionalParams
22
23
  });
23
24
  },
24
25
  validateAuthorizationCode: async ({ code, redirectURI }) => {
@@ -16,11 +16,13 @@ interface NotionOptions extends ProviderOptions<NotionProfile> {
16
16
  declare const notion: (options: NotionOptions) => {
17
17
  id: "notion";
18
18
  name: string;
19
+ callbackPath: string;
19
20
  createAuthorizationURL({
20
21
  state,
21
22
  scopes,
22
23
  loginHint,
23
- redirectURI
24
+ redirectURI,
25
+ additionalParams
24
26
  }: {
25
27
  state: string;
26
28
  codeVerifier: string;
@@ -28,7 +30,11 @@ declare const notion: (options: NotionOptions) => {
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
  redirectURI