@auth0/auth0-server-js 1.12.1 → 1.14.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
@@ -23,37 +23,40 @@ __export(index_exports, {
23
23
  AbstractStateStore: () => AbstractStateStore,
24
24
  AbstractTransactionStore: () => AbstractTransactionStore,
25
25
  BackchannelLogoutError: () => BackchannelLogoutError,
26
- ChangePasswordError: () => import_auth0_auth_js4.ChangePasswordError,
26
+ ChangePasswordError: () => import_auth0_auth_js5.ChangePasswordError,
27
27
  CookieTransactionStore: () => CookieTransactionStore,
28
+ EnterpriseConnectNotSupportedError: () => import_auth0_auth_js6.EnterpriseConnectNotSupportedError,
28
29
  InvalidConfigurationError: () => InvalidConfigurationError,
29
30
  IssuerValidationError: () => IssuerValidationError,
30
- MfaChallengeError: () => import_auth0_auth_js2.MfaChallengeError,
31
- MfaEnrollmentError: () => import_auth0_auth_js2.MfaEnrollmentError,
32
- MfaListAuthenticatorsError: () => import_auth0_auth_js2.MfaListAuthenticatorsError,
33
- MfaVerifyError: () => import_auth0_auth_js2.MfaVerifyError,
34
- MissingClientAuthError: () => import_auth0_auth_js5.MissingClientAuthError,
31
+ MfaChallengeError: () => import_auth0_auth_js3.MfaChallengeError,
32
+ MfaEnrollmentError: () => import_auth0_auth_js3.MfaEnrollmentError,
33
+ MfaListAuthenticatorsError: () => import_auth0_auth_js3.MfaListAuthenticatorsError,
34
+ MfaVerifyError: () => import_auth0_auth_js3.MfaVerifyError,
35
+ MissingClientAuthError: () => import_auth0_auth_js6.MissingClientAuthError,
35
36
  MissingRequiredArgumentError: () => MissingRequiredArgumentError,
36
37
  MissingSessionError: () => MissingSessionError,
37
38
  MissingTransactionError: () => MissingTransactionError,
38
- OrganizationValidationError: () => import_auth0_auth_js5.OrganizationValidationError,
39
- PasskeyChallengeError: () => import_auth0_auth_js3.PasskeyChallengeError,
40
- PasskeyGetTokenError: () => import_auth0_auth_js3.PasskeyGetTokenError,
41
- PasskeyRegisterError: () => import_auth0_auth_js3.PasskeyRegisterError,
42
- PasswordlessStartError: () => import_auth0_auth_js5.PasswordlessStartError,
43
- PasswordlessVerifyError: () => import_auth0_auth_js5.PasswordlessVerifyError,
39
+ OrganizationValidationError: () => import_auth0_auth_js6.OrganizationValidationError,
40
+ PasskeyChallengeError: () => import_auth0_auth_js4.PasskeyChallengeError,
41
+ PasskeyGetTokenError: () => import_auth0_auth_js4.PasskeyGetTokenError,
42
+ PasskeyRegisterError: () => import_auth0_auth_js4.PasskeyRegisterError,
43
+ PasswordlessStartError: () => import_auth0_auth_js6.PasswordlessStartError,
44
+ PasswordlessVerifyError: () => import_auth0_auth_js6.PasswordlessVerifyError,
44
45
  ServerClient: () => ServerClient,
45
46
  ServerDatabaseClient: () => ServerDatabaseClient,
46
47
  ServerMfaClient: () => ServerMfaClient,
47
48
  ServerPasskeyClient: () => ServerPasskeyClient,
48
49
  SessionExpiredError: () => SessionExpiredError,
49
- SignUpError: () => import_auth0_auth_js4.SignUpError,
50
+ SignUpError: () => import_auth0_auth_js5.SignUpError,
50
51
  StartLinkUserError: () => StartLinkUserError,
51
52
  StatefulStateStore: () => StatefulStateStore,
52
53
  StatelessStateStore: () => StatelessStateStore,
53
- TokenExchangeError: () => import_auth0_auth_js5.TokenExchangeError,
54
+ TokenExchangeError: () => import_auth0_auth_js6.TokenExchangeError,
54
55
  TokenExchangeErrorCode: () => TokenExchangeErrorCode,
55
- TokenRevocationError: () => import_auth0_auth_js5.TokenRevocationError,
56
- isMfaRequiredError: () => import_auth0_auth_js5.isMfaRequiredError
56
+ TokenRevocationError: () => import_auth0_auth_js6.TokenRevocationError,
57
+ UserInfoError: () => import_auth0_auth_js6.UserInfoError,
58
+ isFederatedDomain: () => import_auth0_auth_js6.isFederatedDomain,
59
+ isMfaRequiredError: () => import_auth0_auth_js6.isMfaRequiredError
57
60
  });
58
61
  module.exports = __toCommonJS(index_exports);
59
62
 
@@ -224,7 +227,7 @@ function updateStateDataForConnectionTokenSet(options, stateData, tokenEndpointR
224
227
  }
225
228
 
226
229
  // src/server-client.ts
227
- var import_auth0_auth_js = require("@auth0/auth0-auth-js");
230
+ var import_auth0_auth_js2 = require("@auth0/auth0-auth-js");
228
231
 
229
232
  // src/utils.ts
230
233
  var DEFAULT_SCOPES = "openid profile email offline_access";
@@ -262,7 +265,7 @@ function getTelemetryConfig(config) {
262
265
  return {
263
266
  enabled: true,
264
267
  name: config?.name ?? "@auth0/auth0-server-js",
265
- version: config?.version ?? "1.12.1"
268
+ version: config?.version ?? "1.14.0"
266
269
  };
267
270
  }
268
271
 
