@better-auth/core 1.7.0-beta.2 → 1.7.0-beta.4

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 (172) hide show
  1. package/dist/context/global.mjs +1 -1
  2. package/dist/db/adapter/factory.mjs +64 -3
  3. package/dist/db/adapter/index.d.mts +35 -1
  4. package/dist/db/adapter/types.d.mts +1 -1
  5. package/dist/db/type.d.mts +12 -0
  6. package/dist/error/codes.d.mts +1 -0
  7. package/dist/error/codes.mjs +1 -0
  8. package/dist/instrumentation/tracer.mjs +1 -1
  9. package/dist/oauth2/authorization-params.d.mts +12 -0
  10. package/dist/oauth2/authorization-params.mjs +12 -0
  11. package/dist/oauth2/basic-credentials.d.mts +30 -0
  12. package/dist/oauth2/basic-credentials.mjs +64 -0
  13. package/dist/oauth2/client-assertion.d.mts +38 -22
  14. package/dist/oauth2/client-assertion.mjs +63 -28
  15. package/dist/oauth2/client-credentials-token.d.mts +19 -40
  16. package/dist/oauth2/client-credentials-token.mjs +18 -29
  17. package/dist/oauth2/create-authorization-url.d.mts +9 -1
  18. package/dist/oauth2/create-authorization-url.mjs +23 -5
  19. package/dist/oauth2/index.d.mts +10 -7
  20. package/dist/oauth2/index.mjs +9 -7
  21. package/dist/oauth2/oauth-provider.d.mts +21 -2
  22. package/dist/oauth2/refresh-access-token.d.mts +20 -40
  23. package/dist/oauth2/refresh-access-token.mjs +19 -32
  24. package/dist/oauth2/token-endpoint-auth.d.mts +17 -0
  25. package/dist/oauth2/token-endpoint-auth.mjs +89 -0
  26. package/dist/oauth2/utils.d.mts +9 -1
  27. package/dist/oauth2/utils.mjs +12 -1
  28. package/dist/oauth2/validate-authorization-code.d.mts +17 -52
  29. package/dist/oauth2/validate-authorization-code.mjs +17 -30
  30. package/dist/oauth2/verify.mjs +15 -5
  31. package/dist/social-providers/apple.d.mts +5 -12
  32. package/dist/social-providers/apple.mjs +14 -3
  33. package/dist/social-providers/atlassian.d.mts +3 -1
  34. package/dist/social-providers/atlassian.mjs +5 -2
  35. package/dist/social-providers/cognito.d.mts +16 -1
  36. package/dist/social-providers/cognito.mjs +6 -2
  37. package/dist/social-providers/discord.d.mts +5 -3
  38. package/dist/social-providers/discord.mjs +16 -3
  39. package/dist/social-providers/dropbox.d.mts +3 -1
  40. package/dist/social-providers/dropbox.mjs +5 -4
  41. package/dist/social-providers/facebook.d.mts +5 -3
  42. package/dist/social-providers/facebook.mjs +6 -3
  43. package/dist/social-providers/figma.d.mts +3 -1
  44. package/dist/social-providers/figma.mjs +3 -2
  45. package/dist/social-providers/github.d.mts +4 -2
  46. package/dist/social-providers/github.mjs +5 -4
  47. package/dist/social-providers/gitlab.d.mts +3 -1
  48. package/dist/social-providers/gitlab.mjs +3 -2
  49. package/dist/social-providers/google.d.mts +3 -1
  50. package/dist/social-providers/google.mjs +5 -2
  51. package/dist/social-providers/huggingface.d.mts +3 -1
  52. package/dist/social-providers/huggingface.mjs +3 -2
  53. package/dist/social-providers/index.d.mts +104 -36
  54. package/dist/social-providers/kakao.d.mts +3 -1
  55. package/dist/social-providers/kakao.mjs +3 -2
  56. package/dist/social-providers/kick.d.mts +3 -1
  57. package/dist/social-providers/kick.mjs +3 -2
  58. package/dist/social-providers/line.d.mts +3 -1
  59. package/dist/social-providers/line.mjs +3 -2
  60. package/dist/social-providers/linear.d.mts +3 -1
  61. package/dist/social-providers/linear.mjs +3 -2
  62. package/dist/social-providers/linkedin.d.mts +5 -3
  63. package/dist/social-providers/linkedin.mjs +4 -3
  64. package/dist/social-providers/microsoft-entra-id.d.mts +3 -2
  65. package/dist/social-providers/microsoft-entra-id.mjs +3 -2
  66. package/dist/social-providers/naver.d.mts +3 -1
  67. package/dist/social-providers/naver.mjs +3 -2
  68. package/dist/social-providers/notion.d.mts +3 -1
  69. package/dist/social-providers/notion.mjs +5 -2
  70. package/dist/social-providers/paybin.d.mts +3 -1
  71. package/dist/social-providers/paybin.mjs +3 -2
  72. package/dist/social-providers/paypal.d.mts +3 -1
  73. package/dist/social-providers/paypal.mjs +4 -3
  74. package/dist/social-providers/polar.d.mts +3 -1
  75. package/dist/social-providers/polar.mjs +3 -2
  76. package/dist/social-providers/railway.d.mts +3 -1
  77. package/dist/social-providers/railway.mjs +3 -2
  78. package/dist/social-providers/reddit.d.mts +3 -1
  79. package/dist/social-providers/reddit.mjs +3 -2
  80. package/dist/social-providers/roblox.d.mts +4 -2
  81. package/dist/social-providers/roblox.mjs +12 -2
  82. package/dist/social-providers/salesforce.d.mts +3 -1
  83. package/dist/social-providers/salesforce.mjs +3 -2
  84. package/dist/social-providers/slack.d.mts +4 -2
  85. package/dist/social-providers/slack.mjs +11 -8
  86. package/dist/social-providers/spotify.d.mts +3 -1
  87. package/dist/social-providers/spotify.mjs +3 -2
  88. package/dist/social-providers/tiktok.d.mts +3 -1
  89. package/dist/social-providers/tiktok.mjs +14 -2
  90. package/dist/social-providers/twitch.d.mts +3 -1
  91. package/dist/social-providers/twitch.mjs +3 -2
  92. package/dist/social-providers/twitter.d.mts +5 -2
  93. package/dist/social-providers/twitter.mjs +2 -1
  94. package/dist/social-providers/vercel.d.mts +3 -1
  95. package/dist/social-providers/vercel.mjs +3 -2
  96. package/dist/social-providers/vk.d.mts +3 -1
  97. package/dist/social-providers/vk.mjs +3 -2
  98. package/dist/social-providers/wechat.d.mts +3 -1
  99. package/dist/social-providers/wechat.mjs +7 -1
  100. package/dist/social-providers/zoom.d.mts +4 -2
  101. package/dist/social-providers/zoom.mjs +10 -17
  102. package/dist/types/context.d.mts +30 -4
  103. package/dist/types/init-options.d.mts +29 -5
  104. package/dist/utils/ip.d.mts +5 -4
  105. package/dist/utils/ip.mjs +3 -3
  106. package/dist/utils/redirect-uri.d.mts +20 -0
  107. package/dist/utils/redirect-uri.mjs +48 -0
  108. package/dist/utils/string.d.mts +5 -1
  109. package/dist/utils/string.mjs +20 -1
  110. package/dist/utils/url.d.mts +18 -1
  111. package/dist/utils/url.mjs +30 -1
  112. package/package.json +9 -8
  113. package/src/db/adapter/factory.ts +121 -3
  114. package/src/db/adapter/index.ts +32 -0
  115. package/src/db/adapter/types.ts +1 -0
  116. package/src/db/get-tables.ts +2 -0
  117. package/src/db/schema/user.ts +3 -0
  118. package/src/db/type.ts +12 -0
  119. package/src/error/codes.ts +1 -0
  120. package/src/oauth2/authorization-params.ts +28 -0
  121. package/src/oauth2/basic-credentials.ts +87 -0
  122. package/src/oauth2/client-assertion.ts +131 -58
  123. package/src/oauth2/client-credentials-token.ts +48 -72
  124. package/src/oauth2/create-authorization-url.ts +28 -6
  125. package/src/oauth2/index.ts +25 -9
  126. package/src/oauth2/oauth-provider.ts +21 -2
  127. package/src/oauth2/refresh-access-token.ts +50 -76
  128. package/src/oauth2/token-endpoint-auth.ts +221 -0
  129. package/src/oauth2/utils.ts +19 -0
  130. package/src/oauth2/validate-authorization-code.ts +55 -85
  131. package/src/oauth2/verify.ts +20 -4
  132. package/src/social-providers/apple.ts +27 -3
  133. package/src/social-providers/atlassian.ts +8 -1
  134. package/src/social-providers/cognito.ts +26 -1
  135. package/src/social-providers/discord.ts +22 -18
  136. package/src/social-providers/dropbox.ts +7 -5
  137. package/src/social-providers/facebook.ts +14 -9
  138. package/src/social-providers/figma.ts +8 -1
  139. package/src/social-providers/github.ts +5 -3
  140. package/src/social-providers/gitlab.ts +2 -0
  141. package/src/social-providers/google.ts +2 -0
  142. package/src/social-providers/huggingface.ts +8 -1
  143. package/src/social-providers/kakao.ts +2 -1
  144. package/src/social-providers/kick.ts +8 -1
  145. package/src/social-providers/line.ts +2 -0
  146. package/src/social-providers/linear.ts +8 -1
  147. package/src/social-providers/linkedin.ts +5 -3
  148. package/src/social-providers/microsoft-entra-id.ts +2 -1
  149. package/src/social-providers/naver.ts +2 -1
  150. package/src/social-providers/notion.ts +8 -1
  151. package/src/social-providers/paybin.ts +2 -0
  152. package/src/social-providers/paypal.ts +7 -1
  153. package/src/social-providers/polar.ts +8 -1
  154. package/src/social-providers/railway.ts +8 -1
  155. package/src/social-providers/reddit.ts +2 -1
  156. package/src/social-providers/roblox.ts +16 -11
  157. package/src/social-providers/salesforce.ts +8 -1
  158. package/src/social-providers/slack.ts +15 -9
  159. package/src/social-providers/spotify.ts +8 -1
  160. package/src/social-providers/tiktok.ts +22 -9
  161. package/src/social-providers/twitch.ts +2 -1
  162. package/src/social-providers/twitter.ts +1 -0
  163. package/src/social-providers/vercel.ts +8 -1
  164. package/src/social-providers/vk.ts +8 -1
  165. package/src/social-providers/wechat.ts +9 -1
  166. package/src/social-providers/zoom.ts +15 -19
  167. package/src/types/context.ts +33 -5
  168. package/src/types/init-options.ts +29 -5
  169. package/src/utils/ip.ts +12 -13
  170. package/src/utils/redirect-uri.ts +54 -0
  171. package/src/utils/string.ts +37 -0
  172. package/src/utils/url.ts +28 -0
