@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
@@ -2,7 +2,7 @@ import { BetterAuthDBSchema, ModelNames, SecondaryStorage } from "../db/type.mjs
2
2
  import { DBAdapter } from "../db/adapter/index.mjs";
3
3
  import { createLogger } from "../env/logger.mjs";
4
4
  import { AuthContext } from "../types/context.mjs";
5
- import { UpstreamProvider } from "../oauth2/oauth-provider.mjs";
5
+ import { OAuthProvider } from "../oauth2/oauth-provider.mjs";
6
6
  import * as better_call0 from "better-call";
7
7
  import { EndpointContext, EndpointOptions, StrictEndpoint } from "better-call";
8
8
  import * as _better_auth_core0 from "@better-auth/core";
@@ -105,7 +105,7 @@ declare const createAuthMiddleware: {
105
105
  image?: string | null | undefined;
106
106
  } & Record<string, any>;
107
107
  } | null) => void;
108
- socialProviders: UpstreamProvider[];
108
+ socialProviders: OAuthProvider[];
109
109
  authCookies: _better_auth_core0.BetterAuthCookies;
110
110
  logger: ReturnType<typeof createLogger>;
111
111
  rateLimit: {
@@ -234,7 +234,7 @@ declare const createAuthMiddleware: {
234
234
  image?: string | null | undefined;
235
235
  } & Record<string, any>;
236
236
  } | null) => void;
237
- socialProviders: UpstreamProvider[];
237
+ socialProviders: OAuthProvider[];
238
238
  authCookies: _better_auth_core0.BetterAuthCookies;
239
239
  logger: ReturnType<typeof createLogger>;
