@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/README.md +1 -1
- package/dist/index.cjs +454 -224
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +150 -27
- package/dist/index.d.ts +150 -27
- package/dist/index.js +426 -194
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
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: () =>
|
|
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: () =>
|
|
31
|
-
MfaEnrollmentError: () =>
|
|
32
|
-
MfaListAuthenticatorsError: () =>
|
|
33
|
-
MfaVerifyError: () =>
|
|
34
|
-
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: () =>
|
|
39
|
-
PasskeyChallengeError: () =>
|
|
40
|
-
PasskeyGetTokenError: () =>
|
|
41
|
-
PasskeyRegisterError: () =>
|
|
42
|
-
PasswordlessStartError: () =>
|
|
43
|
-
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: () =>
|
|
50
|
+
SignUpError: () => import_auth0_auth_js5.SignUpError,
|
|
50
51
|
StartLinkUserError: () => StartLinkUserError,
|
|
51
52
|
StatefulStateStore: () => StatefulStateStore,
|
|
52
53
|
StatelessStateStore: () => StatelessStateStore,
|
|
53
|
-
TokenExchangeError: () =>
|
|
54
|
+
TokenExchangeError: () => import_auth0_auth_js6.TokenExchangeError,
|
|
54
55
|
TokenExchangeErrorCode: () => TokenExchangeErrorCode,
|
|
55
|
-
TokenRevocationError: () =>
|
|
56
|
-
|
|
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
|
|
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.
|
|
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
|
|
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.#
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 {
|
|
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
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1009
|
-
|
|
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
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
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
|
|
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
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
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
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
*
|
|
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
|
|
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
|
|
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
|
-
|
|
1417
|
+
if (!resolvedOptions?.fullResponse) {
|
|
1418
|
+
return tokenSet;
|
|
1419
|
+
}
|
|
1231
1420
|
}
|
|
1232
1421
|
if (!stateData?.refreshToken) {
|
|
1233
|
-
throw new
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1486
|
+
if (!options.fullResponse) {
|
|
1487
|
+
return connectionTokenSet;
|
|
1488
|
+
}
|
|
1295
1489
|
}
|
|
1296
1490
|
if (!stateData?.refreshToken) {
|
|
1297
|
-
throw new
|
|
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
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
2214
|
+
var import_auth0_auth_js3 = require("@auth0/auth0-auth-js");
|
|
1988
2215
|
|
|
1989
2216
|
// src/passkey/index.ts
|
|
1990
|
-
var
|
|
2217
|
+
var import_auth0_auth_js4 = require("@auth0/auth0-auth-js");
|
|
1991
2218
|
|
|
1992
2219
|
// src/database/index.ts
|
|
1993
|
-
var
|
|
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
|