@@ -1,72 +1,70 @@
1
- import { base64 } from "@better-auth/utils/base64";
2
1
  import { betterFetch } from "@better-fetch/fetch";
3
2
  import type { AwaitableFunction } from "../types";
4
- import type { ClientAssertionConfig } from "./client-assertion";
5
- import { resolveAssertionParams } from "./client-assertion";
6
3
  import type { OAuth2Tokens, ProviderOptions } from "./oauth-provider";
4
+ import type {
5
+ TokenEndpointAuth,
6
+ TokenEndpointSecretAuthentication,
7
+ } from "./token-endpoint-auth";
8
+ import { applyTokenEndpointAuth } from "./token-endpoint-auth";
9
+
10
+ interface ClientCredentialsTokenRequestInput {
11
+ options: AwaitableFunction<ProviderOptions>;
12
+ scope?: string | undefined;
13
+ authentication?: TokenEndpointSecretAuthentication | undefined;
14
+ tokenEndpointAuth?: TokenEndpointAuth | undefined;
15
+ tokenEndpoint?: string | undefined;
16
+ resource?: (string | string[]) | undefined;
17
+ }
18
+
19
+ interface ClientCredentialsTokenRequestBaseInput {
20
+ options: ProviderOptions;
21
+ scope?: string | undefined;
22
+ resource?: (string | string[]) | undefined;
23
+ extraParams?: Record<string, string> | undefined;
24
+ }
25
+
26
+ interface ClientCredentialsTokenInput
27
+ extends ClientCredentialsTokenRequestInput {
28
+ tokenEndpoint: string;
29
+ scope: string;
30
+ }
7
31
 