240
240
  rateLimit: {
@@ -2,7 +2,7 @@
2
2
  const symbol = Symbol.for("better-auth:global");
3
3
  let bind = null;
4
4
  const __context = {};
5
- const __betterAuthVersion = "1.7.0-beta.6";
5
+ const __betterAuthVersion = "1.7.0-beta.8";
6
6
  /**
7
7
  * We store context instance in the globalThis.
8
8
  *
@@ -228,10 +228,10 @@ const getAuthTables = (options) => {
228
228
  returned: false,
229
229
  fieldName: options.account?.fields?.refreshTokenExpiresAt || "refreshTokenExpiresAt"
230
230
  },
231
- grantedScopes: {
232
- type: "string[]",
231
+ scope: {
232
+ type: "string",
233
233
  required: false,
234
- fieldName: options.account?.fields?.grantedScopes || "grantedScopes"
234
+ fieldName: options.account?.fields?.scope || "scope"
235
235
  },
236
236
  password: {
237
237
  type: "string",
@@ -16,7 +16,7 @@ declare const accountSchema: z.ZodObject<{
16
16
  idToken: z.ZodOptional<z.ZodNullable<z.ZodString>>;
17
17
  accessTokenExpiresAt: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
18
18
  refreshTokenExpiresAt: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
19
- grantedScopes: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
19
+ scope: z.ZodOptional<z.ZodNullable<z.ZodString>>;
20
20
  password: z.ZodOptional<z.ZodNullable<z.ZodString>>;
21
21
  }, z.core.$strip>;
22
22
  type BaseAccount = z.infer<typeof accountSchema>;
@@ -10,7 +10,7 @@ const accountSchema = coreSchema.extend({
10
10
  idToken: z.string().nullish(),
11
11
  accessTokenExpiresAt: z.date().nullish(),
12
12
  refreshTokenExpiresAt: z.date().nullish(),
13
- grantedScopes: z.array(z.string()).nullish(),
13
+ scope: z.string().nullish(),
14
14
  password: z.string().nullish()
15
15
  });
16
16
  //#endregion
@@ -29,11 +29,6 @@ declare const BASE_ERROR_CODES: {
29
29
  TOKEN_EXPIRED: RawError<"TOKEN_EXPIRED">;
30
30
  ID_TOKEN_NOT_SUPPORTED: RawError<"ID_TOKEN_NOT_SUPPORTED">;
31
31
  FAILED_TO_GET_USER_INFO: RawError<"FAILED_TO_GET_USER_INFO">;
32
- PROVIDER_NOT_SUPPORTED: RawError<"PROVIDER_NOT_SUPPORTED">;
33
- TOKEN_REFRESH_NOT_SUPPORTED: RawError<"TOKEN_REFRESH_NOT_SUPPORTED">;
34
- REFRESH_TOKEN_NOT_FOUND: RawError<"REFRESH_TOKEN_NOT_FOUND">;
35
- FAILED_TO_GET_ACCESS_TOKEN: RawError<"FAILED_TO_GET_ACCESS_TOKEN">;
36
- FAILED_TO_REFRESH_ACCESS_TOKEN: RawError<"FAILED_TO_REFRESH_ACCESS_TOKEN">;
37
32
  USER_EMAIL_NOT_FOUND: RawError<"USER_EMAIL_NOT_FOUND">;
38
33
  EMAIL_NOT_VERIFIED: RawError<"EMAIL_NOT_VERIFIED">;
39
34
  PASSWORD_TOO_SHORT: RawError<"PASSWORD_TOO_SHORT">;
@@ -16,11 +16,6 @@ const BASE_ERROR_CODES = defineErrorCodes({
16
16
  TOKEN_EXPIRED: "Token expired",
17
17
  ID_TOKEN_NOT_SUPPORTED: "id_token not supported",
18
18
  FAILED_TO_GET_USER_INFO: "Failed to get user info",
19
- PROVIDER_NOT_SUPPORTED: "Provider not supported",
20
- TOKEN_REFRESH_NOT_SUPPORTED: "Token refresh not supported",
21
- REFRESH_TOKEN_NOT_FOUND: "Refresh token not found",
22
- FAILED_TO_GET_ACCESS_TOKEN: "Failed to get a valid access token",
23
- FAILED_TO_REFRESH_ACCESS_TOKEN: "Failed to refresh access token",
24
19
  USER_EMAIL_NOT_FOUND: "User email not found",
25
20
  EMAIL_NOT_VERIFIED: "Email not verified",
26
21
  PASSWORD_TOO_SHORT: "Password too short",
@@ -2,7 +2,7 @@ import { ATTR_HTTP_RESPONSE_STATUS_CODE } from "./attributes.mjs";
2
2
  import { getOpenTelemetryAPI } from "./api.mjs";
3
3
  //#region src/instrumentation/tracer.ts
4
4
  const INSTRUMENTATION_SCOPE = "better-auth";
5
- const INSTRUMENTATION_VERSION = "1.7.0-beta.6";
5
+ const INSTRUMENTATION_VERSION = "1.7.0-beta.8";
6
6
  /**
7
7
  * Better-auth uses `throw ctx.redirect(url)` for flow control (e.g. OAuth
8
8
  * callbacks). These are APIErrors with 3xx status codes and should not be
@@ -7,7 +7,7 @@ import { ProviderOptions } from "./oauth-provider.mjs";
7
7
  * `additionalParams`. Overriding `state`, PKCE, or `redirect_uri` would
8
8
  * break the callback correlation and session pinning guarantees.
9
9
  */
10
- declare const RESERVED_AUTHORIZATION_PARAMS: readonly ["state", "client_id", "redirect_uri", "response_type", "code_challenge", "code_challenge_method", "scope"];
10
+ declare const RESERVED_AUTHORIZATION_PARAMS: readonly ["state", "client_id", "redirect_uri", "response_type", "code_challenge", "code_challenge_method", "nonce", "scope"];
11
11
  declare const RESERVED_AUTHORIZATION_PARAMS_SET: ReadonlySet<string>;
12
12
  declare function createAuthorizationURL({
13
13
  id,
@@ -24,6 +24,7 @@ declare function createAuthorizationURL({
24
24
  responseType,
25
25
  display,
26
26
  loginHint,
27
+ nonce,
27
28
  hd,
28
29
  responseMode,
29
30
  additionalParams,
@@ -43,13 +44,11 @@ declare function createAuthorizationURL({
43
44
  responseType?: string | undefined;
44
45
  display?: string | undefined;
45
46
  loginHint?: string | undefined;
47
+ nonce?: string | undefined;
46
48
  hd?: string | undefined;
47
49
  responseMode?: string | undefined;
48
50
  additionalParams?: Record<string, string> | undefined;
49
51
  scopeJoiner?: string | undefined;
50
- }): Promise<{
51
- url: URL;
52
- requestedScopes: string[];
53
- }>;
52
+ }): Promise<URL>;
54
53
  //#endregion
55
54
  export { RESERVED_AUTHORIZATION_PARAMS, RESERVED_AUTHORIZATION_PARAMS_SET, createAuthorizationURL };
@@ -13,10 +13,11 @@ const RESERVED_AUTHORIZATION_PARAMS = [
13
13
  "response_type",
14
14
  "code_challenge",
15
15
  "code_challenge_method",
16
+ "nonce",
16
17
  "scope"
17
18
  ];
18
19
  const RESERVED_AUTHORIZATION_PARAMS_SET = new Set(RESERVED_AUTHORIZATION_PARAMS);
19
- async function createAuthorizationURL({ id, options, authorizationEndpoint, state, codeVerifier, scopes, claims, redirectURI, duration, prompt, accessType, responseType, display, loginHint, hd, responseMode, additionalParams, scopeJoiner }) {
20
+ async function createAuthorizationURL({ id, options, authorizationEndpoint, state, codeVerifier, scopes, claims, redirectURI, duration, prompt, accessType, responseType, display, loginHint, nonce, hd, responseMode, additionalParams, scopeJoiner }) {
20
21
  options = typeof options === "function" ? await options() : options;
21
22
  const url = new URL(options.authorizationEndpoint || authorizationEndpoint);
22
23
  url.searchParams.set("response_type", responseType || "code");
@@ -29,6 +30,7 @@ async function createAuthorizationURL({ id, options, authorizationEndpoint, stat
29
30
  duration && url.searchParams.set("duration", duration);
30
31
  display && url.searchParams.set("display", display);
31
32
  loginHint && url.searchParams.set("login_hint", loginHint);
33
+ nonce && url.searchParams.set("nonce", nonce);
32
34
  prompt && url.searchParams.set("prompt", prompt);
33
35
  hd && url.searchParams.set("hd", hd);
34
36
  accessType && url.searchParams.set("access_type", accessType);
@@ -53,10 +55,7 @@ async function createAuthorizationURL({ id, options, authorizationEndpoint, stat
53
55
  if (RESERVED_AUTHORIZATION_PARAMS_SET.has(key)) continue;
54
56
  url.searchParams.set(key, value);
55
57
  }
56
- return {
57
- url,
58
- requestedScopes: scopes ?? []
59
- };
58
+ return url;
60
59
  }
61
60
  //#endregion
62
61
  export { RESERVED_AUTHORIZATION_PARAMS, RESERVED_AUTHORIZATION_PARAMS_SET, createAuthorizationURL };
@@ -1,15 +1,14 @@
1
1
  import { additionalAuthorizationParamsSchema } from "./authorization-params.mjs";
2
2
  import { decodeBasicCredentials, encodeBasicCredentials } from "./basic-credentials.mjs";
3
3
  import { CLIENT_ASSERTION_TYPE, ClientAssertionContext, ClientAssertionGetter, ClientAssertionGrantType, PRIVATE_KEY_JWT_SIGNING_ALGORITHMS, PrivateKeyJwtClientAssertionGetterOptions, PrivateKeyJwtSigningAlgorithm, createPrivateKeyJwtClientAssertionGetter, resolveClientAssertionParams, signPrivateKeyJwtClientAssertion } from "./client-assertion.mjs";
4
- import { AuthorizationURLResult, GrantAuthority, OAuth2Tokens, OAuth2UserInfo, OAuthIdTokenConfig, ProviderGrantAuthority, ProviderOptions, UpstreamProvider } from "./oauth-provider.mjs";
4
+ import { OAuth2Tokens, OAuth2UserInfo, OAuthIdTokenConfig, OAuthProvider, OAuthRefreshContext, ProviderOptions } from "./oauth-provider.mjs";
5
5
  import { TokenEndpointAuth, TokenEndpointAuthMethod, TokenEndpointSecretAuthentication } from "./token-endpoint-auth.mjs";
6
6
  import { clientCredentialsToken, clientCredentialsTokenRequest } from "./client-credentials-token.mjs";
7
7
  import { RESERVED_AUTHORIZATION_PARAMS, RESERVED_AUTHORIZATION_PARAMS_SET, createAuthorizationURL } from "./create-authorization-url.mjs";
8
8
  import { AccessTokenAuthorization, AccessTokenAuthorizationScheme, BEARER_AUTHORIZATION_SCHEME, DPOP_AUTHORIZATION_SCHEME, DPOP_PROOF_TYPE, DPOP_SIGNING_ALGORITHMS, DpopBindingError, DpopBindingErrorCode, DpopProofError, DpopProofErrorCode, DpopReplayReservation, DpopReplayReservations, DpopReplayStore, DpopSigningAlgorithm, EnforceDpopBindingParams, VerifiedDpopProof, VerifyDpopProofOptions, createDpopBindingError, createDpopProofError, createDpopReplayStore, createInMemoryDpopReplayStore, deriveDpopAth, deriveDpopJkt, enforceDpopBinding, getConfirmationJkt, getDpopJktFromPayload, isDpopBindingError, isDpopProofError, normalizeDpopHtu, parseAccessTokenAuthorization, stripAccessTokenAuthorizationScheme, verifyDpopProof } from "./dpop.mjs";
9
9
  import { refreshAccessToken, refreshAccessTokenRequest } from "./refresh-access-token.mjs";
10
- import { includesGrantedScope, normalizeScopes, parseScopeField, readGrantedScopes, resolveRequestedScopes, unionGrantedScopes } from "./scopes.mjs";
11
- import { applyDefaultAccessTokenExpiry, generateCodeChallenge, getOAuth2Tokens, getPrimaryClientId } from "./utils.mjs";
10
+ import { applyDefaultAccessTokenExpiry, generateCodeChallenge, getOAuth2Tokens, getPrimaryClientId, mergeScopes } from "./utils.mjs";
12
11
  import { authorizationCodeRequest, validateAuthorizationCode, validateToken } from "./validate-authorization-code.mjs";
13
12
  import { ResourceRequestInput, VerifyAccessTokenOptions, VerifyAccessTokenRequestOptions, getJwks, requestToResourceInput, verifyAccessTokenRequest, verifyBearerToken, verifyJwsAccessToken } from "./verify.mjs";
14
13
  import { supportsIdTokenSignIn, verifyProviderIdToken } from "./verify-id-token.mjs";
15
- export { type AccessTokenAuthorization, type AccessTokenAuthorizationScheme, type AuthorizationURLResult, BEARER_AUTHORIZATION_SCHEME, CLIENT_ASSERTION_TYPE, type ClientAssertionContext, type ClientAssertionGetter, type ClientAssertionGrantType, DPOP_AUTHORIZATION_SCHEME, DPOP_PROOF_TYPE, DPOP_SIGNING_ALGORITHMS, type DpopBindingError, type DpopBindingErrorCode, type DpopProofError, type DpopProofErrorCode, type DpopReplayReservation, type DpopReplayReservations, type DpopReplayStore, type DpopSigningAlgorithm, type EnforceDpopBindingParams, type GrantAuthority, type OAuth2Tokens, type OAuth2UserInfo, type OAuthIdTokenConfig, PRIVATE_KEY_JWT_SIGNING_ALGORITHMS, type PrivateKeyJwtClientAssertionGetterOptions, type PrivateKeyJwtSigningAlgorithm, type ProviderGrantAuthority, type ProviderOptions, RESERVED_AUTHORIZATION_PARAMS, RESERVED_AUTHORIZATION_PARAMS_SET, type ResourceRequestInput, type TokenEndpointAuth, type TokenEndpointAuthMethod, type TokenEndpointSecretAuthentication, type UpstreamProvider, type VerifiedDpopProof, type VerifyAccessTokenOptions, type VerifyAccessTokenRequestOptions, type VerifyDpopProofOptions, additionalAuthorizationParamsSchema, applyDefaultAccessTokenExpiry, authorizationCodeRequest, clientCredentialsToken, clientCredentialsTokenRequest, createAuthorizationURL, createDpopBindingError, createDpopProofError, createDpopReplayStore, createInMemoryDpopReplayStore, createPrivateKeyJwtClientAssertionGetter, decodeBasicCredentials, deriveDpopAth, deriveDpopJkt, encodeBasicCredentials, enforceDpopBinding, generateCodeChallenge, getConfirmationJkt, getDpopJktFromPayload, getJwks, getOAuth2Tokens, getPrimaryClientId, includesGrantedScope, isDpopBindingError, isDpopProofError, normalizeDpopHtu, normalizeScopes, parseAccessTokenAuthorization, parseScopeField, readGrantedScopes, refreshAccessToken, refreshAccessTokenRequest, requestToResourceInput, resolveClientAssertionParams, resolveRequestedScopes, signPrivateKeyJwtClientAssertion, stripAccessTokenAuthorizationScheme, supportsIdTokenSignIn, unionGrantedScopes, validateAuthorizationCode, validateToken, verifyAccessTokenRequest, verifyBearerToken, verifyDpopProof, verifyJwsAccessToken, verifyProviderIdToken };
14
+ export { type AccessTokenAuthorization, type AccessTokenAuthorizationScheme, BEARER_AUTHORIZATION_SCHEME, CLIENT_ASSERTION_TYPE, type ClientAssertionContext, type ClientAssertionGetter, type ClientAssertionGrantType, DPOP_AUTHORIZATION_SCHEME, DPOP_PROOF_TYPE, DPOP_SIGNING_ALGORITHMS, type DpopBindingError, type DpopBindingErrorCode, type DpopProofError, type DpopProofErrorCode, type DpopReplayReservation, type DpopReplayReservations, type DpopReplayStore, type DpopSigningAlgorithm, type EnforceDpopBindingParams, type OAuth2Tokens, type OAuth2UserInfo, type OAuthIdTokenConfig, type OAuthProvider, type OAuthRefreshContext, PRIVATE_KEY_JWT_SIGNING_ALGORITHMS, type PrivateKeyJwtClientAssertionGetterOptions, type PrivateKeyJwtSigningAlgorithm, type ProviderOptions, RESERVED_AUTHORIZATION_PARAMS, RESERVED_AUTHORIZATION_PARAMS_SET, type ResourceRequestInput, type TokenEndpointAuth, type TokenEndpointAuthMethod, type TokenEndpointSecretAuthentication, type VerifiedDpopProof, type VerifyAccessTokenOptions, type VerifyAccessTokenRequestOptions, type VerifyDpopProofOptions, additionalAuthorizationParamsSchema, applyDefaultAccessTokenExpiry, authorizationCodeRequest, clientCredentialsToken, clientCredentialsTokenRequest, createAuthorizationURL, createDpopBindingError, createDpopProofError, createDpopReplayStore, createInMemoryDpopReplayStore, createPrivateKeyJwtClientAssertionGetter, decodeBasicCredentials, deriveDpopAth, deriveDpopJkt, encodeBasicCredentials, enforceDpopBinding, generateCodeChallenge, getConfirmationJkt, getDpopJktFromPayload, getJwks, getOAuth2Tokens, getPrimaryClientId, isDpopBindingError, isDpopProofError, mergeScopes, normalizeDpopHtu, parseAccessTokenAuthorization, refreshAccessToken, refreshAccessTokenRequest, requestToResourceInput, resolveClientAssertionParams, signPrivateKeyJwtClientAssertion, stripAccessTokenAuthorizationScheme, supportsIdTokenSignIn, validateAuthorizationCode, validateToken, verifyAccessTokenRequest, verifyBearerToken, verifyDpopProof, verifyJwsAccessToken, verifyProviderIdToken };
@@ -1,5 +1,4 @@
1
- import { includesGrantedScope, normalizeScopes, parseScopeField, readGrantedScopes, resolveRequestedScopes, unionGrantedScopes } from "./scopes.mjs";
2
- import { applyDefaultAccessTokenExpiry, generateCodeChallenge, getOAuth2Tokens, getPrimaryClientId } from "./utils.mjs";
1
+ import { applyDefaultAccessTokenExpiry, generateCodeChallenge, getOAuth2Tokens, getPrimaryClientId, mergeScopes } from "./utils.mjs";
3
2
  import { RESERVED_AUTHORIZATION_PARAMS, RESERVED_AUTHORIZATION_PARAMS_SET, createAuthorizationURL } from "./create-authorization-url.mjs";
4
3
  import { additionalAuthorizationParamsSchema } from "./authorization-params.mjs";
5
4
  import { decodeBasicCredentials, encodeBasicCredentials } from "./basic-credentials.mjs";
@@ -10,4 +9,4 @@ import { refreshAccessToken, refreshAccessTokenRequest } from "./refresh-access-
10
9
  import { authorizationCodeRequest, validateAuthorizationCode, validateToken } from "./validate-authorization-code.mjs";
11
10
  import { getJwks, requestToResourceInput, verifyAccessTokenRequest, verifyBearerToken, verifyJwsAccessToken } from "./verify.mjs";
12
11
  import { supportsIdTokenSignIn, verifyProviderIdToken } from "./verify-id-token.mjs";
13
- export { BEARER_AUTHORIZATION_SCHEME, CLIENT_ASSERTION_TYPE, DPOP_AUTHORIZATION_SCHEME, DPOP_PROOF_TYPE, DPOP_SIGNING_ALGORITHMS, PRIVATE_KEY_JWT_SIGNING_ALGORITHMS, RESERVED_AUTHORIZATION_PARAMS, RESERVED_AUTHORIZATION_PARAMS_SET, additionalAuthorizationParamsSchema, applyDefaultAccessTokenExpiry, authorizationCodeRequest, clientCredentialsToken, clientCredentialsTokenRequest, createAuthorizationURL, createDpopBindingError, createDpopProofError, createDpopReplayStore, createInMemoryDpopReplayStore, createPrivateKeyJwtClientAssertionGetter, decodeBasicCredentials, deriveDpopAth, deriveDpopJkt, encodeBasicCredentials, enforceDpopBinding, generateCodeChallenge, getConfirmationJkt, getDpopJktFromPayload, getJwks, getOAuth2Tokens, getPrimaryClientId, includesGrantedScope, isDpopBindingError, isDpopProofError, normalizeDpopHtu, normalizeScopes, parseAccessTokenAuthorization, parseScopeField, readGrantedScopes, refreshAccessToken, refreshAccessTokenRequest, requestToResourceInput, resolveClientAssertionParams, resolveRequestedScopes, signPrivateKeyJwtClientAssertion, stripAccessTokenAuthorizationScheme, supportsIdTokenSignIn, unionGrantedScopes, validateAuthorizationCode, validateToken, verifyAccessTokenRequest, verifyBearerToken, verifyDpopProof, verifyJwsAccessToken, verifyProviderIdToken };
12
+ export { BEARER_AUTHORIZATION_SCHEME, CLIENT_ASSERTION_TYPE, DPOP_AUTHORIZATION_SCHEME, DPOP_PROOF_TYPE, DPOP_SIGNING_ALGORITHMS, PRIVATE_KEY_JWT_SIGNING_ALGORITHMS, RESERVED_AUTHORIZATION_PARAMS, RESERVED_AUTHORIZATION_PARAMS_SET, additionalAuthorizationParamsSchema, applyDefaultAccessTokenExpiry, authorizationCodeRequest, clientCredentialsToken, clientCredentialsTokenRequest, createAuthorizationURL, createDpopBindingError, createDpopProofError, createDpopReplayStore, createInMemoryDpopReplayStore, createPrivateKeyJwtClientAssertionGetter, decodeBasicCredentials, deriveDpopAth, deriveDpopJkt, encodeBasicCredentials, enforceDpopBinding, generateCodeChallenge, getConfirmationJkt, getDpopJktFromPayload, getJwks, getOAuth2Tokens, getPrimaryClientId, isDpopBindingError, isDpopProofError, mergeScopes, normalizeDpopHtu, parseAccessTokenAuthorization, refreshAccessToken, refreshAccessTokenRequest, requestToResourceInput, resolveClientAssertionParams, signPrivateKeyJwtClientAssertion, stripAccessTokenAuthorizationScheme, supportsIdTokenSignIn, validateAuthorizationCode, validateToken, verifyAccessTokenRequest, verifyBearerToken, verifyDpopProof, verifyJwsAccessToken, verifyProviderIdToken };
@@ -70,57 +70,29 @@ type OAuth2UserInfo = {
70
70
  emailVerified: boolean;
71
71
  };
72
72
  /**
73
- * The result of building a provider authorization URL.
73
+ * Request metadata available to provider refresh hooks.
74
74
  *
75
- * `requestedScopes` is the effective set of scopes encoded in the URL (the
76
- * provider's built-in defaults + configured `options.scope` + per-request
77
- * `scopes`, composed by `resolveRequestedScopes`). Callers persist it so the
78
- * callback can fall back to the request when the provider omits `scope` from
79
- * its token response (RFC 6749 §5.1).
75
+ * The refresh flow may be triggered by endpoints such as `getAccessToken` or
76
+ * `refreshToken`; this context gives provider hooks access to the triggering
77
+ * request without exposing the full endpoint implementation surface.
80
78
  */
81
- interface AuthorizationURLResult {
82
- url: URL;
83
- requestedScopes: string[];
79
+ interface OAuthRefreshContext {
80
+ headers?: Headers | undefined;
81
+ request?: Request | undefined;
84
82
  }
85
- /**
86
- * How much an RP trusts a provider's echoed token-response `scope` when
87
- * persisting `account.grantedScopes`.
88
- *
89
- * - `"full-grant"`: the echo is the user's complete current grant, so the seam
90
- * replaces the stored grant with it. This is the only path that may narrow
91
- * the grant. Declare it only for providers whose token response reports the
92
- * full combined grant, e.g. Google with `include_granted_scopes`.
93
- * - `"projection"`: the echo is this request's subset, so the seam unions it
94
- * onto the stored grant. The safe default for every provider.
95
- * - `"absent-echo"`: the provider omitted `scope`, so the grant equals what was
96
- * requested (RFC 6749 §5.1) and the seam unions the requested set. Resolved
97
- * at runtime by the persistence seam, never declared by a provider.
98
- *
99
- * @see https://www.rfc-editor.org/rfc/rfc6749#section-5.1
100
- */
101
- type GrantAuthority = "full-grant" | "projection" | "absent-echo";
102
- /**
103
- * The authority a provider may declare for its own echoed scope. `"absent-echo"`
104
- * is excluded because it is a runtime condition (an omitted echo), not a
105
- * provider trait.
106
- */
107
- type ProviderGrantAuthority = Exclude<GrantAuthority, "absent-echo">;
108
- interface UpstreamProvider<T extends Record<string, any> = Record<string, any>, O extends Record<string, any> = Partial<ProviderOptions>> {
83
+ interface OAuthProvider<T extends Record<string, any> = Record<string, any>, O extends Record<string, any> = Partial<ProviderOptions>> {
109
84
  id: LiteralString;
110
85
  /**
111
- * The path the provider redirects back to, relative to the app base URL,
112
- * e.g. `/callback/google`.
113
- */
114
- callbackPath: string;
115
- /**
116
- * How the persistence seam treats this provider's echoed token-response
117
- * `scope`. Declare `"full-grant"` only when the echo is the user's complete
118
- * current grant (e.g. Google with `include_granted_scopes`); otherwise the
119
- * echo is unioned onto the stored grant.
86
+ * Optional path under the resolved per-request `baseURL` where this
87
+ * provider's OAuth callback handler is mounted. Providers that use the
88
+ * shared `/callback/<id>` route can omit this.
89
+ *
90
+ * Custom paths must start with `/`.
120
91
  *
121
- * @default "projection"
92
+ * Endpoints compose `redirectURI = ctx.context.baseURL + callbackPath` per
93
+ * request, so the provider must not hardcode an origin or `baseURL` here.
122
94
  */
123
- grantAuthority?: ProviderGrantAuthority | undefined;
95
+ callbackPath?: string | undefined;
124
96
  createAuthorizationURL: (data: {
125
97
  state: string;
126
98
  codeVerifier: string;
@@ -128,6 +100,12 @@ interface UpstreamProvider<T extends Record<string, any> = Record<string, any>,
128
100
  redirectURI: string;
129
101
  display?: string | undefined;
130
102
  loginHint?: string | undefined;
103
+ /**
104
+ * OIDC nonce generated by the redirect initiator and persisted in OAuth
105
+ * state. Providers that set `requiresIdTokenNonce` must forward this to
106
+ * the authorization URL as the `nonce` parameter.
107
+ */
108
+ idTokenNonce?: string | undefined;
131
109
  /**
132
110
  * Extra query parameters to append to the authorization URL.
133
111
  * Providers forward these to the shared `createAuthorizationURL` helper,
@@ -135,7 +113,7 @@ interface UpstreamProvider<T extends Record<string, any> = Record<string, any>,
135
113
  * before applying them.
136
114
  */
137
115
  additionalParams?: Record<string, string> | undefined;
138
- }) => Awaitable<AuthorizationURLResult>;
116
+ }) => Awaitable<URL>;
139
117
  name: string;
140
118
  validateAuthorizationCode: (data: {
141
119
  code: string;
@@ -144,6 +122,12 @@ interface UpstreamProvider<T extends Record<string, any> = Record<string, any>,
144
122
  deviceId?: string | undefined;
145
123
  }) => Promise<OAuth2Tokens | null>;
146
124
  getUserInfo: (token: OAuth2Tokens & {
125
+ /**
126
+ * OIDC nonce recovered from OAuth state. Providers that required an
127
+ * ID-token nonce must pass this to `verifyProviderIdToken` before
128
+ * trusting ID-token claims.
129
+ */
130
+ expectedIdTokenNonce?: string | undefined;
147
131
  /**
148
132
  * The user object from the provider
149
133
  * This is only available for some providers like Apple
@@ -160,9 +144,14 @@ interface UpstreamProvider<T extends Record<string, any> = Record<string, any>,
160
144
  data: T;
161
145
  } | null>;
162
146
  /**
163
- * Custom function to refresh a token
147
+ * Custom function to refresh a token.
148
+ *
149
+ * Receives request metadata from the endpoint that triggered the refresh.
150
+ * Providers that don't need request-scoped data can ignore the second
151
+ * argument.
164
152
  */
165
- refreshAccessToken?: ((refreshToken: string) => Promise<OAuth2Tokens>) | undefined;
153
+ refreshAccessToken?: ((refreshToken: string, ctx?: OAuthRefreshContext) => Promise<OAuth2Tokens>) | undefined;
154
+ revokeToken?: ((token: string) => Promise<void>) | undefined;
166
155
  /**
167
156
  * Declarative id_token verification config consumed by the shared
168
157
  * `verifyProviderIdToken` verifier. Providers set this instead of implementing a boolean
@@ -175,6 +164,13 @@ interface UpstreamProvider<T extends Record<string, any> = Record<string, any>,
175
164
  * against this value to prevent authorization server mix-up attacks.
176
165
  */
177
166
  issuer?: string | undefined;
167
+ /**
168
+ * Require shared OAuth redirect routes to bind ID-token verification to an
169
+ * authorization request nonce. When true, routes generate `idTokenNonce`,
170
+ * pass it to `createAuthorizationURL`, persist it in state, and provide it
171
+ * back to `getUserInfo` as `expectedIdTokenNonce`.
172
+ */
173
+ requiresIdTokenNonce?: boolean | undefined;
178
174
  /**
179
175
  * Disable implicit sign up for new users. When set to true for the provider,
180
176
  * sign-in need to be called with with requestSignUp as true to create new users.
@@ -333,4 +329,4 @@ type ProviderOptions<Profile extends Record<string, any> = any> = {
333
329
  requireEmailVerification?: boolean | undefined;
334
330
  };
335
331
  //#endregion
336
- export { AuthorizationURLResult, GrantAuthority, OAuth2Tokens, OAuth2UserInfo, OAuthIdTokenConfig, ProviderGrantAuthority, ProviderOptions, UpstreamProvider };
332
+ export { OAuth2Tokens, OAuth2UserInfo, OAuthIdTokenConfig, OAuthProvider, OAuthRefreshContext, ProviderOptions };
@@ -1,6 +1,14 @@
1
+ import { parseScopeField } from "./utils.mjs";
1
2
  import { applyTokenEndpointAuth } from "./token-endpoint-auth.mjs";
2
3
  import { betterFetch } from "@better-fetch/fetch";
3
4
  //#region src/oauth2/refresh-access-token.ts
5
+ const BLOCKED_REFRESH_TOKEN_PARAMS_SET = new Set([
6
+ "grant_type",
7
+ "refresh_token",
8
+ "__proto__",
9
+ "constructor",
10
+ "prototype"
11
+ ]);
4
12
  async function refreshAccessTokenRequest({ refreshToken, options, authentication, tokenEndpointAuth, tokenEndpoint, extraParams, resource }) {
5
13
  options = typeof options === "function" ? await options() : options;
6
14
  const request = buildRefreshAccessTokenRequest({
@@ -20,6 +28,13 @@ async function refreshAccessTokenRequest({ refreshToken, options, authentication
20
28
  });
21
29
  return request;
22
30
  }
31
+ function applyRefreshExtraParams(body, extraParams) {
32
+ if (!extraParams) return;
33
+ for (const [key, value] of Object.entries(extraParams)) {
34
+ if (BLOCKED_REFRESH_TOKEN_PARAMS_SET.has(key)) continue;
35
+ body.set(key, value);
36
+ }
37
+ }
23
38
  function buildRefreshAccessTokenRequest({ refreshToken, options, extraParams, resource }) {
24
39
  const body = new URLSearchParams();
25
40
  const headers = {
@@ -30,7 +45,7 @@ function buildRefreshAccessTokenRequest({ refreshToken, options, extraParams, re
30
45
  body.set("refresh_token", refreshToken);
31
46
  if (resource) if (typeof resource === "string") body.append("resource", resource);
32
47
  else for (const _resource of resource) body.append("resource", _resource);
33
- if (extraParams) for (const [key, value] of Object.entries(extraParams)) body.set(key, value);
48
+ if (extraParams) applyRefreshExtraParams(body, extraParams);
34
49
  return {
35
50
  body,
36
51
  headers
@@ -56,7 +71,7 @@ async function refreshAccessToken({ refreshToken, options, tokenEndpoint, authen
56
71
  accessToken: data.access_token,
57
72
  refreshToken: data.refresh_token,
58
73
  tokenType: data.token_type,
59
- scopes: Array.isArray(data.scope) ? data.scope : data.scope?.split(" "),
74
+ scopes: parseScopeField(data.scope),
60
75
  idToken: data.id_token
61
76
  };
62
77
  if (data.expires_in) {
@@ -10,6 +10,11 @@ declare function getOAuth2Tokens(data: Record<string, any>): OAuth2Tokens;
10
10
  * fallback is configured.
11
11
  */
12
12
  declare function applyDefaultAccessTokenExpiry(tokens: OAuth2Tokens, accessTokenExpiresIn: number | undefined): OAuth2Tokens;
13
+ /**
14
+ * Compute the union of stored and incoming OAuth scopes, preserving
15
+ * stored insertion order and dropping duplicates.
16
+ */
17
+ declare function mergeScopes(stored: string | null | undefined, incoming: string[] | undefined): string;
13
18
  /**
14
19
  * Return the provider's primary Client ID: the single string, or the entry at
15
20
  * array index 0 for the cross-platform form used by ID token audience
@@ -21,4 +26,4 @@ declare function applyDefaultAccessTokenExpiry(tokens: OAuth2Tokens, accessToken
21
26
  declare function getPrimaryClientId(clientId: unknown): string | undefined;
22
27
  declare function generateCodeChallenge(codeVerifier: string): Promise<string>;
23
28
  //#endregion
24
- export { applyDefaultAccessTokenExpiry, generateCodeChallenge, getOAuth2Tokens, getPrimaryClientId };
29
+ export { applyDefaultAccessTokenExpiry, generateCodeChallenge, getOAuth2Tokens, getPrimaryClientId, mergeScopes };
@@ -1,6 +1,19 @@
1
- import { parseScopeField } from "./scopes.mjs";
2
1
  import { base64Url } from "@better-auth/utils/base64";
3
2
  //#region src/oauth2/utils.ts
3
+ /**
4
+ * Parse a provider's `scope` token-response field into a string array.
5
+ *
6
+ * RFC 6749 Section 3.3 defines `scope` as a space-delimited string, but
7
+ * providers vary: some return an already-split array. Accept both forms and
8
+ * drop empty or non-string entries.
9
+ *
10
+ * @see https://github.com/better-auth/better-auth/issues/9076
11
+ */
12
+ function parseScopeField(scope) {
13
+ if (Array.isArray(scope)) return scope.map((s) => typeof s === "string" ? s.trim() : "").filter(Boolean);
14
+ if (typeof scope === "string") return scope.trim().split(/\s+/).filter(Boolean);
15
+ return [];
16
+ }
4
17
  function getOAuth2Tokens(data) {
5
18
  const getDate = (seconds) => {
6
19
  const now = /* @__PURE__ */ new Date();
@@ -29,6 +42,15 @@ function applyDefaultAccessTokenExpiry(tokens, accessTokenExpiresIn) {
29
42
  return tokens;
30
43
  }
31
44
  /**
45
+ * Compute the union of stored and incoming OAuth scopes, preserving
46
+ * stored insertion order and dropping duplicates.
47
+ */
48
+ function mergeScopes(stored, incoming) {
49
+ const existing = stored ? stored.split(",").map((scope) => scope.trim()).filter(Boolean) : [];
50
+ const next = (incoming ?? []).map((scope) => scope.trim()).filter(Boolean);
51
+ return [...new Set([...existing, ...next])].join(",");
52
+ }
53
+ /**
32
54
  * Return the provider's primary Client ID: the single string, or the entry at
33
55
  * array index 0 for the cross-platform form used by ID token audience
34
56
  * verification. Index 0 is the designated primary and pairs with
@@ -46,4 +68,4 @@ async function generateCodeChallenge(codeVerifier) {
46
68
  return base64Url.encode(new Uint8Array(hash), { padding: false });
47
69
  }
48
70
  //#endregion
49
- export { applyDefaultAccessTokenExpiry, generateCodeChallenge, getOAuth2Tokens, getPrimaryClientId };
71
+ export { applyDefaultAccessTokenExpiry, generateCodeChallenge, getOAuth2Tokens, getPrimaryClientId, mergeScopes, parseScopeField };
@@ -1,26 +1,27 @@
1
- import { UpstreamProvider } from "./oauth-provider.mjs";
1
+ import { OAuthProvider } from "./oauth-provider.mjs";
2
2
 
3
3
  //#region src/oauth2/verify-id-token.d.ts
4
+ type ProviderWithIdTokenConfig = Pick<OAuthProvider, "idToken" | "options">;
4
5
  /**
5
6
  * Whether a provider can verify a client-submitted id_token.
6
7
  *
7
- * A provider supports id_token sign-in when it declares an {@link UpstreamProvider.idToken}
8
+ * A provider supports id_token sign-in when it declares an {@link OAuthProvider.idToken}
8
9
  * verification config, or when the integrator supplies a `verifyIdToken` override on the
9
10
  * provider options. A provider whose options set `disableIdTokenSignIn`, or that declares
10
11
  * neither, rejects the client id_token sign-in path with `ID_TOKEN_NOT_SUPPORTED`.
11
12
  */
12
- declare function supportsIdTokenSignIn(provider: UpstreamProvider<any, any>): boolean;
13
+ declare function supportsIdTokenSignIn(provider: ProviderWithIdTokenConfig): boolean;
13
14
  /**
14
15
  * Verify a client-submitted id_token against a provider's verification config.
15
16
  *
16
17
  * This is the single id_token verifier for every social provider. Providers no longer
17
- * implement their own boolean `verifyIdToken`; they declare an {@link UpstreamProvider.idToken}
18
+ * implement their own boolean `verifyIdToken`; they declare an {@link OAuthProvider.idToken}
18
19
  * config and this function performs the cryptographic check. The contract is fail-closed: a
19
20
  * provider without a config (and without an integrator `verifyIdToken` override) returns
20
21
  * `false`, so a forged token can never be accepted by omission.
21
22
  *
22
23
  * @returns `true` only when the token is authentic for the provider.
23
24
  */
24
- declare function verifyProviderIdToken(provider: UpstreamProvider<any, any>, token: string, nonce?: string): Promise<boolean>;
25
+ declare function verifyProviderIdToken(provider: ProviderWithIdTokenConfig, token: string, nonce?: string): Promise<boolean>;
25
26
  //#endregion
26
27
  export { supportsIdTokenSignIn, verifyProviderIdToken };
@@ -14,7 +14,7 @@ async function nonceMatches(claimNonce, nonce, comparison = "exact") {
14
14
  /**
15
15
  * Whether a provider can verify a client-submitted id_token.
16
16
  *
17
- * A provider supports id_token sign-in when it declares an {@link UpstreamProvider.idToken}
17
+ * A provider supports id_token sign-in when it declares an {@link OAuthProvider.idToken}
18
18
  * verification config, or when the integrator supplies a `verifyIdToken` override on the
19
19
  * provider options. A provider whose options set `disableIdTokenSignIn`, or that declares
20
20
  * neither, rejects the client id_token sign-in path with `ID_TOKEN_NOT_SUPPORTED`.
@@ -28,7 +28,7 @@ function supportsIdTokenSignIn(provider) {
28
28
  * Verify a client-submitted id_token against a provider's verification config.
29
29
  *
30
30
  * This is the single id_token verifier for every social provider. Providers no longer
31
- * implement their own boolean `verifyIdToken`; they declare an {@link UpstreamProvider.idToken}
31
+ * implement their own boolean `verifyIdToken`; they declare an {@link OAuthProvider.idToken}
32
32
  * config and this function performs the cryptographic check. The contract is fail-closed: a
33
33
  * provider without a config (and without an integrator `verifyIdToken` override) returns
34
34
  * `false`, so a forged token can never be accepted by omission.
@@ -69,7 +69,6 @@ interface AppleOptions extends ProviderOptions<AppleProfile> {
69
69
  declare const apple: (options: AppleOptions) => {
70
70
  id: "apple";
71
71
  name: string;
72
- callbackPath: string;
73
72
  createAuthorizationURL({
74
73
  state,
75
74
  scopes,
@@ -82,11 +81,9 @@ declare const apple: (options: AppleOptions) => {
82
81
  redirectURI: string;
83
82
  display?: string | undefined;
84
83
  loginHint?: string | undefined;
84
+ idTokenNonce?: string | undefined;
85
85
  additionalParams?: Record<string, string> | undefined;
86
- }): Promise<{
87
- url: URL;
88
- requestedScopes: string[];
89
- }>;
86
+ }): Promise<URL>;
90
87
  validateAuthorizationCode: ({
91
88
  code,
92
89
  codeVerifier,
@@ -106,6 +103,7 @@ declare const apple: (options: AppleOptions) => {
106
103
  };
107
104
  refreshAccessToken: (refreshToken: string) => Promise<OAuth2Tokens>;
108
105
  getUserInfo(token: OAuth2Tokens & {
106
+ expectedIdTokenNonce?: string | undefined;
109
107
  user?: {
110
108
  name?: {
111
109
  firstName?: string;
@@ -1,6 +1,5 @@
1
1
  import { APIError, BetterAuthError } from "../error/index.mjs";
2
2
  import { logger } from "../env/logger.mjs";
3
- import { resolveRequestedScopes } from "../oauth2/scopes.mjs";
4
3
  import { getPrimaryClientId } from "../oauth2/utils.mjs";
5
4
  import { createAuthorizationURL } from "../oauth2/create-authorization-url.mjs";
6
5
  import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
@@ -8,23 +7,24 @@ import { validateAuthorizationCode } from "../oauth2/validate-authorization-code
8
7
  import { decodeJwt, importJWK } from "jose";
9
8
  import { betterFetch } from "@better-fetch/fetch";
10
9
  //#region src/social-providers/apple.ts
11
- const APPLE_DEFAULT_SCOPES = ["email", "name"];
12
10
  const apple = (options) => {
13
11
  const tokenEndpoint = "https://appleid.apple.com/auth/token";
14
12
  return {
15
13
  id: "apple",
16
14
  name: "Apple",
17
- callbackPath: "/callback/apple",
18
15
  async createAuthorizationURL({ state, scopes, redirectURI, additionalParams }) {
19
16
  if (!getPrimaryClientId(options.clientId) || !options.clientSecret) {
20
17
  logger.error("Client ID and client secret are required for Apple. Make sure to provide them in the options.");
21
18
  throw new BetterAuthError("CLIENT_ID_AND_SECRET_REQUIRED");
22
19
  }
23
- return createAuthorizationURL({
20
+ const _scope = options.disableDefaultScope ? [] : ["email", "name"];
21
+ if (options.scope) _scope.push(...options.scope);
22
+ if (scopes) _scope.push(...scopes);
23
+ return await createAuthorizationURL({
24
24
  id: "apple",
25
25
  options,
26
26
  authorizationEndpoint: "https://appleid.apple.com/auth/authorize",
27
- scopes: resolveRequestedScopes(options, APPLE_DEFAULT_SCOPES, scopes),
27
+ scopes: _scope,
28
28
  state,
29
29
  redirectURI,
30
30
  responseMode: "form_post",
@@ -21,7 +21,6 @@ interface AtlassianOptions extends ProviderOptions<AtlassianProfile> {
21
21
  declare const atlassian: (options: AtlassianOptions) => {
22
22
  id: "atlassian";
23
23
  name: string;
24
- callbackPath: string;
25
24
  createAuthorizationURL({
26
25
  state,
27
26
  scopes,
@@ -35,11 +34,9 @@ declare const atlassian: (options: AtlassianOptions) => {
35
34
  redirectURI: string;
36
35
  display?: string | undefined;
37
36
  loginHint?: string | undefined;
37
+ idTokenNonce?: string | undefined;
38
38
  additionalParams?: Record<string, string> | undefined;
39
- }): Promise<{
40
- url: URL;
41
- requestedScopes: string[];
42
- }>;
39
+ }): Promise<URL>;
43
40
  validateAuthorizationCode: ({
44
41
  code,
45
42
  codeVerifier,
@@ -52,6 +49,7 @@ declare const atlassian: (options: AtlassianOptions) => {
52
49
  }) => Promise<OAuth2Tokens>;
53
50
  refreshAccessToken: (refreshToken: string) => Promise<OAuth2Tokens>;
54
51
  getUserInfo(token: OAuth2Tokens & {
52
+ expectedIdTokenNonce?: string | undefined;
55
53
  user?: {
56
54
  name?: {
57
55
  firstName?: string;