@@ -282,8 +285,8 @@ var ServerMfaClient = class {
282
285
  * @returns Promise resolving to an array of enrolled authenticators
283
286
  * @throws {MfaListAuthenticatorsError} When the request fails
284
287
  */
285
- async listAuthenticators(options) {
286
- return this.#options.authClient.mfa.listAuthenticators(options);
288
+ async listAuthenticators(options, requestOptions) {
289
+ return this.#options.authClient.mfa.listAuthenticators(options, requestOptions);
287
290
  }
288
291
  /**
289
292
  * Enrolls a new MFA authenticator for the user.
@@ -292,8 +295,8 @@ var ServerMfaClient = class {
292
295
  * @returns Promise resolving to enrollment response with authenticator details
293
296
  * @throws {MfaEnrollmentError} When enrollment fails
294
297
  */
295
- async enrollAuthenticator(options) {
296
- return this.#options.authClient.mfa.enrollAuthenticator(options);
298
+ async enrollAuthenticator(options, requestOptions) {
299
+ return this.#options.authClient.mfa.enrollAuthenticator(options, requestOptions);
297
300
  }
298
301
  /**
299
302
  * Initiates an MFA challenge for user verification.
@@ -302,8 +305,8 @@ var ServerMfaClient = class {
302
305
  * @returns Promise resolving to challenge response with challenge details
303
306
  * @throws {MfaChallengeError} When the challenge fails
304
307
  */
305
- async challengeAuthenticator(options) {
306
- return this.#options.authClient.mfa.challengeAuthenticator(options);
308
+ async challengeAuthenticator(options, requestOptions) {
309
+ return this.#options.authClient.mfa.challengeAuthenticator(options, requestOptions);
307
310
  }
308
311
  /**
309
312
  * Verifies an MFA challenge and completes the authentication flow.
@@ -317,8 +320,8 @@ var ServerMfaClient = class {
317
320
  * @returns The tokens returned by Auth0 after successful verification
318
321
  * @throws {MfaVerifyError} When verification fails (e.g. invalid token, wrong code)
319
322
  */
320
- async verify(options, storeOptions) {
321
- const tokenResponse = await this.#options.authClient.mfa.verify(options);
323
+ async verify(options, storeOptions, requestOptions) {
324
+ const tokenResponse = await this.#options.authClient.mfa.verify(options, requestOptions);
322
325
  const audience = options.audience ?? this.#options.defaultAudience;
323
326
  const existingStateData = await this.#options.stateStore.get(
324
327
  this.#options.stateStoreIdentifier,
@@ -381,10 +384,10 @@ var ServerPasskeyClient = class {
381
384
  *
382
385
  * @returns A promise resolving to the signup challenge.
383
386
  */
384
- async register(options, storeOptions) {
387
+ async register(options, storeOptions, requestOptions) {
385
388
  const domain = await this.#options.resolveDomain(storeOptions);
386
389
  const authClient = this.#options.getAuthClient(domain);
387
- return authClient.passkey.register(options);
390
+ return authClient.passkey.register(options, requestOptions);
388
391
  }
389
392
  /**
390
393
  * Requests a passkey login challenge for an existing user.
@@ -406,10 +409,10 @@ var ServerPasskeyClient = class {
406
409
  *
407
410
  * @returns A promise resolving to the login challenge.
408
411
  */
409
- async challenge(options, storeOptions) {
412
+ async challenge(options, storeOptions, requestOptions) {
410
413
  const domain = await this.#options.resolveDomain(storeOptions);
411
414
  const authClient = this.#options.getAuthClient(domain);
412
- return authClient.passkey.challenge(options);
415
+ return authClient.passkey.challenge(options, requestOptions);
413
416
  }
414
417
  /**
415
418
  * Completes a passkey authentication flow (signup or login) by exchanging the
@@ -431,7 +434,7 @@ var ServerPasskeyClient = class {
431
434
  *
432
435
  * @returns A promise resolving to an object containing the authorizationDetails (when RAR was used).
433
436
  */
434
- async getToken(options, storeOptions) {
437
+ async getToken(options, storeOptions, requestOptions) {
435
438
  const scope = ensureOpenIdScope(options.scope ?? this.#options.defaultScope);
436
439
  const audience = options.audience ?? this.#options.defaultAudience;
437
440
  const domain = await this.#options.resolveDomain(storeOptions);
@@ -440,7 +443,7 @@ var ServerPasskeyClient = class {
440
443
  ...options,
441
444
  scope,
442
445
  audience
443
- });
446
+ }, requestOptions);
444
447
  const existingStateData = await this.#options.stateStore.get(this.#options.stateStoreIdentifier, storeOptions);
445
448
  const stateData = updateStateData(audience ?? "default", existingStateData, tokenEndpointResponse, { domain });
446
449
  await this.#options.stateStore.set(this.#options.stateStoreIdentifier, stateData, true, storeOptions);
@@ -473,9 +476,9 @@ var ServerDatabaseClient = class {
473
476
  *
474
477
  * @returns A promise resolving to the created user result with a normalized `id` field.
475
478
  */
476
- async signUp(options, storeOptions) {
479
+ async signUp(options, storeOptions, requestOptions) {
477
480
  const domain = await this.#options.resolveDomain(storeOptions);
478
- return this.#options.getAuthClient(domain).database.signUp(options);
481
+ return this.#options.getAuthClient(domain).database.signUp(options, requestOptions);
479
482
  }
480
483
  /**
481
484
  * Requests a password-change email for a database connection user.
@@ -491,11 +494,52 @@ var ServerDatabaseClient = class {
491
494
  *
492
495
  * @returns A promise resolving to the server's plain-text confirmation message.
493
496
  */
494
- async changePassword(options, storeOptions) {
497
+ async changePassword(options, storeOptions, requestOptions) {
495
498
  const domain = await this.#options.resolveDomain(storeOptions);
496
- return this.#options.getAuthClient(domain).database.changePassword(options);
499
+ return this.#options.getAuthClient(domain).database.changePassword(options, requestOptions);
500
+ }
501
+ };
502
+
503
+ // src/enterprise-connect.ts
504
+ var import_auth0_auth_js = require("@auth0/auth0-auth-js");
505
+ var EC_ALLOWED_METHODS = /* @__PURE__ */ new Set([
506
+ "startInteractiveLogin",
507
+ "startEnterpriseLogin",
508
+ "completeInteractiveLogin",
509
+ "logout",
510
+ "customTokenExchange",
511
+ "handleBackchannelLogout"
512
+ ]);
513
+ var EC_ALLOWED_GETTERS = /* @__PURE__ */ new Set(["authClient"]);
514
+ var NullStateStore = class {
515
+ async get() {
516
+ return void 0;
517
+ }
518
+ async set() {
519
+ }
520
+ async delete() {
521
+ }
522
+ async deleteByLogoutToken() {
497
523
  }
498
524
  };
525
+ function applyEnterpriseConnectRestrictions(instance) {
526
+ const proto = Object.getPrototypeOf(instance);
527
+ for (const [name, desc] of Object.entries(Object.getOwnPropertyDescriptors(proto))) {
528
+ if (name === "constructor") continue;
529
+ if (desc.get && !EC_ALLOWED_GETTERS.has(name)) {
530
+ Object.defineProperty(instance, name, {
531
+ get: () => {
532
+ throw new import_auth0_auth_js.EnterpriseConnectNotSupportedError(name);
533
+ },
534
+ configurable: true
535
+ });
536
+ } else if (typeof desc.value === "function" && !EC_ALLOWED_METHODS.has(name)) {
537
+ instance[name] = () => {
538
+ throw new import_auth0_auth_js.EnterpriseConnectNotSupportedError(name);
539
+ };
540
+ }
541
+ }
542
+ }
499
543
 
500
544
  // src/server-client.ts
501
545
  var normalizeDomain = (value) => {
@@ -514,7 +558,7 @@ var decodeIssuer = (token) => {
514
558
  var ID_TOKEN_TYPE = "urn:ietf:params:oauth:token-type:id_token";
515
559
  var ID_TOKEN_EXPIRY_SKEW_SECONDS = 30;
516
560
  var actorUnavailableError = (message) => {
517
- const error = new import_auth0_auth_js.TokenExchangeError(message);
561
+ const error = new import_auth0_auth_js2.TokenExchangeError(message);
518
562
  error.code = TokenExchangeErrorCode.ACTOR_UNAVAILABLE;
519
563
  return error;
520
564
  };
@@ -535,6 +579,7 @@ var ServerClient = class {
535
579
  #transactionStoreIdentifier;
536
580
  #stateStore;
537
581
  #stateStoreIdentifier;
582
+ #enterpriseConnect;
538
583
  #authClientOptions;
539
584
  #staticDomain;
540
585
  #authClient;
@@ -605,16 +650,36 @@ var ServerClient = class {
605
650
  }
606
651
  constructor(options) {
607
652
  this.#options = options;
653
+ this.#enterpriseConnect = !!options.enterpriseConnect;
608
654
  this.#stateStoreIdentifier = this.#options.stateIdentifier || "__a0_session";
609
655
  this.#transactionStoreIdentifier = this.#options.transactionIdentifier || "__a0_tx";
610
656
  this.#transactionStore = options.transactionStore;
611
- this.#stateStore = options.stateStore;
612
- if (!this.#options.stateStore) {
657
+ if (!this.#enterpriseConnect && !this.#options.stateStore) {
613
658
  throw new MissingRequiredArgumentError("stateStore");
614
659
  }
660
+ this.#stateStore = this.#enterpriseConnect ? new NullStateStore() : this.#options.stateStore;
615
661
  if (!this.#options.transactionStore) {
616
662
  throw new MissingRequiredArgumentError("transactionStore");
617
663
  }
664
+ if (this.#enterpriseConnect) {
665
+ if (typeof this.#options.domain === "function") {
666
+ throw new InvalidConfigurationError(
667
+ "Enterprise Connect requires a static domain string. DomainResolver is not supported because isFederatedDomain needs a concrete domain."
668
+ );
669
+ }
670
+ const scope = this.#options.authorizationParams?.scope ?? "";
671
+ if (scope.includes("offline_access")) {
672
+ console.warn(
673
+ '[Auth0] Enterprise Connect: "offline_access" in scope has no effect. B2B Integration clients are not issued refresh tokens.'
674
+ );
675
+ }
676
+ if (this.#options.organization || this.#options.authorizationParams?.organization) {
677
+ console.warn(
678
+ '[Auth0] Enterprise Connect: static "organization" is set. The organization is resolved per login by HRD from the login_hint email domain. A static value routes all enterprise users to the same organization.'
679
+ );
680
+ }
681
+ applyEnterpriseConnectRestrictions(this);
682
+ }
618
683
  if (typeof this.#options.domain !== "string" && typeof this.#options.domain !== "function") {
619
684
  throw new InvalidConfigurationError("domain must be a string or resolver function");
620
685
  }
@@ -631,7 +696,7 @@ var ServerClient = class {
631
696
  if (typeof this.#options.domain === "string") {
632
697
  const domain = normalizeDomain(this.#options.domain);
633
698
  this.#staticDomain = domain;
634
- this.#authClient = new import_auth0_auth_js.AuthClient({
699
+ this.#authClient = new import_auth0_auth_js2.AuthClient({
635
700
  domain,
636
701
  ...this.#authClientOptions,
637
702
  telemetry: getTelemetryConfig(this.#options.telemetry)
@@ -668,7 +733,7 @@ var ServerClient = class {
668
733
  return normalizeDomain(this.#options.domain);
669
734
  }
670
735
  #createAuthClient(domain) {
671
- return new import_auth0_auth_js.AuthClient({
736
+ return new import_auth0_auth_js2.AuthClient({
672
737
  domain,
673
738
  ...this.#authClientOptions,
674
739
  telemetry: getTelemetryConfig(this.#options.telemetry)
@@ -705,6 +770,33 @@ var ServerClient = class {
705
770
  const resolvedDomain = await this.#resolveDomain(storeOptions);
706
771
  return sessionDomain === resolvedDomain;
707
772
  }
773
+ /**
774
+ * Starts the Enterprise Connect login flow. Performs WebFinger domain discovery
775
+ * and, if the email domain is federated, initiates an interactive login with `login_hint`.
776
+ *
777
+ * @param options Options including the user's email and optional returnTo URL.
778
+ * @param storeOptions Optional options passed to the Transaction Store.
779
+ *
780
+ * @returns A URL to redirect to (federated domain) or null (not federated / invalid email).
781
+ */
782
+ async startEnterpriseLogin(options, storeOptions) {
783
+ const parts = options.email.split("@");
784
+ if (parts.length !== 2 || !parts[0] || !parts[1]) return null;
785
+ const emailDomain = parts[1].toLowerCase();
786
+ const domain = await this.#resolveDomain(storeOptions);
787
+ const isFederated = await (0, import_auth0_auth_js2.isFederatedDomain)(domain, emailDomain, {
788
+ customFetch: this.#options.customFetch,
789
+ telemetry: getTelemetryConfig(this.#options.telemetry)
790
+ });
791
+ if (!isFederated) return null;
792
+ return this.startInteractiveLogin(
793
+ {
794
+ authorizationParams: { login_hint: options.email },
795
+ appState: options.returnTo ? { returnTo: options.returnTo } : void 0
796
+ },
797
+ storeOptions
798
+ );
799
+ }
708
800
  /**
709
801
  * Starts the interactive login process, and returns a URL to redirect the user-agent to to request authorization at Auth0.
710
802
  *
@@ -726,12 +818,13 @@ var ServerClient = class {
726
818
  if (!redirectUri) {
727
819
  throw new MissingRequiredArgumentError("authorizationParams.redirect_uri");
728
820
  }
729
- const scope = ensureOpenIdScope(options?.authorizationParams?.scope ?? this.#options.authorizationParams?.scope);
821
+ const rawScope = ensureOpenIdScope(options?.authorizationParams?.scope ?? this.#options.authorizationParams?.scope);
822
+ const scope = this.#enterpriseConnect ? rawScope.split(" ").filter((s) => s !== "offline_access").join(" ") : rawScope;
730
823
  const perLoginAuthParamsOrganization = typeof options?.authorizationParams?.organization === "string" ? options.authorizationParams.organization : void 0;
731
824
  const clientAuthParamsOrganization = typeof this.#options.authorizationParams?.organization === "string" ? this.#options.authorizationParams.organization : void 0;
732
825
  const resolvedOrganization = options?.organization ?? perLoginAuthParamsOrganization ?? this.#options.organization ?? clientAuthParamsOrganization;
733
826
  if (resolvedOrganization !== void 0 && !resolvedOrganization.trim()) {
734
- throw new import_auth0_auth_js.OrganizationValidationError("organization must not be blank");
827
+ throw new import_auth0_auth_js2.OrganizationValidationError("organization must not be blank");
735
828
  }
736
829
  const hasInvitation = !!(options?.invitation || options?.authorizationParams?.invitation);
737
830
  if (hasInvitation && !resolvedOrganization) {
@@ -768,6 +861,7 @@ var ServerClient = class {
768
861
  * Takes an URL, extract the Authorization Code flow query parameters and requests a token.
769
862
  * @param url The URl from which the query params should be extracted to exchange for a token.
770
863
  * @param storeOptions Optional options used to pass to the Transaction and State Store.
864
+ * @param requestOptions Optional per-request options (signal, headers, customFetch). Applied to the code-for-token exchange.
771
865
  *
772
866
  * @throws {MissingTransactionError} When no transaction was found.
773
867
  * @throws {TokenByCodeError} If there was an issue requesting the access token.
@@ -775,8 +869,16 @@ var ServerClient = class {
775
869
  * @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
870
  *
777
871
  * @returns A promise resolving to an object, containing the original appState (if present) and the authorizationDetails (when RAR was used).
872
+ * In Enterprise Connect mode, also includes `idTokenClaims` and `user`.
873
+ *
874
+ * @remarks
875
+ * This method does not support the `fullResponse` opt-in in v1. It accepts
876
+ * `url` and `storeOptions` with no intermediate options object; adding
877
+ * `fullResponse` would require a new options parameter and is deferred to
878
+ * a later revision.
879
+ * TODO(#<issue-number>): add fullResponse overload to completeInteractiveLogin in a future minor.
778
880
  */
779
- async completeInteractiveLogin(url, storeOptions) {
881
+ async completeInteractiveLogin(url, storeOptions, requestOptions) {
780
882
  const transactionData = await this.#transactionStore.get(this.#transactionStoreIdentifier, storeOptions);
781
883
  if (!transactionData) {
782
884
  throw new MissingTransactionError();
@@ -787,8 +889,18 @@ var ServerClient = class {
787
889
  // TransactionData.codeVerifier is optional only to accommodate magic-link transactions.
788
890
  codeVerifier: transactionData.codeVerifier,
789
891
  organization: transactionData.organization
790
- });
892
+ }, requestOptions);
791
893
  await this.#transactionStore.delete(this.#transactionStoreIdentifier, storeOptions);
894
+ if (this.#enterpriseConnect) {
895
+ const claims = tokenEndpointResponse.claims;
896
+ const user = claims ? Object.fromEntries(Object.entries(claims).filter(([, v]) => v !== void 0)) : void 0;
897
+ return {
898
+ appState: transactionData.appState,
899
+ authorizationDetails: tokenEndpointResponse.authorizationDetails,
900
+ idTokenClaims: claims,
901
+ user
902
+ };
903
+ }
792
904
  const existingStateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
793
905
  const stateData = applySessionExpiryAtLogin(
794
906
  updateStateData(transactionData.audience ?? "default", existingStateData, tokenEndpointResponse, {
@@ -797,7 +909,10 @@ var ServerClient = class {
797
909
  tokenEndpointResponse.claims
798
910
  );
799
911
  await this.#stateStore.set(this.#stateStoreIdentifier, stateData, true, storeOptions);
800
- return { appState: transactionData.appState, authorizationDetails: tokenEndpointResponse.authorizationDetails };
912
+ return {
913
+ appState: transactionData.appState,
914
+ authorizationDetails: tokenEndpointResponse.authorizationDetails
915
+ };
801
916
  }
802
917
  /**
803
918
  * Starts the user linking process, and returns a URL to redirect the user-agent to to request authorization at Auth0.
@@ -851,14 +966,15 @@ var ServerClient = class {
851
966
  * Takes an URL, extract the Authorization Code flow query parameters and requests a token.
852
967
  * @param url The URl from which the query params should be extracted to exchange for a token.
853
968
  * @param storeOptions Optional options used to pass to the Transaction and State Store.
969
+ * @param requestOptions Optional per-request options (signal, headers, customFetch). Applied to the code-for-token exchange.
854
970
  *
855
971
  * @throws {MissingTransactionError} When no transaction was found.
856
972
  * @throws {TokenByCodeError} If there was an issue requesting the access token.
857
973
  *
858
974
  * @returns A promise resolving to an object, containing the original appState (if present).
859
975
  */
860
- async completeLinkUser(url, storeOptions) {
861
- const result = await this.completeInteractiveLogin(url, storeOptions);
976
+ async completeLinkUser(url, storeOptions, requestOptions) {
977
+ const result = await this.completeInteractiveLogin(url, storeOptions, requestOptions);
862
978
  return {
863
979
  appState: result.appState
864
980
  };
@@ -914,43 +1030,44 @@ var ServerClient = class {
914
1030
  * Takes an URL, extract the Authorization Code flow query parameters and requests a token.
915
1031
  * @param url The URl from which the query params should be extracted to exchange for a token.
916
1032
  * @param storeOptions Optional options used to pass to the Transaction and State Store.
1033
+ * @param requestOptions Optional per-request options (signal, headers, customFetch). Applied to the code-for-token exchange.
917
1034
  *
918
1035
  * @throws {MissingTransactionError} When no transaction was found.
919
1036
  * @throws {TokenByCodeError} If there was an issue requesting the access token.
920
1037
  *
921
1038
  * @returns A promise resolving to an object, containing the original appState (if present).
922
1039
  */
923
- async completeUnlinkUser(url, storeOptions) {
924
- const result = await this.completeInteractiveLogin(url, storeOptions);
1040
+ async completeUnlinkUser(url, storeOptions, requestOptions) {
1041
+ const result = await this.completeInteractiveLogin(url, storeOptions, requestOptions);
925
1042
  return {
926
1043
  appState: result.appState
927
1044
  };
928
1045
  }
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) {
1046
+ async loginBackchannel(options, storeOptions, requestOptions) {
943
1047
  const scope = ensureOpenIdScope(options.authorizationParams?.scope ?? this.#options.authorizationParams?.scope);
944
1048
  const domain = await this.#resolveDomain(storeOptions);
945
1049
  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
- });
1050
+ let response;
1051
+ let tokenEndpointResponse;
1052
+ if (options.fullResponse) {
1053
+ const authJsResult = await authClient.backchannelAuthentication({
1054
+ bindingMessage: options.bindingMessage,
1055
+ loginHint: options.loginHint,
1056
+ authorizationParams: { ...options.authorizationParams, scope },
1057
+ fullResponse: true
1058
+ }, requestOptions);
1059
+ tokenEndpointResponse = authJsResult.data;
1060
+ response = authJsResult.response;
1061
+ } else {
1062
+ tokenEndpointResponse = await authClient.backchannelAuthentication({
1063
+ bindingMessage: options.bindingMessage,
1064
+ loginHint: options.loginHint,
1065
+ authorizationParams: {
1066
+ ...options.authorizationParams,
1067
+ scope
1068
+ }
1069
+ }, requestOptions);
1070
+ }
954
1071
  const existingStateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
955
1072
  const stateData = applySessionExpiryAtLogin(
956
1073
  updateStateData(this.#options.authorizationParams?.audience ?? "default", existingStateData, tokenEndpointResponse, {
@@ -959,9 +1076,16 @@ var ServerClient = class {
959
1076
  tokenEndpointResponse.claims
960
1077
  );
961
1078
  await this.#stateStore.set(this.#stateStoreIdentifier, stateData, true, storeOptions);
962
- return {
1079
+ const result = {
963
1080
  authorizationDetails: tokenEndpointResponse.authorizationDetails
964
1081
  };
1082
+ if (options.fullResponse) {
1083
+ if (!response) {
1084
+ throw new import_auth0_auth_js2.MissingCapturedResponseError();
1085
+ }
1086
+ return { data: result, response };
1087
+ }
1088
+ return result;
965
1089
  }
966
1090
  /**
967
1091
  * Starts a passwordless flow by sending a one-time code (OTP) or a magic link.
@@ -984,6 +1108,7 @@ var ServerClient = class {
984
1108
  *
985
1109
  * @param options Discriminated start options.
986
1110
  * @param storeOptions Optional options passed to the resolver / stores.
1111
+ * @param requestOptions Optional per-request options (signal, headers, customFetch). Applied to the `/passwordless/start` request.
987
1112
  *
988
1113
  * @throws {PasswordlessStartError} If the request fails, or if a magic link is requested without a `redirectUri`.
989
1114
  *
@@ -1000,43 +1125,52 @@ var ServerClient = class {
1000
1125
  * redirectUri: 'https://app.example.com/auth/callback',
1001
1126
  * });
1002
1127
  */
1003
- async startPasswordless(options, storeOptions) {
1128
+ async startPasswordless(options, storeOptions, requestOptions) {
1004
1129
  const domain = await this.#resolveDomain(storeOptions);
1005
1130
  const authClient = this.#getAuthClient(domain);
1006
1131
  if (options.connection === "sms") {
1007
- await authClient.passwordless.sendSms({
1008
- phoneNumber: options.phoneNumber,
1009
- language: options.language
1010
- });
1132
+ await authClient.passwordless.sendSms(
1133
+ {
1134
+ phoneNumber: options.phoneNumber,
1135
+ language: options.language
1136
+ },
1137
+ requestOptions
1138
+ );
1011
1139
  return;
1012
1140
  }
1013
1141
  if (options.send !== "link") {
1014
- await authClient.passwordless.sendEmail({
1015
- email: options.email,
1016
- send: "code",
1017
- language: options.language
1018
- });
1142
+ await authClient.passwordless.sendEmail(
1143
+ {
1144
+ email: options.email,
1145
+ send: "code",
1146
+ language: options.language
1147
+ },
1148
+ requestOptions
1149
+ );
1019
1150
  return;
1020
1151
  }
1021
1152
  if (!options.redirectUri || typeof options.redirectUri !== "string") {
1022
- throw new import_auth0_auth_js.PasswordlessStartError("redirectUri is required to start a passwordless magic-link login.");
1153
+ throw new import_auth0_auth_js2.PasswordlessStartError("redirectUri is required to start a passwordless magic-link login.");
1023
1154
  }
1024
1155
  const state = crypto.randomUUID();
1025
1156
  const scope = ensureOpenIdScope(options.scope ?? this.#options.authorizationParams?.scope);
1026
1157
  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
- });
1158
+ await authClient.passwordless.sendEmail(
1159
+ {
1160
+ email: options.email,
1161
+ send: "link",
1162
+ language: options.language,
1163
+ authParams: {
1164
+ ...options.authParams,
1165
+ redirect_uri: options.redirectUri,
1166
+ response_type: "code",
1167
+ scope,
1168
+ ...audience ? { audience } : {},
1169
+ state
1170
+ }
1171
+ },
1172
+ requestOptions
1173
+ );
1040
1174
  const transactionState = {
1041
1175
  audience,
1042
1176
  domain,
@@ -1044,42 +1178,42 @@ var ServerClient = class {
1044
1178
  };
1045
1179
  await this.#transactionStore.set(this.#transactionStoreIdentifier, transactionState, false, storeOptions);
1046
1180
  }
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) {
1181
+ async completePasswordless(options, storeOptions, requestOptions) {
1068
1182
  const scope = ensureOpenIdScope(options.authorizationParams?.scope ?? this.#options.authorizationParams?.scope);
1069
1183
  const audience = options.authorizationParams?.audience ?? this.#options.authorizationParams?.audience;
1070
1184
  const domain = await this.#resolveDomain(storeOptions);
1071
1185
  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
- });
1186
+ let response;
1187
+ let tokenEndpointResponse;
1188
+ if (options.fullResponse) {
1189
+ const authJsResult = options.connection === "sms" ? await authClient.getTokenByPasswordlessSms({
1190
+ phoneNumber: options.phoneNumber,
1191
+ code: options.verificationCode,
1192
+ audience,
1193
+ scope,
1194
+ fullResponse: true
1195
+ }, requestOptions) : await authClient.getTokenByPasswordlessEmail({
1196
+ email: options.email,
1197
+ code: options.verificationCode,
1198
+ audience,
1199
+ scope,
1200
+ fullResponse: true
1201
+ }, requestOptions);
1202
+ tokenEndpointResponse = authJsResult.data;
1203
+ response = authJsResult.response;
1204
+ } else {
1205
+ tokenEndpointResponse = options.connection === "sms" ? await authClient.getTokenByPasswordlessSms({
1206
+ phoneNumber: options.phoneNumber,
1207
+ code: options.verificationCode,
1208
+ audience,
1209
+ scope
1210
+ }, requestOptions) : await authClient.getTokenByPasswordlessEmail({
1211
+ email: options.email,
1212
+ code: options.verificationCode,
1213
+ audience,
1214
+ scope
1215
+ }, requestOptions);
1216
+ }
1083
1217
  const existingStateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
1084
1218
  const stateData = updateStateData(
1085
1219
  this.#options.authorizationParams?.audience ?? "default",
@@ -1088,9 +1222,16 @@ var ServerClient = class {
1088
1222
  { domain }
1089
1223
  );
1090
1224
  await this.#stateStore.set(this.#stateStoreIdentifier, stateData, true, storeOptions);
1091
- return {
1225
+ const result = {
1092
1226
  authorizationDetails: tokenEndpointResponse.authorizationDetails
1093
1227
  };
1228
+ if (options.fullResponse) {
1229
+ if (!response) {
1230
+ throw new import_auth0_auth_js2.MissingCapturedResponseError();
1231
+ }
1232
+ return { data: result, response };
1233
+ }
1234
+ return result;
1094
1235
  }
1095
1236
  /**
1096
1237
  * Completes a passwordless magic-link login and persists the resulting session.
@@ -1102,6 +1243,7 @@ var ServerClient = class {
1102
1243
  *
1103
1244
  * @param url The callback URL containing the authorization `code` and `state`.
1104
1245
  * @param storeOptions Optional options passed to the resolver / stores.
1246
+ * @param requestOptions Optional per-request options (signal, headers, customFetch). Applied to the code exchange.
1105
1247
  *
1106
1248
  * @throws {MissingTransactionError} If no magic-link transaction was found.
1107
1249
  * @throws {PasswordlessVerifyError} If the returned `state` is missing or does not match.
@@ -1112,7 +1254,7 @@ var ServerClient = class {
1112
1254
  * @example
1113
1255
  * const result = await serverClient.completePasswordlessMagicLink(callbackUrl, storeOptions);
1114
1256
  */
1115
- async completePasswordlessMagicLink(url, storeOptions) {
1257
+ async completePasswordlessMagicLink(url, storeOptions, requestOptions) {
1116
1258
  const transactionData = await this.#transactionStore.get(this.#transactionStoreIdentifier, storeOptions);
1117
1259
  if (!transactionData) {
1118
1260
  throw new MissingTransactionError();
@@ -1120,11 +1262,11 @@ var ServerClient = class {
1120
1262
  const expectedState = typeof transactionData.state === "string" ? transactionData.state : void 0;
1121
1263
  const returnedState = url.searchParams.get("state");
1122
1264
  if (!returnedState || !expectedState || returnedState !== expectedState) {
1123
- throw new import_auth0_auth_js.PasswordlessVerifyError("State mismatch on magic-link callback");
1265
+ throw new import_auth0_auth_js2.PasswordlessVerifyError("State mismatch on magic-link callback");
1124
1266
  }
1125
1267
  const domain = transactionData.domain ?? await this.#resolveDomain(storeOptions);
1126
1268
  const authClient = this.#getAuthClient(domain);
1127
- const tokenEndpointResponse = await authClient.getTokenByMagicLinkCode(url, { expectedState });
1269
+ const tokenEndpointResponse = await authClient.getTokenByMagicLinkCode(url, { expectedState }, requestOptions);
1128
1270
  const existingStateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
1129
1271
  const stateData = updateStateData(transactionData.audience ?? "default", existingStateData, tokenEndpointResponse, {
1130
1272
  domain
@@ -1137,6 +1279,12 @@ var ServerClient = class {
1137
1279
  }
1138
1280
  /**
1139
1281
  * Retrieves the user from the store, or undefined if no user found.
1282
+ *
1283
+ * This does not accept `RequestOptions`. It is a pure read from the state store and makes no
1284
+ * network call, so a per-request `signal`/`headers`/`customFetch` could not take effect. The
1285
+ * exclusion is deliberate: a parameter that can never do anything costs the public surface more
1286
+ * than the asymmetry with `getAccessToken`/`getAccessTokenForConnection`/`revokeRefreshToken` does.
1287
+ *
1140
1288
  * @param storeOptions Optional options used to pass to the Transaction and State Store.
1141
1289
  * @returns The user, or undefined if no user found in the store.
1142
1290
  */
@@ -1179,6 +1327,34 @@ var ServerClient = class {
1179
1327
  return sessionData;
1180
1328
  }
1181
1329
  }
1330
+ /**
1331
+ * Retrieves the OIDC UserInfo claims for a given access token.
1332
+ *
1333
+ * The access token must be supplied explicitly by the caller. This method does NOT read
1334
+ * the token from the session and does NOT trigger a refresh. The token must be accepted by
1335
+ * the `/userinfo` endpoint:
1336
+ * - Without Multi-Resource Refresh Tokens (MRRT): pass a default OIDC access token, one
1337
+ * obtained without an explicit `audience` parameter.
1338
+ * - With MRRT: tokens are audience-bound, so request the userinfo endpoint as the audience
1339
+ * (e.g. `https://<domain>/userinfo`) when obtaining the token. A token bound to a
1340
+ * different resource-server audience is rejected by `/userinfo`.
1341
+ *
1342
+ * `/userinfo` is a bearer-protected resource and requires no client authentication, so this
1343
+ * works for public clients: the supplied access token is the only credential used.
1344
+ *
1345
+ * @param options Options containing the access token and an optional expected subject
1346
+ * for OIDC subject-consistency validation.
1347
+ * @param storeOptions Optional store options, used to resolve the domain in resolver mode.
1348
+ * @param requestOptions Optional per-request options (signal, headers, customFetch) forwarded
1349
+ * to the underlying `/userinfo` request.
1350
+ * @throws {UserInfoError} When the `/userinfo` request fails or the subject check fails.
1351
+ * @returns A Promise resolving to the UserInfo claims.
1352
+ */
1353
+ async getUserInfo(options, storeOptions, requestOptions) {
1354
+ const domain = await this.#resolveDomain(storeOptions);
1355
+ const authClient = this.#getAuthClient(domain);
1356
+ return authClient.getUserInfo(options, requestOptions);
1357
+ }
1182
1358
  /**
1183
1359
  * 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
1360
  * Also updates the store when a new token was retrieved from Auth0.
@@ -1187,19 +1363,30 @@ var ServerClient = class {
1187
1363
  * request an access token for that audience/scope (Multi-Resource Refresh Tokens). Tokens are cached per
1188
1364
  * audience and scope combination.
1189
1365
  *
1190
- * @param options Optional options for requesting a specific audience/scope.
1366
+ * When `options.fullResponse` is `true`, the method returns an {@link ApiResponse} envelope containing both
1367
+ * the token set and the raw {@link Response} from the token endpoint. The cache is bypassed in this case,
1368
+ * forcing a refresh-token call even when a valid cached token exists, because the `Response` can only be
1369
+ * produced by a live HTTP call.
1370
+ *
1371
+ * @param options Optional options for requesting a specific audience/scope or enabling full response.
1191
1372
  * @param storeOptions Optional options used to pass to the Transaction and State Store.
1373
+ * @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.
1374
+ *
1375
+ * @remarks
1376
+ * Legacy single-argument form: `getAccessToken(storeOptions?)`. If your `TStoreOptions` type
1377
+ * contains `audience` or `scope` keys, use the explicit two-argument form instead:
1378
+ * `getAccessToken({}, storeOptions)` to avoid call-site routing ambiguity.
1192
1379
  *
1193
1380
  * @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
1381
  * @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
1382
  *
1196
- * @returns The Token Set, containing the access token, as well as additional information.
1383
+ * @returns The Token Set when `fullResponse` is omitted, or an {@link ApiResponse} envelope when `fullResponse: true`.
1197
1384
  */
1198
- async getAccessToken(tokenOptionsOrStoreOptions, storeOptions) {
1385
+ async getAccessToken(tokenOptionsOrStoreOptions, storeOptions, requestOptions) {
1199
1386
  const hasTokenOptions = (
1200
1387
  // 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)
1388
+ storeOptions !== void 0 || // OR if first arg has audience, scope, or fullResponse properties
1389
+ !!tokenOptionsOrStoreOptions && typeof tokenOptionsOrStoreOptions === "object" && ("audience" in tokenOptionsOrStoreOptions || "scope" in tokenOptionsOrStoreOptions || "fullResponse" in tokenOptionsOrStoreOptions)
1203
1390
  );
1204
1391
  const [resolvedOptions, resolvedStoreOptions] = hasTokenOptions ? [tokenOptionsOrStoreOptions, storeOptions] : [void 0, tokenOptionsOrStoreOptions];
1205
1392
  const stateData = await this.#stateStore.get(this.#stateStoreIdentifier, resolvedStoreOptions);
@@ -1227,10 +1414,12 @@ var ServerClient = class {
1227
1414
  (tokenSet2) => tokenSet2.audience === audience && (!scope || compareScopes(tokenSet2.scope, scope))
1228
1415
  );
1229
1416
  if (tokenSet && tokenSet.expiresAt > Date.now() / 1e3) {
1230
- return tokenSet;
1417
+ if (!resolvedOptions?.fullResponse) {
1418
+ return tokenSet;
1419
+ }
1231
1420
  }
1232
1421
  if (!stateData?.refreshToken) {
1233
- throw new import_auth0_auth_js.TokenByRefreshTokenError(
1422
+ throw new import_auth0_auth_js2.TokenByRefreshTokenError(
1234
1423
  "The access token has expired and a refresh token was not provided. The user needs to re-authenticate."
1235
1424
  );
1236
1425
  }
@@ -1244,35 +1433,38 @@ var ServerClient = class {
1244
1433
  ...scope && { scope }
1245
1434
  }
1246
1435
  };
1247
- const tokenEndpointResponse = await this.#getAuthClient(domainForSession).getTokenByRefreshToken(tokenByRefreshTokenOptions);
1436
+ let response;
1437
+ let tokenEndpointResponse;
1438
+ if (resolvedOptions?.fullResponse) {
1439
+ const authJsResult = await this.#getAuthClient(domainForSession).getTokenByRefreshToken({
1440
+ ...tokenByRefreshTokenOptions,
1441
+ fullResponse: true
1442
+ }, requestOptions);
1443
+ tokenEndpointResponse = authJsResult.data;
1444
+ response = authJsResult.response;
1445
+ } else {
1446
+ tokenEndpointResponse = await this.#getAuthClient(domainForSession).getTokenByRefreshToken(tokenByRefreshTokenOptions, requestOptions);
1447
+ }
1248
1448
  const existingStateData = await this.#stateStore.get(this.#stateStoreIdentifier, resolvedStoreOptions);
1249
1449
  const updatedStateData = updateStateData(audience, existingStateData, tokenEndpointResponse, {
1250
1450
  domain: domainForSession
1251
1451
  });
1252
1452
  await this.#stateStore.set(this.#stateStoreIdentifier, updatedStateData, false, resolvedStoreOptions);
1253
- return {
1453
+ const returnTokenSet = {
1254
1454
  accessToken: tokenEndpointResponse.accessToken,
1255
1455
  scope: tokenEndpointResponse.scope,
1256
1456
  expiresAt: tokenEndpointResponse.expiresAt,
1257
1457
  audience
1258
1458
  };
1459
+ if (resolvedOptions?.fullResponse) {
1460
+ if (!response) {
1461
+ throw new import_auth0_auth_js2.MissingCapturedResponseError();
1462
+ }
1463
+ return { data: returnTokenSet, response };
1464
+ }
1465
+ return returnTokenSet;
1259
1466
  }
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) {
1467
+ async getAccessTokenForConnection(options, storeOptions, requestOptions) {
1276
1468
  const stateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
1277
1469
  const sessionDomain = stateData ? this.#getSessionDomain(stateData) : this.#staticDomain;
1278
1470
  if (this.#isResolverMode()) {
@@ -1291,19 +1483,34 @@ var ServerClient = class {
1291
1483
  (tokenSet) => tokenSet.connection === options.connection
1292
1484
  );
1293
1485
  if (connectionTokenSet && connectionTokenSet.expiresAt > Date.now() / 1e3) {
1294
- return connectionTokenSet;
1486
+ if (!options.fullResponse) {
1487
+ return connectionTokenSet;
1488
+ }
1295
1489
  }
1296
1490
  if (!stateData?.refreshToken) {
1297
- throw new import_auth0_auth_js.TokenForConnectionError(
1491
+ throw new import_auth0_auth_js2.TokenForConnectionError(
1298
1492
  "A refresh token was not found but is required to be able to retrieve an access token for a connection."
1299
1493
  );
1300
1494
  }
1301
1495
  const domainForSession = sessionDomain;
1302
- const tokenEndpointResponse = await this.#getAuthClient(domainForSession).getTokenForConnection({
1303
- connection: options.connection,
1304
- loginHint: options.loginHint,
1305
- refreshToken: stateData.refreshToken
1306
- });
1496
+ let response;
1497
+ let tokenEndpointResponse;
1498
+ if (options.fullResponse) {
1499
+ const authJsResult = await this.#getAuthClient(domainForSession).getTokenForConnection({
1500
+ connection: options.connection,
1501
+ loginHint: options.loginHint,
1502
+ refreshToken: stateData.refreshToken,
1503
+ fullResponse: true
1504
+ }, requestOptions);
1505
+ tokenEndpointResponse = authJsResult.data;
1506
+ response = authJsResult.response;
1507
+ } else {
1508
+ tokenEndpointResponse = await this.#getAuthClient(domainForSession).getTokenForConnection({
1509
+ connection: options.connection,
1510
+ loginHint: options.loginHint,
1511
+ refreshToken: stateData.refreshToken
1512
+ }, requestOptions);
1513
+ }
1307
1514
  const updatedStateData = updateStateDataForConnectionTokenSet(
1308
1515
  options,
1309
1516
  {
@@ -1313,13 +1520,20 @@ var ServerClient = class {
1313
1520
  tokenEndpointResponse
1314
1521
  );
1315
1522
  await this.#stateStore.set(this.#stateStoreIdentifier, updatedStateData, false, storeOptions);
1316
- return {
1523
+ const returnConnectionTokenSet = {
1317
1524
  accessToken: tokenEndpointResponse.accessToken,
1318
1525
  scope: tokenEndpointResponse.scope,
1319
1526
  expiresAt: tokenEndpointResponse.expiresAt,
1320
1527
  connection: options.connection,
1321
1528
  loginHint: options.loginHint
1322
1529
  };
1530
+ if (options.fullResponse) {
1531
+ if (!response) {
1532
+ throw new import_auth0_auth_js2.MissingCapturedResponseError();
1533
+ }
1534
+ return { data: returnConnectionTokenSet, response };
1535
+ }
1536
+ return returnConnectionTokenSet;
1323
1537
  }
1324
1538
  /**
1325
1539
  * Revokes the refresh token stored in the current session, or an explicitly supplied token.
@@ -1331,12 +1545,13 @@ var ServerClient = class {
1331
1545
  *
1332
1546
  * @param options Optionally supply a token to revoke instead of reading from the session.
1333
1547
  * @param storeOptions Optional options passed to the StateStore.
1548
+ * @param requestOptions Optional per-request options (signal, headers, customFetch). Applied to the revocation request.
1334
1549
  *
1335
1550
  * @throws {MissingRequiredArgumentError} If `options.token` is an empty string.
1336
1551
  * @throws {MissingSessionError} If no refresh token is found in the session and none was provided.
1337
1552
  * @throws {TokenRevocationError} If the revocation request fails.
1338
1553
  */
1339
- async revokeRefreshToken(options = {}, storeOptions) {
1554
+ async revokeRefreshToken(options = {}, storeOptions, requestOptions) {
1340
1555
  if (options.token !== void 0 && options.token.length === 0) {
1341
1556
  throw new MissingRequiredArgumentError("options.token must not be an empty string.");
1342
1557
  }
@@ -1360,18 +1575,27 @@ var ServerClient = class {
1360
1575
  } else {
1361
1576
  authClient = this.authClient;
1362
1577
  }
1363
- await authClient.revokeToken({ token: refreshToken, tokenTypeHint: "refresh_token" });
1578
+ await authClient.revokeToken({ token: refreshToken, tokenTypeHint: "refresh_token" }, requestOptions);
1364
1579
  }
1365
1580
  /**
1366
1581
  * Logs the user out and returns a URL to redirect the user-agent to after they log out.
1367
1582
  * @param options Options used to configure the logout process.
1368
1583
  * @param storeOptions Optional options used to pass to the Transaction and State Store.
1584
+ * @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
1585
  * @returns {URL}
1370
1586
  */
1371
- async logout(options, storeOptions) {
1587
+ async logout(options, storeOptions, requestOptions) {
1588
+ if (this.#enterpriseConnect) {
1589
+ if (options.federated === false) {
1590
+ console.warn(
1591
+ "[Auth0] Enterprise Connect: logout() called with federated=false. The enterprise IdP session will remain active; the user may silently re-authenticate on the next login."
1592
+ );
1593
+ }
1594
+ return this.authClient.buildLogoutUrl({ returnTo: options.returnTo, federated: options.federated ?? true });
1595
+ }
1372
1596
  if (!this.#isResolverMode()) {
1373
1597
  try {
1374
- await this.revokeRefreshToken({}, storeOptions);
1598
+ await this.revokeRefreshToken({}, storeOptions, requestOptions);
1375
1599
  } catch {
1376
1600
  }
1377
1601
  await this.#stateStore.delete(this.#stateStoreIdentifier, storeOptions);
@@ -1387,39 +1611,33 @@ var ServerClient = class {
1387
1611
  const domainMatches = sessionDomain === resolvedDomain;
1388
1612
  if (domainMatches) {
1389
1613
  try {
1390
- await this.revokeRefreshToken({}, storeOptions);
1614
+ await this.revokeRefreshToken({}, storeOptions, requestOptions);
1391
1615
  } catch {
1392
1616
  }
1393
1617
  await this.#stateStore.delete(this.#stateStoreIdentifier, storeOptions);
1394
1618
  }
1395
1619
  return authClient.buildLogoutUrl(options);
1396
1620
  }
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) {
1621
+ async loginWithCustomTokenExchange(options, storeOptions, requestOptions) {
1417
1622
  const domain = await this.#resolveDomain(storeOptions);
1418
1623
  const authClient = this.#getAuthClient(domain);
1419
- const tokenEndpointResponse = await authClient.exchangeToken({
1420
- ...options,
1421
- scope: ensureOpenIdScope(options.scope)
1422
- });
1624
+ let response;
1625
+ let tokenEndpointResponse;
1626
+ if (options.fullResponse) {
1627
+ const { fullResponse: _, ...rest } = options;
1628
+ const authJsResult = await authClient.exchangeToken({
1629
+ ...rest,
1630
+ scope: ensureOpenIdScope(options.scope),
1631
+ fullResponse: true
1632
+ }, requestOptions);
1633
+ tokenEndpointResponse = authJsResult.data;
1634
+ response = authJsResult.response;
1635
+ } else {
1636
+ tokenEndpointResponse = await authClient.exchangeToken({
1637
+ ...options,
1638
+ scope: ensureOpenIdScope(options.scope)
1639
+ }, requestOptions);
1640
+ }
1423
1641
  const existingStateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
1424
1642
  const stateData = updateStateData(
1425
1643
  this.#options.authorizationParams?.audience ?? "default",
@@ -1428,30 +1646,25 @@ var ServerClient = class {
1428
1646
  { domain }
1429
1647
  );
1430
1648
  await this.#stateStore.set(this.#stateStoreIdentifier, stateData, true, storeOptions);
1431
- return { authorizationDetails: tokenEndpointResponse.authorizationDetails };
1649
+ const result = {
1650
+ authorizationDetails: tokenEndpointResponse.authorizationDetails
1651
+ };
1652
+ if (options.fullResponse) {
1653
+ if (!response) {
1654
+ throw new import_auth0_auth_js2.MissingCapturedResponseError();
1655
+ }
1656
+ return { data: result, response };
1657
+ }
1658
+ return result;
1432
1659
  }
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) {
1660
+ async customTokenExchange(options, storeOptions, requestOptions) {
1452
1661
  const domain = await this.#resolveDomain(storeOptions);
1453
1662
  const authClient = this.#getAuthClient(domain);
1454
- return authClient.exchangeToken(options);
1663
+ if (options.fullResponse) {
1664
+ const { fullResponse: _, ...rest } = options;
1665
+ return authClient.exchangeToken({ ...rest, fullResponse: true }, requestOptions);
1666
+ }
1667
+ return authClient.exchangeToken(options, requestOptions);
1455
1668
  }
1456
1669
  /**
1457
1670
  * Requests a Session Transfer Token (STT) for impersonation via session transfer (RFC 8693).
@@ -1475,8 +1688,17 @@ var ServerClient = class {
1475
1688
  * {@link ServerClient.buildSessionTransferRedirect}, which is forwarded to the target's
1476
1689
  * `/authorize` on the redirect.
1477
1690
  *
1691
+ * @remarks
1692
+ * If the actor's ID token has expired, an internal refresh is performed before the
1693
+ * session transfer token exchange. This refresh call is NOT guarded by the caller's
1694
+ * requestOptions.signal — if the signal fires during this step, the abort is ignored.
1695
+ * Only the final exchangeToken call respects the signal.
1696
+ * Thread requestOptions into #resolveSessionTransferActor in a future minor if
1697
+ * callers need full-request abort coverage.
1698
+ *
1478
1699
  * @param options Options including the developer-supplied `subjectToken`/`subjectTokenType` and an optional explicit `actor`.
1479
1700
  * @param storeOptions Optional options used to read the agent session (for the actor) and resolve the request domain.
1701
+ * @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
1702
  *
1481
1703
  * @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
1704
  * @throws {MissingClientAuthError} When client credentials are not configured (STT requires a confidential client).
@@ -1485,7 +1707,7 @@ var ServerClient = class {
1485
1707
  *
1486
1708
  * @returns A promise resolving to a {@link SessionTransferTokenResult} containing the STT and its metadata.
1487
1709
  */
1488
- async requestSessionTransferToken(options, storeOptions) {
1710
+ async requestSessionTransferToken(options, storeOptions, requestOptions) {
1489
1711
  if (!options.subjectToken || !options.subjectToken.trim()) {
1490
1712
  throw new MissingRequiredArgumentError("subjectToken");
1491
1713
  }
@@ -1493,7 +1715,7 @@ var ServerClient = class {
1493
1715
  throw new MissingRequiredArgumentError("subjectTokenType");
1494
1716
  }
1495
1717
  if (options.organization !== void 0 && !options.organization.trim()) {
1496
- throw new import_auth0_auth_js.OrganizationValidationError("organization must not be blank");
1718
+ throw new import_auth0_auth_js2.OrganizationValidationError("organization must not be blank");
1497
1719
  }
1498
1720
  const domain = await this.#resolveDomain(storeOptions);
1499
1721
  const actor = await this.#resolveSessionTransferActor(options.actor, domain, storeOptions);
@@ -1511,7 +1733,7 @@ var ServerClient = class {
1511
1733
  // `/authorize`; neither implies the other.
1512
1734
  organization: options.organization,
1513
1735
  extra: options.extra
1514
- });
1736
+ }, requestOptions);
1515
1737
  return {
1516
1738
  sessionTransferToken: response.accessToken,
1517
1739
  // Surface exactly what the server returned — never fabricate the URN, so a non-STT
@@ -1567,7 +1789,7 @@ var ServerClient = class {
1567
1789
  url.searchParams.set("session_transfer_token", result.sessionTransferToken);
1568
1790
  if (options?.organization !== void 0) {
1569
1791
  if (!options.organization.trim()) {
1570
- throw new import_auth0_auth_js.OrganizationValidationError("organization must not be blank");
1792
+ throw new import_auth0_auth_js2.OrganizationValidationError("organization must not be blank");
1571
1793
  }
1572
1794
  url.searchParams.set("organization", options.organization);
1573
1795
  }
@@ -1635,6 +1857,11 @@ var ServerClient = class {
1635
1857
  }
1636
1858
  /**
1637
1859
  * Handles the backchannel logout process by verifying the logout token and deleting the session from the store if the logout token was considered valid.
1860
+ *
1861
+ * This does not accept `RequestOptions`. Verification does fetch JWKS, but the auth-js method it
1862
+ * delegates to, `verifyLogoutToken`, takes no `requestOptions`, so there is nothing to forward.
1863
+ * That fetch always uses the client's configured `customFetch`.
1864
+ *
1638
1865
  * @param logoutToken The logout token to verify and use to delete the session from the store.
1639
1866
  * @param storeOptions Optional options used to pass to the Transaction and State Store.
1640
1867
  *
@@ -1787,7 +2014,7 @@ var AbstractTransactionStore = class extends AbstractStore {
1787
2014
  };
1788
2015
 
1789
2016
  // src/index.ts
1790
- var import_auth0_auth_js5 = require("@auth0/auth0-auth-js");
2017
+ var import_auth0_auth_js6 = require("@auth0/auth0-auth-js");
1791
2018
 
1792
2019
  // src/store/cookie-transaction-store.ts
1793
2020
  var CookieTransactionStore = class extends AbstractTransactionStore {
@@ -1984,13 +2211,13 @@ var StatelessStateStore = class extends AbstractSessionStore {
1984
2211
  };
1985
2212
 
1986
2213
  // src/mfa/index.ts
1987
- var import_auth0_auth_js2 = require("@auth0/auth0-auth-js");
2214
+ var import_auth0_auth_js3 = require("@auth0/auth0-auth-js");
1988
2215
 
1989
2216
  // src/passkey/index.ts
1990
- var import_auth0_auth_js3 = require("@auth0/auth0-auth-js");
2217
+ var import_auth0_auth_js4 = require("@auth0/auth0-auth-js");
1991
2218
 
1992
2219
  // src/database/index.ts
1993
- var import_auth0_auth_js4 = require("@auth0/auth0-auth-js");
2220
+ var import_auth0_auth_js5 = require("@auth0/auth0-auth-js");
1994
2221
  // Annotate the CommonJS export names for ESM import in node:
1995
2222
  0 && (module.exports = {
1996
2223
  AbstractStateStore,
@@ -1998,6 +2225,7 @@ var import_auth0_auth_js4 = require("@auth0/auth0-auth-js");
1998
2225
  BackchannelLogoutError,
1999
2226
  ChangePasswordError,
2000
2227
  CookieTransactionStore,
2228
+ EnterpriseConnectNotSupportedError,
2001
2229
  InvalidConfigurationError,
2002
2230
  IssuerValidationError,
2003
2231
  MfaChallengeError,
@@ -2026,6 +2254,8 @@ var import_auth0_auth_js4 = require("@auth0/auth0-auth-js");
2026
2254
  TokenExchangeError,
2027
2255
  TokenExchangeErrorCode,
2028
2256
  TokenRevocationError,
2257
+ UserInfoError,
2258
+ isFederatedDomain,
2029
2259
  isMfaRequiredError
2030
2260
  });
2031
2261
  //# sourceMappingURL=index.cjs.map