@auth0/auth0-server-js 1.12.1 → 1.13.0

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.
package/dist/index.cjs CHANGED
@@ -53,6 +53,7 @@ __export(index_exports, {
53
53
  TokenExchangeError: () => import_auth0_auth_js5.TokenExchangeError,
54
54
  TokenExchangeErrorCode: () => TokenExchangeErrorCode,
55
55
  TokenRevocationError: () => import_auth0_auth_js5.TokenRevocationError,
56
+ UserInfoError: () => import_auth0_auth_js5.UserInfoError,
56
57
  isMfaRequiredError: () => import_auth0_auth_js5.isMfaRequiredError
57
58
  });
58
59
  module.exports = __toCommonJS(index_exports);
@@ -262,7 +263,7 @@ function getTelemetryConfig(config) {
262
263
  return {
263
264
  enabled: true,
264
265
  name: config?.name ?? "@auth0/auth0-server-js",
265
- version: config?.version ?? "1.12.1"
266
+ version: config?.version ?? "1.13.0"
266
267
  };
267
268
  }
268
269
 
@@ -282,8 +283,8 @@ var ServerMfaClient = class {
282
283
  * @returns Promise resolving to an array of enrolled authenticators
283
284
  * @throws {MfaListAuthenticatorsError} When the request fails
284
285
  */
285
- async listAuthenticators(options) {
286
- return this.#options.authClient.mfa.listAuthenticators(options);
286
+ async listAuthenticators(options, requestOptions) {
287
+ return this.#options.authClient.mfa.listAuthenticators(options, requestOptions);
287
288
  }
288
289
  /**
289
290
  * Enrolls a new MFA authenticator for the user.
@@ -292,8 +293,8 @@ var ServerMfaClient = class {
292
293
  * @returns Promise resolving to enrollment response with authenticator details
293
294
  * @throws {MfaEnrollmentError} When enrollment fails
294
295
  */
295
- async enrollAuthenticator(options) {
296
- return this.#options.authClient.mfa.enrollAuthenticator(options);
296
+ async enrollAuthenticator(options, requestOptions) {
297
+ return this.#options.authClient.mfa.enrollAuthenticator(options, requestOptions);
297
298
  }
298
299
  /**
299
300
  * Initiates an MFA challenge for user verification.
@@ -302,8 +303,8 @@ var ServerMfaClient = class {
302
303
  * @returns Promise resolving to challenge response with challenge details
303
304
  * @throws {MfaChallengeError} When the challenge fails
304
305
  */
305
- async challengeAuthenticator(options) {
306
- return this.#options.authClient.mfa.challengeAuthenticator(options);
306
+ async challengeAuthenticator(options, requestOptions) {
307
+ return this.#options.authClient.mfa.challengeAuthenticator(options, requestOptions);
307
308
  }
308
309
  /**
309
310
  * Verifies an MFA challenge and completes the authentication flow.
@@ -317,8 +318,8 @@ var ServerMfaClient = class {
317
318
  * @returns The tokens returned by Auth0 after successful verification
318
319
  * @throws {MfaVerifyError} When verification fails (e.g. invalid token, wrong code)
319
320
  */
320
- async verify(options, storeOptions) {
321
- const tokenResponse = await this.#options.authClient.mfa.verify(options);
321
+ async verify(options, storeOptions, requestOptions) {
322
+ const tokenResponse = await this.#options.authClient.mfa.verify(options, requestOptions);
322
323
  const audience = options.audience ?? this.#options.defaultAudience;
323
324
  const existingStateData = await this.#options.stateStore.get(
324
325
  this.#options.stateStoreIdentifier,
@@ -381,10 +382,10 @@ var ServerPasskeyClient = class {
381
382
  *
382
383
  * @returns A promise resolving to the signup challenge.
383
384
  */
384
- async register(options, storeOptions) {
385
+ async register(options, storeOptions, requestOptions) {
385
386
  const domain = await this.#options.resolveDomain(storeOptions);
386
387
  const authClient = this.#options.getAuthClient(domain);
387
- return authClient.passkey.register(options);
388
+ return authClient.passkey.register(options, requestOptions);
388
389
  }
389
390
  /**
390
391
  * Requests a passkey login challenge for an existing user.
@@ -406,10 +407,10 @@ var ServerPasskeyClient = class {
406
407
  *
407
408
  * @returns A promise resolving to the login challenge.
408
409
  */
409
- async challenge(options, storeOptions) {
410
+ async challenge(options, storeOptions, requestOptions) {
410
411
  const domain = await this.#options.resolveDomain(storeOptions);
411
412
  const authClient = this.#options.getAuthClient(domain);
412
- return authClient.passkey.challenge(options);
413
+ return authClient.passkey.challenge(options, requestOptions);
413
414
  }
414
415
  /**
415
416
  * Completes a passkey authentication flow (signup or login) by exchanging the
@@ -431,7 +432,7 @@ var ServerPasskeyClient = class {
431
432
  *
432
433
  * @returns A promise resolving to an object containing the authorizationDetails (when RAR was used).
433
434
  */
434
- async getToken(options, storeOptions) {
435
+ async getToken(options, storeOptions, requestOptions) {
435
436
  const scope = ensureOpenIdScope(options.scope ?? this.#options.defaultScope);
436
437
  const audience = options.audience ?? this.#options.defaultAudience;
437
438
  const domain = await this.#options.resolveDomain(storeOptions);
@@ -440,7 +441,7 @@ var ServerPasskeyClient = class {
440
441
  ...options,
441
442
  scope,
442
443
  audience
443
- });
444
+ }, requestOptions);
444
445
  const existingStateData = await this.#options.stateStore.get(this.#options.stateStoreIdentifier, storeOptions);
445
446
  const stateData = updateStateData(audience ?? "default", existingStateData, tokenEndpointResponse, { domain });
446
447
  await this.#options.stateStore.set(this.#options.stateStoreIdentifier, stateData, true, storeOptions);
@@ -473,9 +474,9 @@ var ServerDatabaseClient = class {
473
474
  *
474
475
  * @returns A promise resolving to the created user result with a normalized `id` field.
475
476
  */
476
- async signUp(options, storeOptions) {
477
+ async signUp(options, storeOptions, requestOptions) {
477
478
  const domain = await this.#options.resolveDomain(storeOptions);
478
- return this.#options.getAuthClient(domain).database.signUp(options);
479
+ return this.#options.getAuthClient(domain).database.signUp(options, requestOptions);
479
480
  }
480
481
  /**
481
482
  * Requests a password-change email for a database connection user.
@@ -491,9 +492,9 @@ var ServerDatabaseClient = class {
491
492
  *
492
493
  * @returns A promise resolving to the server's plain-text confirmation message.
493
494
  */
494
- async changePassword(options, storeOptions) {
495
+ async changePassword(options, storeOptions, requestOptions) {
495
496
  const domain = await this.#options.resolveDomain(storeOptions);
496
- return this.#options.getAuthClient(domain).database.changePassword(options);
497
+ return this.#options.getAuthClient(domain).database.changePassword(options, requestOptions);
497
498
  }
498
499
  };
499
500
 
@@ -768,6 +769,7 @@ var ServerClient = class {
768
769
  * Takes an URL, extract the Authorization Code flow query parameters and requests a token.
769
770
  * @param url The URl from which the query params should be extracted to exchange for a token.
770
771
  * @param storeOptions Optional options used to pass to the Transaction and State Store.
772
+ * @param requestOptions Optional per-request options (signal, headers, customFetch). Applied to the code-for-token exchange.
771
773
  *
772
774
  * @throws {MissingTransactionError} When no transaction was found.
773
775
  * @throws {TokenByCodeError} If there was an issue requesting the access token.
@@ -775,8 +777,15 @@ var ServerClient = class {
775
777
  * @throws {SessionExpiredError} When the ID token's `session_expiry` is already in the past at login (the session is born expired); nothing is persisted.
776
778
  *
777
779
  * @returns A promise resolving to an object, containing the original appState (if present) and the authorizationDetails (when RAR was used).
780
+ *
781
+ * @remarks
782
+ * This method does not support the `fullResponse` opt-in in v1. It accepts
783
+ * `url` and `storeOptions` with no intermediate options object; adding
784
+ * `fullResponse` would require a new options parameter and is deferred to
785
+ * a later revision.
786
+ * TODO(#<issue-number>): add fullResponse overload to completeInteractiveLogin in a future minor.
778
787
  */
779
- async completeInteractiveLogin(url, storeOptions) {
788
+ async completeInteractiveLogin(url, storeOptions, requestOptions) {
780
789
  const transactionData = await this.#transactionStore.get(this.#transactionStoreIdentifier, storeOptions);
781
790
  if (!transactionData) {
782
791
  throw new MissingTransactionError();
@@ -787,7 +796,7 @@ var ServerClient = class {
787
796
  // TransactionData.codeVerifier is optional only to accommodate magic-link transactions.
788
797
  codeVerifier: transactionData.codeVerifier,
789
798
  organization: transactionData.organization
790
- });
799
+ }, requestOptions);
791
800
  await this.#transactionStore.delete(this.#transactionStoreIdentifier, storeOptions);
792
801
  const existingStateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
793
802
  const stateData = applySessionExpiryAtLogin(
@@ -851,14 +860,15 @@ var ServerClient = class {
851
860
  * Takes an URL, extract the Authorization Code flow query parameters and requests a token.
852
861
  * @param url The URl from which the query params should be extracted to exchange for a token.
853
862
  * @param storeOptions Optional options used to pass to the Transaction and State Store.
863
+ * @param requestOptions Optional per-request options (signal, headers, customFetch). Applied to the code-for-token exchange.
854
864
  *
855
865
  * @throws {MissingTransactionError} When no transaction was found.
856
866
  * @throws {TokenByCodeError} If there was an issue requesting the access token.
857
867
  *
858
868
  * @returns A promise resolving to an object, containing the original appState (if present).
859
869
  */
860
- async completeLinkUser(url, storeOptions) {
861
- const result = await this.completeInteractiveLogin(url, storeOptions);
870
+ async completeLinkUser(url, storeOptions, requestOptions) {
871
+ const result = await this.completeInteractiveLogin(url, storeOptions, requestOptions);
862
872
  return {
863
873
  appState: result.appState
864
874
  };
@@ -914,43 +924,44 @@ var ServerClient = class {
914
924
  * Takes an URL, extract the Authorization Code flow query parameters and requests a token.
915
925
  * @param url The URl from which the query params should be extracted to exchange for a token.
916
926
  * @param storeOptions Optional options used to pass to the Transaction and State Store.
927
+ * @param requestOptions Optional per-request options (signal, headers, customFetch). Applied to the code-for-token exchange.
917
928
  *
918
929
  * @throws {MissingTransactionError} When no transaction was found.
919
930
  * @throws {TokenByCodeError} If there was an issue requesting the access token.
920
931
  *
921
932
  * @returns A promise resolving to an object, containing the original appState (if present).
922
933
  */
923
- async completeUnlinkUser(url, storeOptions) {
924
- const result = await this.completeInteractiveLogin(url, storeOptions);
934
+ async completeUnlinkUser(url, storeOptions, requestOptions) {
935
+ const result = await this.completeInteractiveLogin(url, storeOptions, requestOptions);
925
936
  return {
926
937
  appState: result.appState
927
938
  };
928
939
  }
929
- /**
930
- * Logs in using Client-Initiated Backchannel Authentication.
931
- *
932
- * Using Client-Initiated Backchannel Authentication requires the feature to be enabled in the Auth0 dashboard.
933
- * @see https://auth0.com/docs/get-started/authentication-and-authorization-flow/client-initiated-backchannel-authentication-flow
934
- * @param options Options used to configure the backchannel login process.
935
- * @param storeOptions Optional options used to pass to the Transaction and State Store.
936
- *
937
- * @throws {BackchannelAuthenticationError} If there was an issue when doing backchannel authentication.
938
- * @throws {SessionExpiredError} When the ID token's `session_expiry` is already in the past at login (the session is born expired); nothing is persisted.
939
- *
940
- * @returns A promise resolving to an object, containing the authorizationDetails (when RAR was used).
941
- */
942
- async loginBackchannel(options, storeOptions) {
940
+ async loginBackchannel(options, storeOptions, requestOptions) {
943
941
  const scope = ensureOpenIdScope(options.authorizationParams?.scope ?? this.#options.authorizationParams?.scope);
944
942
  const domain = await this.#resolveDomain(storeOptions);
945
943
  const authClient = this.#getAuthClient(domain);
946
- const tokenEndpointResponse = await authClient.backchannelAuthentication({
947
- bindingMessage: options.bindingMessage,
948
- loginHint: options.loginHint,
949
- authorizationParams: {
950
- ...options.authorizationParams,
951
- scope
952
- }
953
- });
944
+ let response;
945
+ let tokenEndpointResponse;
946
+ if (options.fullResponse) {
947
+ const authJsResult = await authClient.backchannelAuthentication({
948
+ bindingMessage: options.bindingMessage,
949
+ loginHint: options.loginHint,
950
+ authorizationParams: { ...options.authorizationParams, scope },
951
+ fullResponse: true
952
+ }, requestOptions);
953
+ tokenEndpointResponse = authJsResult.data;
954
+ response = authJsResult.response;
955
+ } else {
956
+ tokenEndpointResponse = await authClient.backchannelAuthentication({
957
+ bindingMessage: options.bindingMessage,
958
+ loginHint: options.loginHint,
959
+ authorizationParams: {
960
+ ...options.authorizationParams,
961
+ scope
962
+ }
963
+ }, requestOptions);
964
+ }
954
965
  const existingStateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
955
966
  const stateData = applySessionExpiryAtLogin(
956
967
  updateStateData(this.#options.authorizationParams?.audience ?? "default", existingStateData, tokenEndpointResponse, {
@@ -959,9 +970,16 @@ var ServerClient = class {
959
970
  tokenEndpointResponse.claims
960
971
  );
961
972
  await this.#stateStore.set(this.#stateStoreIdentifier, stateData, true, storeOptions);
962
- return {
973
+ const result = {
963
974
  authorizationDetails: tokenEndpointResponse.authorizationDetails
964
975
  };
976
+ if (options.fullResponse) {
977
+ if (!response) {
978
+ throw new import_auth0_auth_js.MissingCapturedResponseError();
979
+ }
980
+ return { data: result, response };
981
+ }
982
+ return result;
965
983
  }
966
984
  /**
967
985
  * Starts a passwordless flow by sending a one-time code (OTP) or a magic link.
@@ -984,6 +1002,7 @@ var ServerClient = class {
984
1002
  *
985
1003
  * @param options Discriminated start options.
986
1004
  * @param storeOptions Optional options passed to the resolver / stores.
1005
+ * @param requestOptions Optional per-request options (signal, headers, customFetch). Applied to the `/passwordless/start` request.
987
1006
  *
988
1007
  * @throws {PasswordlessStartError} If the request fails, or if a magic link is requested without a `redirectUri`.
989
1008
  *
@@ -1000,22 +1019,28 @@ var ServerClient = class {
1000
1019
  * redirectUri: 'https://app.example.com/auth/callback',
1001
1020
  * });
1002
1021
  */
1003
- async startPasswordless(options, storeOptions) {
1022
+ async startPasswordless(options, storeOptions, requestOptions) {
1004
1023
  const domain = await this.#resolveDomain(storeOptions);
1005
1024
  const authClient = this.#getAuthClient(domain);
1006
1025
  if (options.connection === "sms") {
1007
- await authClient.passwordless.sendSms({
1008
- phoneNumber: options.phoneNumber,
1009
- language: options.language
1010
- });
1026
+ await authClient.passwordless.sendSms(
1027
+ {
1028
+ phoneNumber: options.phoneNumber,
1029
+ language: options.language
1030
+ },
1031
+ requestOptions
1032
+ );
1011
1033
  return;
1012
1034
  }
1013
1035
  if (options.send !== "link") {
1014
- await authClient.passwordless.sendEmail({
1015
- email: options.email,
1016
- send: "code",
1017
- language: options.language
1018
- });
1036
+ await authClient.passwordless.sendEmail(
1037
+ {
1038
+ email: options.email,
1039
+ send: "code",
1040
+ language: options.language
1041
+ },
1042
+ requestOptions
1043
+ );
1019
1044
  return;
1020
1045
  }
1021
1046
  if (!options.redirectUri || typeof options.redirectUri !== "string") {
@@ -1024,19 +1049,22 @@ var ServerClient = class {
1024
1049
  const state = crypto.randomUUID();
1025
1050
  const scope = ensureOpenIdScope(options.scope ?? this.#options.authorizationParams?.scope);
1026
1051
  const audience = options.audience ?? this.#options.authorizationParams?.audience;
1027
- await authClient.passwordless.sendEmail({
1028
- email: options.email,
1029
- send: "link",
1030
- language: options.language,
1031
- authParams: {
1032
- ...options.authParams,
1033
- redirect_uri: options.redirectUri,
1034
- response_type: "code",
1035
- scope,
1036
- ...audience ? { audience } : {},
1037
- state
1038
- }
1039
- });
1052
+ await authClient.passwordless.sendEmail(
1053
+ {
1054
+ email: options.email,
1055
+ send: "link",
1056
+ language: options.language,
1057
+ authParams: {
1058
+ ...options.authParams,
1059
+ redirect_uri: options.redirectUri,
1060
+ response_type: "code",
1061
+ scope,
1062
+ ...audience ? { audience } : {},
1063
+ state
1064
+ }
1065
+ },
1066
+ requestOptions
1067
+ );
1040
1068
  const transactionState = {
1041
1069
  audience,
1042
1070
  domain,
@@ -1044,42 +1072,42 @@ var ServerClient = class {
1044
1072
  };
1045
1073
  await this.#transactionStore.set(this.#transactionStoreIdentifier, transactionState, false, storeOptions);
1046
1074
  }
1047
- /**
1048
- * Completes a passwordless OTP login and persists the resulting session.
1049
- *
1050
- * Discriminated on `connection` to mirror the `@auth0/nextjs-auth0` `passwordless.verify()`
1051
- * surface. Non-redirect flow: no PKCE and no transaction store (mirrors
1052
- * {@link ServerClient#loginBackchannel}). The `openid` scope is always ensured by this layer.
1053
- *
1054
- * Note: the state store is read-then-written; if your deployment performs concurrent
1055
- * logins for the same session identifier, use a state store with atomic/serializable
1056
- * writes to avoid last-write-wins races.
1057
- *
1058
- * @param options Discriminated completion options (`connection`, identifier, `verificationCode`).
1059
- * @param storeOptions Optional options passed to the resolver / stores.
1060
- *
1061
- * @throws {PasswordlessVerifyError} If the code is invalid, expired, or rate-limited. When the
1062
- * connection requires MFA, the server responds with `mfa_required`; narrow the thrown error
1063
- * with `isMfaRequiredError(error)` to read `cause.mfa_token`.
1064
- *
1065
- * @returns A promise resolving to the authorizationDetails (when RAR was used).
1066
- */
1067
- async completePasswordless(options, storeOptions) {
1075
+ async completePasswordless(options, storeOptions, requestOptions) {
1068
1076
  const scope = ensureOpenIdScope(options.authorizationParams?.scope ?? this.#options.authorizationParams?.scope);
1069
1077
  const audience = options.authorizationParams?.audience ?? this.#options.authorizationParams?.audience;
1070
1078
  const domain = await this.#resolveDomain(storeOptions);
1071
1079
  const authClient = this.#getAuthClient(domain);
1072
- const tokenEndpointResponse = options.connection === "sms" ? await authClient.getTokenByPasswordlessSms({
1073
- phoneNumber: options.phoneNumber,
1074
- code: options.verificationCode,
1075
- audience,
1076
- scope
1077
- }) : await authClient.getTokenByPasswordlessEmail({
1078
- email: options.email,
1079
- code: options.verificationCode,
1080
- audience,
1081
- scope
1082
- });
1080
+ let response;
1081
+ let tokenEndpointResponse;
1082
+ if (options.fullResponse) {
1083
+ const authJsResult = options.connection === "sms" ? await authClient.getTokenByPasswordlessSms({
1084
+ phoneNumber: options.phoneNumber,
1085
+ code: options.verificationCode,
1086
+ audience,
1087
+ scope,
1088
+ fullResponse: true
1089
+ }, requestOptions) : await authClient.getTokenByPasswordlessEmail({
1090
+ email: options.email,
1091
+ code: options.verificationCode,
1092
+ audience,
1093
+ scope,
1094
+ fullResponse: true
1095
+ }, requestOptions);
1096
+ tokenEndpointResponse = authJsResult.data;
1097
+ response = authJsResult.response;
1098
+ } else {
1099
+ tokenEndpointResponse = options.connection === "sms" ? await authClient.getTokenByPasswordlessSms({
1100
+ phoneNumber: options.phoneNumber,
1101
+ code: options.verificationCode,
1102
+ audience,
1103
+ scope
1104
+ }, requestOptions) : await authClient.getTokenByPasswordlessEmail({
1105
+ email: options.email,
1106
+ code: options.verificationCode,
1107
+ audience,
1108
+ scope
1109
+ }, requestOptions);
1110
+ }
1083
1111
  const existingStateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
1084
1112
  const stateData = updateStateData(
1085
1113
  this.#options.authorizationParams?.audience ?? "default",
@@ -1088,9 +1116,16 @@ var ServerClient = class {
1088
1116
  { domain }
1089
1117
  );
1090
1118
  await this.#stateStore.set(this.#stateStoreIdentifier, stateData, true, storeOptions);
1091
- return {
1119
+ const result = {
1092
1120
  authorizationDetails: tokenEndpointResponse.authorizationDetails
1093
1121
  };
1122
+ if (options.fullResponse) {
1123
+ if (!response) {
1124
+ throw new import_auth0_auth_js.MissingCapturedResponseError();
1125
+ }
1126
+ return { data: result, response };
1127
+ }
1128
+ return result;
1094
1129
  }
1095
1130
  /**
1096
1131
  * Completes a passwordless magic-link login and persists the resulting session.
@@ -1102,6 +1137,7 @@ var ServerClient = class {
1102
1137
  *
1103
1138
  * @param url The callback URL containing the authorization `code` and `state`.
1104
1139
  * @param storeOptions Optional options passed to the resolver / stores.
1140
+ * @param requestOptions Optional per-request options (signal, headers, customFetch). Applied to the code exchange.
1105
1141
  *
1106
1142
  * @throws {MissingTransactionError} If no magic-link transaction was found.
1107
1143
  * @throws {PasswordlessVerifyError} If the returned `state` is missing or does not match.
@@ -1112,7 +1148,7 @@ var ServerClient = class {
1112
1148
  * @example
1113
1149
  * const result = await serverClient.completePasswordlessMagicLink(callbackUrl, storeOptions);
1114
1150
  */
1115
- async completePasswordlessMagicLink(url, storeOptions) {
1151
+ async completePasswordlessMagicLink(url, storeOptions, requestOptions) {
1116
1152
  const transactionData = await this.#transactionStore.get(this.#transactionStoreIdentifier, storeOptions);
1117
1153
  if (!transactionData) {
1118
1154
  throw new MissingTransactionError();
@@ -1124,7 +1160,7 @@ var ServerClient = class {
1124
1160
  }
1125
1161
  const domain = transactionData.domain ?? await this.#resolveDomain(storeOptions);
1126
1162
  const authClient = this.#getAuthClient(domain);
1127
- const tokenEndpointResponse = await authClient.getTokenByMagicLinkCode(url, { expectedState });
1163
+ const tokenEndpointResponse = await authClient.getTokenByMagicLinkCode(url, { expectedState }, requestOptions);
1128
1164
  const existingStateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
1129
1165
  const stateData = updateStateData(transactionData.audience ?? "default", existingStateData, tokenEndpointResponse, {
1130
1166
  domain
@@ -1137,6 +1173,12 @@ var ServerClient = class {
1137
1173
  }
1138
1174
  /**
1139
1175
  * Retrieves the user from the store, or undefined if no user found.
1176
+ *
1177
+ * This does not accept `RequestOptions`. It is a pure read from the state store and makes no
1178
+ * network call, so a per-request `signal`/`headers`/`customFetch` could not take effect. The
1179
+ * exclusion is deliberate: a parameter that can never do anything costs the public surface more
1180
+ * than the asymmetry with `getAccessToken`/`getAccessTokenForConnection`/`revokeRefreshToken` does.
1181
+ *
1140
1182
  * @param storeOptions Optional options used to pass to the Transaction and State Store.
1141
1183
  * @returns The user, or undefined if no user found in the store.
1142
1184
  */
@@ -1179,6 +1221,34 @@ var ServerClient = class {
1179
1221
  return sessionData;
1180
1222
  }
1181
1223
  }
1224
+ /**
1225
+ * Retrieves the OIDC UserInfo claims for a given access token.
1226
+ *
1227
+ * The access token must be supplied explicitly by the caller. This method does NOT read
1228
+ * the token from the session and does NOT trigger a refresh. The token must be accepted by
1229
+ * the `/userinfo` endpoint:
1230
+ * - Without Multi-Resource Refresh Tokens (MRRT): pass a default OIDC access token, one
1231
+ * obtained without an explicit `audience` parameter.
1232
+ * - With MRRT: tokens are audience-bound, so request the userinfo endpoint as the audience
1233
+ * (e.g. `https://<domain>/userinfo`) when obtaining the token. A token bound to a
1234
+ * different resource-server audience is rejected by `/userinfo`.
1235
+ *
1236
+ * `/userinfo` is a bearer-protected resource and requires no client authentication, so this
1237
+ * works for public clients: the supplied access token is the only credential used.
1238
+ *
1239
+ * @param options Options containing the access token and an optional expected subject
1240
+ * for OIDC subject-consistency validation.
1241
+ * @param storeOptions Optional store options, used to resolve the domain in resolver mode.
1242
+ * @param requestOptions Optional per-request options (signal, headers, customFetch) forwarded
1243
+ * to the underlying `/userinfo` request.
1244
+ * @throws {UserInfoError} When the `/userinfo` request fails or the subject check fails.
1245
+ * @returns A Promise resolving to the UserInfo claims.
1246
+ */
1247
+ async getUserInfo(options, storeOptions, requestOptions) {
1248
+ const domain = await this.#resolveDomain(storeOptions);
1249
+ const authClient = this.#getAuthClient(domain);
1250
+ return authClient.getUserInfo(options, requestOptions);
1251
+ }
1182
1252
  /**
1183
1253
  * Retrieves the access token from the store, or calls Auth0 when the access token is expired and a refresh token is available in the store.
1184
1254
  * Also updates the store when a new token was retrieved from Auth0.
@@ -1187,19 +1257,30 @@ var ServerClient = class {
1187
1257
  * request an access token for that audience/scope (Multi-Resource Refresh Tokens). Tokens are cached per
1188
1258
  * audience and scope combination.
1189
1259
  *
1190
- * @param options Optional options for requesting a specific audience/scope.
1260
+ * When `options.fullResponse` is `true`, the method returns an {@link ApiResponse} envelope containing both
1261
+ * the token set and the raw {@link Response} from the token endpoint. The cache is bypassed in this case,
1262
+ * forcing a refresh-token call even when a valid cached token exists, because the `Response` can only be
1263
+ * produced by a live HTTP call.
1264
+ *
1265
+ * @param options Optional options for requesting a specific audience/scope or enabling full response.
1191
1266
  * @param storeOptions Optional options used to pass to the Transaction and State Store.
1267
+ * @param requestOptions Optional per-request options (signal, headers, customFetch). Only supported with the options form (second overload). A cache hit returns before any network call, so `requestOptions` (including `signal`) is a no-op on that path; it applies only to the refresh-token exchange on a cache miss.
1268
+ *
1269
+ * @remarks
1270
+ * Legacy single-argument form: `getAccessToken(storeOptions?)`. If your `TStoreOptions` type
1271
+ * contains `audience` or `scope` keys, use the explicit two-argument form instead:
1272
+ * `getAccessToken({}, storeOptions)` to avoid call-site routing ambiguity.
1192
1273
  *
1193
1274
  * @throws {TokenByRefreshTokenError} If the refresh token was not found or there was an issue requesting the access token. When the cause is `mfa_required`, use `isMfaRequiredError(error)` to narrow the error and read `cause.mfa_token`.
1194
1275
  * @throws {SessionExpiredError} When the session's `session_expiry` ceiling has been reached; the session is cleared and no refresh is attempted — the user must re-authenticate.
1195
1276
  *
1196
- * @returns The Token Set, containing the access token, as well as additional information.
1277
+ * @returns The Token Set when `fullResponse` is omitted, or an {@link ApiResponse} envelope when `fullResponse: true`.
1197
1278
  */
1198
- async getAccessToken(tokenOptionsOrStoreOptions, storeOptions) {
1279
+ async getAccessToken(tokenOptionsOrStoreOptions, storeOptions, requestOptions) {
1199
1280
  const hasTokenOptions = (
1200
1281
  // If second arg exists, first arg must be GetAccessTokenOptions
1201
- storeOptions !== void 0 || // OR if first arg has audience/scope properties
1202
- !!tokenOptionsOrStoreOptions && typeof tokenOptionsOrStoreOptions === "object" && ("audience" in tokenOptionsOrStoreOptions || "scope" in tokenOptionsOrStoreOptions)
1282
+ storeOptions !== void 0 || // OR if first arg has audience, scope, or fullResponse properties
1283
+ !!tokenOptionsOrStoreOptions && typeof tokenOptionsOrStoreOptions === "object" && ("audience" in tokenOptionsOrStoreOptions || "scope" in tokenOptionsOrStoreOptions || "fullResponse" in tokenOptionsOrStoreOptions)
1203
1284
  );
1204
1285
  const [resolvedOptions, resolvedStoreOptions] = hasTokenOptions ? [tokenOptionsOrStoreOptions, storeOptions] : [void 0, tokenOptionsOrStoreOptions];
1205
1286
  const stateData = await this.#stateStore.get(this.#stateStoreIdentifier, resolvedStoreOptions);
@@ -1227,7 +1308,9 @@ var ServerClient = class {
1227
1308
  (tokenSet2) => tokenSet2.audience === audience && (!scope || compareScopes(tokenSet2.scope, scope))
1228
1309
  );
1229
1310
  if (tokenSet && tokenSet.expiresAt > Date.now() / 1e3) {
1230
- return tokenSet;
1311
+ if (!resolvedOptions?.fullResponse) {
1312
+ return tokenSet;
1313
+ }
1231
1314
  }
1232
1315
  if (!stateData?.refreshToken) {
1233
1316
  throw new import_auth0_auth_js.TokenByRefreshTokenError(
@@ -1244,35 +1327,38 @@ var ServerClient = class {
1244
1327
  ...scope && { scope }
1245
1328
  }
1246
1329
  };
1247
- const tokenEndpointResponse = await this.#getAuthClient(domainForSession).getTokenByRefreshToken(tokenByRefreshTokenOptions);
1330
+ let response;
1331
+ let tokenEndpointResponse;
1332
+ if (resolvedOptions?.fullResponse) {
1333
+ const authJsResult = await this.#getAuthClient(domainForSession).getTokenByRefreshToken({
1334
+ ...tokenByRefreshTokenOptions,
1335
+ fullResponse: true
1336
+ }, requestOptions);
1337
+ tokenEndpointResponse = authJsResult.data;
1338
+ response = authJsResult.response;
1339
+ } else {
1340
+ tokenEndpointResponse = await this.#getAuthClient(domainForSession).getTokenByRefreshToken(tokenByRefreshTokenOptions, requestOptions);
1341
+ }
1248
1342
  const existingStateData = await this.#stateStore.get(this.#stateStoreIdentifier, resolvedStoreOptions);
1249
1343
  const updatedStateData = updateStateData(audience, existingStateData, tokenEndpointResponse, {
1250
1344
  domain: domainForSession
1251
1345
  });
1252
1346
  await this.#stateStore.set(this.#stateStoreIdentifier, updatedStateData, false, resolvedStoreOptions);
1253
- return {
1347
+ const returnTokenSet = {
1254
1348
  accessToken: tokenEndpointResponse.accessToken,
1255
1349
  scope: tokenEndpointResponse.scope,
1256
1350
  expiresAt: tokenEndpointResponse.expiresAt,
1257
1351
  audience
1258
1352
  };
1353
+ if (resolvedOptions?.fullResponse) {
1354
+ if (!response) {
1355
+ throw new import_auth0_auth_js.MissingCapturedResponseError();
1356
+ }
1357
+ return { data: returnTokenSet, response };
1358
+ }
1359
+ return returnTokenSet;
1259
1360
  }
1260
- /**
1261
- * Retrieves an access token for a connection.
1262
- *
1263
- * This method attempts to obtain an access token for a specified connection.
1264
- * It first checks if a refresh token exists in the store.
1265
- * If no refresh token is found, it throws an `AccessTokenForConnectionError` indicating
1266
- * that the refresh token was not found.
1267
- *
1268
- * @param options - Options for retrieving an access token for a connection.
1269
- * @param storeOptions Optional options used to pass to the Transaction and State Store.
1270
- *
1271
- * @throws {TokenForConnectionError} If the refresh token was not found or there was an issue requesting the access token.
1272
- *
1273
- * @returns The Connection Token Set, containing the access token for the connection, as well as additional information.
1274
- */
1275
- async getAccessTokenForConnection(options, storeOptions) {
1361
+ async getAccessTokenForConnection(options, storeOptions, requestOptions) {
1276
1362
  const stateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
1277
1363
  const sessionDomain = stateData ? this.#getSessionDomain(stateData) : this.#staticDomain;
1278
1364
  if (this.#isResolverMode()) {
@@ -1291,7 +1377,9 @@ var ServerClient = class {
1291
1377
  (tokenSet) => tokenSet.connection === options.connection
1292
1378
  );
1293
1379
  if (connectionTokenSet && connectionTokenSet.expiresAt > Date.now() / 1e3) {
1294
- return connectionTokenSet;
1380
+ if (!options.fullResponse) {
1381
+ return connectionTokenSet;
1382
+ }
1295
1383
  }
1296
1384
  if (!stateData?.refreshToken) {
1297
1385
  throw new import_auth0_auth_js.TokenForConnectionError(
@@ -1299,11 +1387,24 @@ var ServerClient = class {
1299
1387
  );
1300
1388
  }
1301
1389
  const domainForSession = sessionDomain;
1302
- const tokenEndpointResponse = await this.#getAuthClient(domainForSession).getTokenForConnection({
1303
- connection: options.connection,
1304
- loginHint: options.loginHint,
1305
- refreshToken: stateData.refreshToken
1306
- });
1390
+ let response;
1391
+ let tokenEndpointResponse;
1392
+ if (options.fullResponse) {
1393
+ const authJsResult = await this.#getAuthClient(domainForSession).getTokenForConnection({
1394
+ connection: options.connection,
1395
+ loginHint: options.loginHint,
1396
+ refreshToken: stateData.refreshToken,
1397
+ fullResponse: true
1398
+ }, requestOptions);
1399
+ tokenEndpointResponse = authJsResult.data;
1400
+ response = authJsResult.response;
1401
+ } else {
1402
+ tokenEndpointResponse = await this.#getAuthClient(domainForSession).getTokenForConnection({
1403
+ connection: options.connection,
1404
+ loginHint: options.loginHint,
1405
+ refreshToken: stateData.refreshToken
1406
+ }, requestOptions);
1407
+ }
1307
1408
  const updatedStateData = updateStateDataForConnectionTokenSet(
1308
1409
  options,
1309
1410
  {
@@ -1313,13 +1414,20 @@ var ServerClient = class {
1313
1414
  tokenEndpointResponse
1314
1415
  );
1315
1416
  await this.#stateStore.set(this.#stateStoreIdentifier, updatedStateData, false, storeOptions);
1316
- return {
1417
+ const returnConnectionTokenSet = {
1317
1418
  accessToken: tokenEndpointResponse.accessToken,
1318
1419
  scope: tokenEndpointResponse.scope,
1319
1420
  expiresAt: tokenEndpointResponse.expiresAt,
1320
1421
  connection: options.connection,
1321
1422
  loginHint: options.loginHint
1322
1423
  };
1424
+ if (options.fullResponse) {
1425
+ if (!response) {
1426
+ throw new import_auth0_auth_js.MissingCapturedResponseError();
1427
+ }
1428
+ return { data: returnConnectionTokenSet, response };
1429
+ }
1430
+ return returnConnectionTokenSet;
1323
1431
  }
1324
1432
  /**
1325
1433
  * Revokes the refresh token stored in the current session, or an explicitly supplied token.
@@ -1331,12 +1439,13 @@ var ServerClient = class {
1331
1439
  *
1332
1440
  * @param options Optionally supply a token to revoke instead of reading from the session.
1333
1441
  * @param storeOptions Optional options passed to the StateStore.
1442
+ * @param requestOptions Optional per-request options (signal, headers, customFetch). Applied to the revocation request.
1334
1443
  *
1335
1444
  * @throws {MissingRequiredArgumentError} If `options.token` is an empty string.
1336
1445
  * @throws {MissingSessionError} If no refresh token is found in the session and none was provided.
1337
1446
  * @throws {TokenRevocationError} If the revocation request fails.
1338
1447
  */
1339
- async revokeRefreshToken(options = {}, storeOptions) {
1448
+ async revokeRefreshToken(options = {}, storeOptions, requestOptions) {
1340
1449
  if (options.token !== void 0 && options.token.length === 0) {
1341
1450
  throw new MissingRequiredArgumentError("options.token must not be an empty string.");
1342
1451
  }
@@ -1360,18 +1469,19 @@ var ServerClient = class {
1360
1469
  } else {
1361
1470
  authClient = this.authClient;
1362
1471
  }
1363
- await authClient.revokeToken({ token: refreshToken, tokenTypeHint: "refresh_token" });
1472
+ await authClient.revokeToken({ token: refreshToken, tokenTypeHint: "refresh_token" }, requestOptions);
1364
1473
  }
1365
1474
  /**
1366
1475
  * Logs the user out and returns a URL to redirect the user-agent to after they log out.
1367
1476
  * @param options Options used to configure the logout process.
1368
1477
  * @param storeOptions Optional options used to pass to the Transaction and State Store.
1478
+ * @param requestOptions Optional per-request options (signal, headers, customFetch). Applied to the token revocation ONLY. Building the logout URL is local string work and issues no request, so nothing here can affect it.
1369
1479
  * @returns {URL}
1370
1480
  */
1371
- async logout(options, storeOptions) {
1481
+ async logout(options, storeOptions, requestOptions) {
1372
1482
  if (!this.#isResolverMode()) {
1373
1483
  try {
1374
- await this.revokeRefreshToken({}, storeOptions);
1484
+ await this.revokeRefreshToken({}, storeOptions, requestOptions);
1375
1485
  } catch {
1376
1486
  }
1377
1487
  await this.#stateStore.delete(this.#stateStoreIdentifier, storeOptions);
@@ -1387,39 +1497,33 @@ var ServerClient = class {
1387
1497
  const domainMatches = sessionDomain === resolvedDomain;
1388
1498
  if (domainMatches) {
1389
1499
  try {
1390
- await this.revokeRefreshToken({}, storeOptions);
1500
+ await this.revokeRefreshToken({}, storeOptions, requestOptions);
1391
1501
  } catch {
1392
1502
  }
1393
1503
  await this.#stateStore.delete(this.#stateStoreIdentifier, storeOptions);
1394
1504
  }
1395
1505
  return authClient.buildLogoutUrl(options);
1396
1506
  }
1397
- /**
1398
- * Exchanges a custom token for Auth0 tokens and persists the resulting session (RFC 8693).
1399
- *
1400
- * Calls the token endpoint using the RFC 8693 Token Exchange grant, then stores the
1401
- * resulting tokens in the StateStore — effectively logging the user in without an
1402
- * interactive browser flow. Use this when the caller already holds a trusted external
1403
- * token (e.g. a Google ID token, a legacy system token) and wants to establish an
1404
- * Auth0 session from it.
1405
- *
1406
- * Requires a Token Exchange Profile configured in your Auth0 tenant.
1407
- *
1408
- * @param options Options for the custom token exchange, including the subject token and its type.
1409
- * @param storeOptions Optional options passed to the StateStore.
1410
- *
1411
- * @throws {TokenExchangeError} If the exchange fails or the subject token is invalid.
1412
- * @throws {MissingClientAuthError} If client credentials are not configured.
1413
- *
1414
- * @returns A promise resolving to an object containing `authorizationDetails` when RAR was used.
1415
- */
1416
- async loginWithCustomTokenExchange(options, storeOptions) {
1507
+ async loginWithCustomTokenExchange(options, storeOptions, requestOptions) {
1417
1508
  const domain = await this.#resolveDomain(storeOptions);
1418
1509
  const authClient = this.#getAuthClient(domain);
1419
- const tokenEndpointResponse = await authClient.exchangeToken({
1420
- ...options,
1421
- scope: ensureOpenIdScope(options.scope)
1422
- });
1510
+ let response;
1511
+ let tokenEndpointResponse;
1512
+ if (options.fullResponse) {
1513
+ const { fullResponse: _, ...rest } = options;
1514
+ const authJsResult = await authClient.exchangeToken({
1515
+ ...rest,
1516
+ scope: ensureOpenIdScope(options.scope),
1517
+ fullResponse: true
1518
+ }, requestOptions);
1519
+ tokenEndpointResponse = authJsResult.data;
1520
+ response = authJsResult.response;
1521
+ } else {
1522
+ tokenEndpointResponse = await authClient.exchangeToken({
1523
+ ...options,
1524
+ scope: ensureOpenIdScope(options.scope)
1525
+ }, requestOptions);
1526
+ }
1423
1527
  const existingStateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
1424
1528
  const stateData = updateStateData(
1425
1529
  this.#options.authorizationParams?.audience ?? "default",
@@ -1428,30 +1532,25 @@ var ServerClient = class {
1428
1532
  { domain }
1429
1533
  );
1430
1534
  await this.#stateStore.set(this.#stateStoreIdentifier, stateData, true, storeOptions);
1431
- return { authorizationDetails: tokenEndpointResponse.authorizationDetails };
1535
+ const result = {
1536
+ authorizationDetails: tokenEndpointResponse.authorizationDetails
1537
+ };
1538
+ if (options.fullResponse) {
1539
+ if (!response) {
1540
+ throw new import_auth0_auth_js.MissingCapturedResponseError();
1541
+ }
1542
+ return { data: result, response };
1543
+ }
1544
+ return result;
1432
1545
  }
1433
- /**
1434
- * Exchanges a custom token for Auth0 tokens without establishing a session (RFC 8693).
1435
- *
1436
- * Performs the same RFC 8693 Token Exchange as `loginWithCustomTokenExchange` but
1437
- * returns the raw token response without writing anything to the StateStore. Use this
1438
- * for delegation or impersonation flows where you need downstream tokens but do not
1439
- * want to create or modify the current user session.
1440
- *
1441
- * Requires a Token Exchange Profile configured in your Auth0 tenant.
1442
- *
1443
- * @param options Options for the custom token exchange, including the subject token and its type.
1444
- * @param storeOptions Optional options passed to the StateStore (used only for domain resolution in resolver mode).
1445
- *
1446
- * @throws {TokenExchangeError} If the exchange fails or the subject token is invalid.
1447
- * @throws {MissingClientAuthError} If client credentials are not configured.
1448
- *
1449
- * @returns A promise resolving to the token response from Auth0.
1450
- */
1451
- async customTokenExchange(options, storeOptions) {
1546
+ async customTokenExchange(options, storeOptions, requestOptions) {
1452
1547
  const domain = await this.#resolveDomain(storeOptions);
1453
1548
  const authClient = this.#getAuthClient(domain);
1454
- return authClient.exchangeToken(options);
1549
+ if (options.fullResponse) {
1550
+ const { fullResponse: _, ...rest } = options;
1551
+ return authClient.exchangeToken({ ...rest, fullResponse: true }, requestOptions);
1552
+ }
1553
+ return authClient.exchangeToken(options, requestOptions);
1455
1554
  }
1456
1555
  /**
1457
1556
  * Requests a Session Transfer Token (STT) for impersonation via session transfer (RFC 8693).
@@ -1475,8 +1574,17 @@ var ServerClient = class {
1475
1574
  * {@link ServerClient.buildSessionTransferRedirect}, which is forwarded to the target's
1476
1575
  * `/authorize` on the redirect.
1477
1576
  *
1577
+ * @remarks
1578
+ * If the actor's ID token has expired, an internal refresh is performed before the
1579
+ * session transfer token exchange. This refresh call is NOT guarded by the caller's
1580
+ * requestOptions.signal — if the signal fires during this step, the abort is ignored.
1581
+ * Only the final exchangeToken call respects the signal.
1582
+ * Thread requestOptions into #resolveSessionTransferActor in a future minor if
1583
+ * callers need full-request abort coverage.
1584
+ *
1478
1585
  * @param options Options including the developer-supplied `subjectToken`/`subjectTokenType` and an optional explicit `actor`.
1479
1586
  * @param storeOptions Optional options used to read the agent session (for the actor) and resolve the request domain.
1587
+ * @param requestOptions Optional per-request options (signal, headers, customFetch). Applied to the STT exchange only. Resolving the actor may refresh an expired agent session ID token, and that refresh is an internal call outside the caller's per-request scope, so it does not receive these options.
1480
1588
  *
1481
1589
  * @throws {TokenExchangeError} With code `actor_unavailable` when no explicit actor is given and no usable session ID token can be resolved — no logged-in agent, a session that belongs to a different domain in resolver mode, or an expired ID token that cannot be refreshed (raised client-side, before any network call). With the default code when the exchange itself fails; a server-side `setactor_required` or `session_transfer_disabled` condition is surfaced via `cause.error` / `cause.error_description`. An organization the tenant rejects also surfaces here.
1482
1590
  * @throws {MissingClientAuthError} When client credentials are not configured (STT requires a confidential client).
@@ -1485,7 +1593,7 @@ var ServerClient = class {
1485
1593
  *
1486
1594
  * @returns A promise resolving to a {@link SessionTransferTokenResult} containing the STT and its metadata.
1487
1595
  */
1488
- async requestSessionTransferToken(options, storeOptions) {
1596
+ async requestSessionTransferToken(options, storeOptions, requestOptions) {
1489
1597
  if (!options.subjectToken || !options.subjectToken.trim()) {
1490
1598
  throw new MissingRequiredArgumentError("subjectToken");
1491
1599
  }
@@ -1511,7 +1619,7 @@ var ServerClient = class {
1511
1619
  // `/authorize`; neither implies the other.
1512
1620
  organization: options.organization,
1513
1621
  extra: options.extra
1514
- });
1622
+ }, requestOptions);
1515
1623
  return {
1516
1624
  sessionTransferToken: response.accessToken,
1517
1625
  // Surface exactly what the server returned — never fabricate the URN, so a non-STT
@@ -1635,6 +1743,11 @@ var ServerClient = class {
1635
1743
  }
1636
1744
  /**
1637
1745
  * Handles the backchannel logout process by verifying the logout token and deleting the session from the store if the logout token was considered valid.
1746
+ *
1747
+ * This does not accept `RequestOptions`. Verification does fetch JWKS, but the auth-js method it
1748
+ * delegates to, `verifyLogoutToken`, takes no `requestOptions`, so there is nothing to forward.
1749
+ * That fetch always uses the client's configured `customFetch`.
1750
+ *
1638
1751
  * @param logoutToken The logout token to verify and use to delete the session from the store.
1639
1752
  * @param storeOptions Optional options used to pass to the Transaction and State Store.
1640
1753
  *
@@ -2026,6 +2139,7 @@ var import_auth0_auth_js4 = require("@auth0/auth0-auth-js");
2026
2139
  TokenExchangeError,
2027
2140
  TokenExchangeErrorCode,
2028
2141
  TokenRevocationError,
2142
+ UserInfoError,
2029
2143
  isMfaRequiredError
2030
2144
  });
2031
2145
  //# sourceMappingURL=index.cjs.map