8
32
  export async function clientCredentialsTokenRequest({
9
33
  options,
10
34
  scope,
11
35
  authentication,
12
- clientAssertion,
36
+ tokenEndpointAuth,
13
37
  tokenEndpoint,
14
38
  resource,
15
- }: {
16
- options: AwaitableFunction<ProviderOptions>;
17
- scope?: string | undefined;
18
- authentication?: ("basic" | "post" | "private_key_jwt") | undefined;
19
- clientAssertion?: ClientAssertionConfig | undefined;
20
- /** Token endpoint URL. Used as the JWT `aud` claim when signing assertions. */
21
- tokenEndpoint?: string | undefined;
22
- resource?: (string | string[]) | undefined;
23
- }) {
39
+ }: ClientCredentialsTokenRequestInput) {
24
40
  options = typeof options === "function" ? await options() : options;
25
-
26
- let extraParams: Record<string, string> | undefined;
27
- if (authentication === "private_key_jwt") {
28
- if (!clientAssertion) {
29
- throw new Error(
30
- "private_key_jwt authentication requires a clientAssertion configuration",
31
- );
32
- }
33
- const primaryClientId = Array.isArray(options.clientId)
34
- ? options.clientId[0]
35
- : options.clientId;
36
- extraParams = await resolveAssertionParams({
37
- clientAssertion,
38
- clientId: primaryClientId,
39
- tokenEndpoint,
40
- });
41
- }
42
-
43
- return createClientCredentialsTokenRequest({
41
+ const request = buildClientCredentialsTokenRequest({
44
42
  options,
45
43
  scope,
46
- authentication,
47
44
  resource,
48
- extraParams,
49
45
  });
46
+
47
+ await applyTokenEndpointAuth({
48
+ body: request.body,
49
+ headers: request.headers,
50
+ options,
51
+ tokenEndpoint: tokenEndpoint ?? "",
52
+ grantType: "client_credentials",
53
+ tokenEndpointAuth,
54
+ authentication,
55
+ });
56
+
57
+ return request;
50
58
  }
51
59
 
52
- /**
53
- * @deprecated use async'd clientCredentialsTokenRequest instead
54
- */
55
- export function createClientCredentialsTokenRequest({
60
+ function buildClientCredentialsTokenRequest({
56
61
  options,
57
62
  scope,
58
- authentication,
59
63
  resource,
60
64
  extraParams,
61
- }: {
62
- options: ProviderOptions;
63
- scope?: string | undefined;
64
- authentication?: ("basic" | "post" | "private_key_jwt") | undefined;
65
- resource?: (string | string[]) | undefined;
66
- extraParams?: Record<string, string> | undefined;
67
- }) {
65
+ }: ClientCredentialsTokenRequestBaseInput) {
68
66
  const body = new URLSearchParams();
69
- const headers: Record<string, any> = {
67
+ const headers: Record<string, string> = {
70
68
  "content-type": "application/x-www-form-urlencoded",
71
69
  accept: "application/json",
72
70
  };
@@ -82,21 +80,6 @@ export function createClientCredentialsTokenRequest({
82
80
  }
83
81
  }
84
82
  }
85
- const primaryClientId = Array.isArray(options.clientId)
86
- ? options.clientId[0]
87
- : options.clientId;
88
- if (authentication === "basic") {
89
- const encodedCredentials = base64.encode(
90
- `${primaryClientId}:${options.clientSecret ?? ""}`,
91
- );
92
- headers["authorization"] = `Basic ${encodedCredentials}`;
93
- } else {
94
- body.set("client_id", primaryClientId);
95
- if (authentication !== "private_key_jwt" && options.clientSecret) {
96
- body.set("client_secret", options.clientSecret);
97
- }
98
- }
99
-
100
83
  if (extraParams) {
101
84
  for (const [key, value] of Object.entries(extraParams)) {
102
85
  if (!body.has(key)) body.append(key, value);
@@ -114,21 +97,14 @@ export async function clientCredentialsToken({
114
97
  tokenEndpoint,
115
98
  scope,
116
99
  authentication,
117
- clientAssertion,
100
+ tokenEndpointAuth,
118
101
  resource,
119
- }: {
120
- options: AwaitableFunction<ProviderOptions>;
121
- tokenEndpoint: string;
122
- scope: string;
123
- authentication?: ("basic" | "post" | "private_key_jwt") | undefined;
124
- clientAssertion?: ClientAssertionConfig | undefined;
125
- resource?: (string | string[]) | undefined;
126
- }): Promise<OAuth2Tokens> {
102
+ }: ClientCredentialsTokenInput): Promise<OAuth2Tokens> {
127
103
  const { body, headers } = await clientCredentialsTokenRequest({
128
104
  options,
129
105
  scope,
130
106
  authentication,
131
- clientAssertion,
107
+ tokenEndpointAuth,
132
108
  tokenEndpoint,
133
109
  resource,
134
110
  });
@@ -1,6 +1,26 @@
1
1
  import type { AwaitableFunction } from "../types";
2
2
  import type { ProviderOptions } from "./index";
3
- import { generateCodeChallenge } from "./utils";
3
+ import { generateCodeChallenge, getPrimaryClientId } from "./utils";
4
+
5
+ /**
6
+ * Query-parameter names that are populated by the framework as part of the
7
+ * authorization request and must not be overridden by caller-supplied
8
+ * `additionalParams`. Overriding `state`, PKCE, or `redirect_uri` would
9
+ * break the callback correlation and session pinning guarantees.
10
+ */
11
+ export const RESERVED_AUTHORIZATION_PARAMS = [
12
+ "state",
13
+ "client_id",
14
+ "redirect_uri",
15
+ "response_type",
16
+ "code_challenge",
17
+ "code_challenge_method",
18
+ "scope",
19
+ ] as const;
20
+
21
+ export const RESERVED_AUTHORIZATION_PARAMS_SET: ReadonlySet<string> = new Set(
22
+ RESERVED_AUTHORIZATION_PARAMS,
23
+ );
4
24
 
5
25
  export async function createAuthorizationURL({
6
26
  id,
@@ -44,9 +64,10 @@ export async function createAuthorizationURL({
44
64
  options = typeof options === "function" ? await options() : options;
45
65
  const url = new URL(options.authorizationEndpoint || authorizationEndpoint);
46
66
  url.searchParams.set("response_type", responseType || "code");
47
- const primaryClientId = Array.isArray(options.clientId)
48
- ? options.clientId[0]
49
- : options.clientId;
67
+ const primaryClientId = getPrimaryClientId(options.clientId);
68
+ if (!primaryClientId) {
69
+ throw new Error("OAuth provider requires clientId");
70
+ }
50
71
  url.searchParams.set("client_id", primaryClientId);
51
72
  url.searchParams.set("state", state);
52
73
  if (scopes) {
@@ -81,9 +102,10 @@ export async function createAuthorizationURL({
81
102
  );
82
103
  }
83
104
  if (additionalParams) {
84
- Object.entries(additionalParams).forEach(([key, value]) => {
105
+ for (const [key, value] of Object.entries(additionalParams)) {
106
+ if (RESERVED_AUTHORIZATION_PARAMS_SET.has(key)) continue;
85
107
  url.searchParams.set(key, value);
86
- });
108
+ }
87
109
  }
88
110
  return url;
89
111
  }
@@ -1,19 +1,31 @@
1
+ export { additionalAuthorizationParamsSchema } from "./authorization-params";
2
+ export {
3
+ decodeBasicCredentials,
4
+ encodeBasicCredentials,
5
+ } from "./basic-credentials";
1
6
  export type {
2
- AssertionSigningAlgorithm,
3
- ClientAssertionConfig,
7
+ ClientAssertionContext,
8
+ ClientAssertionGetter,
9
+ ClientAssertionGrantType,
10
+ PrivateKeyJwtClientAssertionGetterOptions,
11
+ PrivateKeyJwtSigningAlgorithm,
4
12
  } from "./client-assertion";
5
13
  export {
6
- ASSERTION_SIGNING_ALGORITHMS,
7
14
  CLIENT_ASSERTION_TYPE,
8
- resolveAssertionParams,
9
- signClientAssertion,
15
+ createPrivateKeyJwtClientAssertionGetter,
16
+ PRIVATE_KEY_JWT_SIGNING_ALGORITHMS,
17
+ resolveClientAssertionParams,
18
+ signPrivateKeyJwtClientAssertion,
10
19
  } from "./client-assertion";
11
20
  export {
12
21
  clientCredentialsToken,
13
22
  clientCredentialsTokenRequest,
14
- createClientCredentialsTokenRequest,
15
23
  } from "./client-credentials-token";
16
- export { createAuthorizationURL } from "./create-authorization-url";
24
+ export {
25
+ createAuthorizationURL,
26
+ RESERVED_AUTHORIZATION_PARAMS,
27
+ RESERVED_AUTHORIZATION_PARAMS_SET,
28
+ } from "./create-authorization-url";
17
29
  export type {
18
30
  OAuth2Tokens,
19
31
  OAuth2UserInfo,
@@ -21,18 +33,22 @@ export type {
21
33
  ProviderOptions,
22
34
  } from "./oauth-provider";
23
35
  export {
24
- createRefreshAccessTokenRequest,
25
36
  refreshAccessToken,
26
37
  refreshAccessTokenRequest,
27
38
  } from "./refresh-access-token";
39
+ export type {
40
+ TokenEndpointAuth,
41
+ TokenEndpointAuthMethod,
42
+ TokenEndpointSecretAuthentication,
43
+ } from "./token-endpoint-auth";
28
44
  export {
45
+ applyDefaultAccessTokenExpiry,
29
46
  generateCodeChallenge,
30
47
  getOAuth2Tokens,
31
48
  getPrimaryClientId,
32
49
  } from "./utils";
33
50
  export {
34
51
  authorizationCodeRequest,
35
- createAuthorizationCodeRequest,
36
52
  validateAuthorizationCode,
37
53
  validateToken,
38
54
  } from "./validate-authorization-code";
@@ -35,6 +35,13 @@ export interface OAuthProvider<
35
35
  redirectURI: string;
36
36
  display?: string | undefined;
37
37
  loginHint?: string | undefined;
38
+ /**
39
+ * Extra query parameters to append to the authorization URL.
40
+ * Providers forward these to the shared `createAuthorizationURL` helper,
41
+ * which drops any keys present in `RESERVED_AUTHORIZATION_PARAMS`
42
+ * before applying them.
43
+ */
44
+ additionalParams?: Record<string, string> | undefined;
38
45
  }) => Awaitable<URL>;
39
46
  name: string;
40
47
  validateAuthorizationCode: (data: {
@@ -94,6 +101,17 @@ export interface OAuthProvider<
94
101
  * Disable sign up for new users.
95
102
  */
96
103
  disableSignUp?: boolean | undefined;
104
+ /**
105
+ * Accept callbacks that arrive without a `state` parameter. When true,
106
+ * the shared OAuth callback handler restarts the flow server-side with
107
+ * fresh `state` and PKCE instead of rejecting the request. Intended for
108
+ * providers that initiate OAuth without RP-side flow kickoff (e.g.
109
+ * Clever). Leave unset for any provider that always initiates from the
110
+ * RP.
111
+ *
112
+ * @default false
113
+ */
114
+ allowIdpInitiated?: boolean | undefined;
97
115
  /**
98
116
  * Options for the provider
99
117
  */
@@ -104,9 +122,10 @@ export type ProviderOptions<Profile extends Record<string, any> = any> = {
104
122
  /**
105
123
  * The client ID of your application.
106
124
  *
107
- * This is usually a string but can be any type depending on the provider.
125
+ * Some providers accept multiple platform client IDs. The first entry is the
126
+ * primary client ID used for token endpoint client authentication.
108
127
  */
109
- clientId?: unknown | undefined;
128
+ clientId?: LiteralString | string[] | undefined;
110
129
  /**
111
130
  * The client secret of your application
112
131
  */
@@ -1,99 +1,78 @@
1
- import { base64 } from "@better-auth/utils/base64";
2
1
  import { betterFetch } from "@better-fetch/fetch";
3
2
  import type { AwaitableFunction } from "../types";
4
- import type { ClientAssertionConfig } from "./client-assertion";
5
- import { resolveAssertionParams } from "./client-assertion";
6
3
  import type { OAuth2Tokens, ProviderOptions } from "./oauth-provider";
4
+ import type {
5
+ TokenEndpointAuth,
6
+ TokenEndpointSecretAuthentication,
7
+ } from "./token-endpoint-auth";
8
+ import { applyTokenEndpointAuth } from "./token-endpoint-auth";
9
+
10
+ interface RefreshAccessTokenRequestInput {
11
+ refreshToken: string;
12
+ options: AwaitableFunction<Partial<ProviderOptions>>;
13
+ authentication?: TokenEndpointSecretAuthentication | undefined;
14
+ tokenEndpointAuth?: TokenEndpointAuth | undefined;
15
+ tokenEndpoint?: string | undefined;
16
+ extraParams?: Record<string, string> | undefined;
17
+ resource?: (string | string[]) | undefined;
18
+ }
19
+
20
+ interface RefreshAccessTokenRequestBaseInput {
21
+ refreshToken: string;
22
+ options: ProviderOptions;
23
+ extraParams?: Record<string, string> | undefined;
24
+ resource?: (string | string[]) | undefined;
25
+ }
26
+
27
+ interface RefreshAccessTokenInput extends RefreshAccessTokenRequestInput {
28
+ options: Partial<ProviderOptions>;
29
+ tokenEndpoint: string;
30
+ }
7
31
 
8
32
  export async function refreshAccessTokenRequest({
9
33
  refreshToken,
10
34
  options,
11
35
  authentication,
12
- clientAssertion,
36
+ tokenEndpointAuth,
13
37
  tokenEndpoint,
14
38
  extraParams,
15
39
  resource,
16
- }: {
17
- refreshToken: string;
18
- options: AwaitableFunction<Partial<ProviderOptions>>;
19
- authentication?: ("basic" | "post" | "private_key_jwt") | undefined;
20
- clientAssertion?: ClientAssertionConfig | undefined;
21
- /** Token endpoint URL. Used as the JWT `aud` claim when signing assertions. */
22
- tokenEndpoint?: string | undefined;
23
- extraParams?: Record<string, string> | undefined;
24
- resource?: (string | string[]) | undefined;
25
- }) {
40
+ }: RefreshAccessTokenRequestInput) {
26
41
  options = typeof options === "function" ? await options() : options;
27
-
28
- if (authentication === "private_key_jwt") {
29
- if (!clientAssertion) {
30
- throw new Error(
31
- "private_key_jwt authentication requires a clientAssertion configuration",
32
- );
33
- }
34
- const primaryClientId = Array.isArray(options.clientId)
35
- ? options.clientId[0]
36
- : options.clientId;
37
- const assertionParams = await resolveAssertionParams({
38
- clientAssertion,
39
- clientId: primaryClientId,
40
- tokenEndpoint,
41
- });
42
- extraParams = { ...extraParams, ...assertionParams };
43
- }
44
-
45
- return createRefreshAccessTokenRequest({
42
+ const request = buildRefreshAccessTokenRequest({
46
43
  refreshToken,
47
44
  options,
48
- authentication,
49
45
  extraParams,
50
46
  resource,
51
47
  });
48
+
49
+ await applyTokenEndpointAuth({
50
+ body: request.body,
51
+ headers: request.headers,
52
+ options,
53
+ tokenEndpoint: tokenEndpoint ?? "",
54
+ grantType: "refresh_token",
55
+ tokenEndpointAuth,
56
+ authentication,
57
+ });
58
+
59
+ return request;
52
60
  }
53
61
 
54
- /**
55
- * @deprecated use async'd refreshAccessTokenRequest instead
56
- */
57
- export function createRefreshAccessTokenRequest({
62
+ function buildRefreshAccessTokenRequest({
58
63
  refreshToken,
59
64
  options,
60
- authentication,
61
65
  extraParams,
62
66
  resource,
63
- }: {
64
- refreshToken: string;
65
- options: ProviderOptions;
66
- authentication?: ("basic" | "post" | "private_key_jwt") | undefined;
67
- extraParams?: Record<string, string> | undefined;
68
- resource?: (string | string[]) | undefined;
69
- }) {
67
+ }: RefreshAccessTokenRequestBaseInput) {
70
68
  const body = new URLSearchParams();
71
- const headers: Record<string, any> = {
69
+ const headers: Record<string, string> = {
72
70
  "content-type": "application/x-www-form-urlencoded",
73
71
  accept: "application/json",
74
72
  };
75
73
 
76
74
  body.set("grant_type", "refresh_token");
77
75
  body.set("refresh_token", refreshToken);
78
- const primaryClientId = Array.isArray(options.clientId)
79
- ? options.clientId[0]
80
- : options.clientId;
81
- if (authentication === "basic") {
82
- if (primaryClientId) {
83
- headers["authorization"] =
84
- "Basic " +
85
- base64.encode(`${primaryClientId}:${options.clientSecret ?? ""}`);
86
- } else {
87
- headers["authorization"] =
88
- "Basic " + base64.encode(`:${options.clientSecret ?? ""}`);
89
- }
90
- } else {
91
- body.set("client_id", primaryClientId);
92
- if (authentication !== "private_key_jwt" && options.clientSecret) {
93
- body.set("client_secret", options.clientSecret);
94
- }
95
- }
96
-
97
76
  if (resource) {
98
77
  if (typeof resource === "string") {
99
78
  body.append("resource", resource);
@@ -120,23 +99,18 @@ export async function refreshAccessToken({
120
99
  options,
121
100
  tokenEndpoint,
122
101
  authentication,
123
- clientAssertion,
102
+ tokenEndpointAuth,
124
103
  extraParams,
125
- }: {
126
- refreshToken: string;
127
- options: Partial<ProviderOptions>;
128
- tokenEndpoint: string;
129
- authentication?: ("basic" | "post" | "private_key_jwt") | undefined;
130
- clientAssertion?: ClientAssertionConfig | undefined;
131
- extraParams?: Record<string, string> | undefined;
132
- }): Promise<OAuth2Tokens> {
104
+ resource,
105
+ }: RefreshAccessTokenInput): Promise<OAuth2Tokens> {
133
106
  const { body, headers } = await refreshAccessTokenRequest({
134
107
  refreshToken,
135
108
  options,
136
109
  authentication,
137
- clientAssertion,
110
+ tokenEndpointAuth,
138
111
  tokenEndpoint,
139
112
  extraParams,
113
+ resource,
140
114
  });
141
115
 
142
116
  const { data, error } = await betterFetch<{