@auth0/auth0-server-js 1.3.0 → 1.5.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.js CHANGED
@@ -41,6 +41,13 @@ var InvalidConfigurationError = class extends Error {
41
41
  this.name = "InvalidConfigurationError";
42
42
  }
43
43
  };
44
+ var IssuerValidationError = class extends Error {
45
+ code = "issuer_validation_error";
46
+ constructor(message) {
47
+ super(message);
48
+ this.name = "IssuerValidationError";
49
+ }
50
+ };
44
51
 
45
52
  // src/state/utils.ts
46
53
  var createUpdatedTokenSet = (audience, response) => ({
@@ -49,7 +56,18 @@ var createUpdatedTokenSet = (audience, response) => ({
49
56
  scope: response.scope,
50
57
  expiresAt: response.expiresAt
51
58
  });
52
- function updateStateData(audience, stateData, tokenEndpointResponse) {
59
+ function updateStateData(audience, stateData, tokenEndpointResponse, context) {
60
+ if (stateData && tokenEndpointResponse.claims) {
61
+ const newSub = tokenEndpointResponse.claims.sub;
62
+ const newIss = tokenEndpointResponse.claims.iss;
63
+ const existingSub = stateData.user?.sub;
64
+ const existingIss = stateData.user?.iss;
65
+ const subMismatch = newSub !== void 0 && existingSub !== void 0 && newSub !== existingSub;
66
+ const issMismatch = newIss !== void 0 && existingIss !== void 0 && newIss !== existingIss;
67
+ if (subMismatch || issMismatch) {
68
+ stateData = void 0;
69
+ }
70
+ }
53
71
  if (stateData) {
54
72
  const isNewTokenSet = !stateData.tokenSets.some(
55
73
  (tokenSet) => tokenSet.audience === audience && tokenSet.scope === tokenEndpointResponse.scope
@@ -61,7 +79,8 @@ function updateStateData(audience, stateData, tokenEndpointResponse) {
61
79
  ...stateData,
62
80
  idToken: tokenEndpointResponse.idToken ?? stateData.idToken,
63
81
  refreshToken: tokenEndpointResponse.refreshToken ?? stateData.refreshToken,
64
- tokenSets
82
+ tokenSets,
83
+ domain: context?.domain ?? stateData.domain
65
84
  };
66
85
  } else {
67
86
  const user = tokenEndpointResponse.claims;
@@ -69,9 +88,8 @@ function updateStateData(audience, stateData, tokenEndpointResponse) {
69
88
  user,
70
89
  idToken: tokenEndpointResponse.idToken,
71
90
  refreshToken: tokenEndpointResponse.refreshToken,
72
- tokenSets: [
73
- createUpdatedTokenSet(audience, tokenEndpointResponse)
74
- ],
91
+ tokenSets: [createUpdatedTokenSet(audience, tokenEndpointResponse)],
92
+ domain: context?.domain,
75
93
  internal: {
76
94
  sid: user?.sid,
77
95
  createdAt: Math.floor(Date.now() / 1e3)
@@ -120,6 +138,9 @@ var compareScopes = (scopes, requiredScopes) => {
120
138
  return requiredScopesArray.every((scope) => scopesSet.has(scope));
121
139
  };
122
140
 
141
+ // src/server-client.ts
142
+ import { decodeJwt } from "jose";
143
+
123
144
  // src/telemetry.ts
124
145
  function getTelemetryConfig(config) {
125
146
  if (config?.enabled === false) {
@@ -128,13 +149,106 @@ function getTelemetryConfig(config) {
128
149
  return {
129
150
  enabled: true,
130
151
  name: config?.name ?? "@auth0/auth0-server-js",
131
- version: config?.version ?? "1.3.0"
152
+ version: config?.version ?? "1.5.0"
132
153
  };
133
154
  }
134
155
 
156
+ // src/mfa/server-mfa-client.ts
157
+ var ServerMfaClient = class {
158
+ #options;
159
+ /**
160
+ * @internal
161
+ */
162
+ constructor(options) {
163
+ this.#options = options;
164
+ }
165
+ /**
166
+ * Lists all MFA authenticators enrolled by the user.
167
+ *
168
+ * @param options - Options for listing authenticators
169
+ * @returns Promise resolving to an array of enrolled authenticators
170
+ * @throws {MfaListAuthenticatorsError} When the request fails
171
+ */
172
+ async listAuthenticators(options) {
173
+ return this.#options.authClient.mfa.listAuthenticators(options);
174
+ }
175
+ /**
176
+ * Enrolls a new MFA authenticator for the user.
177
+ *
178
+ * @param options - Enrollment options
179
+ * @returns Promise resolving to enrollment response with authenticator details
180
+ * @throws {MfaEnrollmentError} When enrollment fails
181
+ */
182
+ async enrollAuthenticator(options) {
183
+ return this.#options.authClient.mfa.enrollAuthenticator(options);
184
+ }
185
+ /**
186
+ * Initiates an MFA challenge for user verification.
187
+ *
188
+ * @param options - Challenge options
189
+ * @returns Promise resolving to challenge response with challenge details
190
+ * @throws {MfaChallengeError} When the challenge fails
191
+ */
192
+ async challengeAuthenticator(options) {
193
+ return this.#options.authClient.mfa.challengeAuthenticator(options);
194
+ }
195
+ /**
196
+ * Verifies an MFA challenge and completes the authentication flow.
197
+ *
198
+ * Exchanges the MFA token and verification code for access, ID, and refresh tokens,
199
+ * then saves them into the user's session automatically.
200
+ *
201
+ * @param options - The MFA token, factor type (otp / oob / recovery-code), and the code to verify
202
+ * @param storeOptions - Optional options forwarded to the session store. Can be omitted when
203
+ * using the built-in stores; required if your custom store needs extra context (e.g. a request object).
204
+ * @returns The tokens returned by Auth0 after successful verification
205
+ * @throws {MfaVerifyError} When verification fails (e.g. invalid token, wrong code)
206
+ */
207
+ async verify(options, storeOptions) {
208
+ const tokenResponse = await this.#options.authClient.mfa.verify(options);
209
+ const audience = options.audience ?? this.#options.defaultAudience;
210
+ const existingStateData = await this.#options.stateStore.get(
211
+ this.#options.stateStoreIdentifier,
212
+ storeOptions
213
+ );
214
+ const updatedStateData = updateStateData(audience, existingStateData, tokenResponse, {
215
+ domain: this.#options.domain
216
+ });
217
+ await this.#options.stateStore.set(
218
+ this.#options.stateStoreIdentifier,
219
+ updatedStateData,
220
+ true,
221
+ storeOptions
222
+ );
223
+ const result = {
224
+ accessToken: tokenResponse.accessToken,
225
+ tokenType: tokenResponse.tokenType ?? "bearer",
226
+ expiresAt: tokenResponse.expiresAt,
227
+ scope: tokenResponse.scope
228
+ };
229
+ if (tokenResponse.idToken) result.idToken = tokenResponse.idToken;
230
+ if (tokenResponse.refreshToken) result.refreshToken = tokenResponse.refreshToken;
231
+ if (tokenResponse.recoveryCode) result.recoveryCode = tokenResponse.recoveryCode;
232
+ return result;
233
+ }
234
+ };
235
+
135
236
  // src/server-client.ts
136
237
  var DEFAULT_SCOPES = "openid profile email offline_access";
137
- function ensureOpenIdScope(scope) {
238
+ var normalizeDomain = (value) => {
239
+ const trimmed = value.trim();
240
+ const parsed = trimmed.startsWith("http") ? new URL(trimmed) : new URL(`https://${trimmed}`);
241
+ return parsed.host.toLowerCase();
242
+ };
243
+ var decodeIssuer = (token) => {
244
+ try {
245
+ const { iss } = decodeJwt(token);
246
+ return typeof iss === "string" ? iss : void 0;
247
+ } catch {
248
+ return void 0;
249
+ }
250
+ };
251
+ var ensureOpenIdScope = (scope) => {
138
252
  if (!scope) {
139
253
  return DEFAULT_SCOPES;
140
254
  }
@@ -143,20 +257,51 @@ function ensureOpenIdScope(scope) {
143
257
  scopes.unshift("openid");
144
258
  }
145
259
  return scopes.join(" ");
146
- }
260
+ };
147
261
  var ServerClient = class {
148
262
  #options;
149
263
  #transactionStore;
150
264
  #transactionStoreIdentifier;
151
265
  #stateStore;
152
266
  #stateStoreIdentifier;
267
+ #authClientOptions;
268
+ #staticDomain;
269
+ #authClient;
270
+ #mfaClient;
153
271
  /**
154
272
  * The underlying `authClient` instance that can be used to interact with the Auth0 Authentication API.
155
273
  * Generally, you should prefer to use the higher-level methods exposed on the `ServerClient` instance.
156
- *
274
+ *
275
+ * This property can only be used when `domain` is configured as a static string.
276
+ * In resolver mode (`domain` as a function), the SDK resolves the domain per request,
277
+ * so use `ServerClient` methods instead.
278
+ *
157
279
  * Important: the methods exposed on the `authClient` instance do not handle any session or state management.
158
280
  */
159
- authClient;
281
+ get authClient() {
282
+ if (!this.#authClient) {
283
+ throw new InvalidConfigurationError("authClient is only available when using a static domain configuration.");
284
+ }
285
+ return this.#authClient;
286
+ }
287
+ /**
288
+ * The MFA client for managing multi-factor authentication operations.
289
+ *
290
+ * Provides methods to list, enroll, and challenge MFA authenticators,
291
+ * as well as verify MFA challenges to complete authentication.
292
+ *
293
+ * The `verify` method integrates with the session state store, persisting tokens
294
+ * and user data after successful MFA verification.
295
+ *
296
+ * This property can only be used when `domain` is configured as a static string.
297
+ * In resolver mode (`domain` as a function), MFA is not supported.
298
+ */
299
+ get mfa() {
300
+ if (!this.#mfaClient) {
301
+ throw new InvalidConfigurationError("mfa is only available when using a static domain configuration.");
302
+ }
303
+ return this.#mfaClient;
304
+ }
160
305
  constructor(options) {
161
306
  this.#options = options;
162
307
  this.#stateStoreIdentifier = this.#options.stateIdentifier || "__a0_session";
@@ -169,18 +314,84 @@ var ServerClient = class {
169
314
  if (!this.#options.transactionStore) {
170
315
  throw new MissingRequiredArgumentError("transactionStore");
171
316
  }
172
- this.authClient = new AuthClient({
173
- domain: this.#options.domain,
317
+ if (typeof this.#options.domain !== "string" && typeof this.#options.domain !== "function") {
318
+ throw new InvalidConfigurationError("domain must be a string or resolver function");
319
+ }
320
+ this.#authClientOptions = {
174
321
  clientId: this.#options.clientId,
175
322
  clientSecret: this.#options.clientSecret,
176
323
  clientAssertionSigningKey: this.#options.clientAssertionSigningKey,
177
324
  clientAssertionSigningAlg: this.#options.clientAssertionSigningAlg,
178
325
  authorizationParams: this.#options.authorizationParams,
326
+ discoveryCache: this.#options.discoveryCache,
179
327
  customFetch: this.#options.customFetch,
180
- useMtls: this.#options.useMtls,
328
+ useMtls: this.#options.useMtls
329
+ };
330
+ if (typeof this.#options.domain === "string") {
331
+ const domain = normalizeDomain(this.#options.domain);
332
+ this.#staticDomain = domain;
333
+ this.#authClient = new AuthClient({
334
+ domain,
335
+ ...this.#authClientOptions,
336
+ telemetry: getTelemetryConfig(this.#options.telemetry)
337
+ });
338
+ this.#mfaClient = new ServerMfaClient({
339
+ authClient: this.#authClient,
340
+ domain,
341
+ stateStore: this.#stateStore,
342
+ stateStoreIdentifier: this.#stateStoreIdentifier,
343
+ defaultAudience: this.#options.authorizationParams?.audience ?? "default"
344
+ });
345
+ }
346
+ }
347
+ async #resolveDomain(storeOptions) {
348
+ if (typeof this.#options.domain === "function") {
349
+ const resolved = await this.#options.domain(storeOptions);
350
+ if (typeof resolved !== "string" || resolved.trim().length === 0) {
351
+ throw new InvalidConfigurationError("domainResolver returned no domain");
352
+ }
353
+ return normalizeDomain(resolved);
354
+ }
355
+ return normalizeDomain(this.#options.domain);
356
+ }
357
+ #createAuthClient(domain) {
358
+ return new AuthClient({
359
+ domain,
360
+ ...this.#authClientOptions,
181
361
  telemetry: getTelemetryConfig(this.#options.telemetry)
182
362
  });
183
363
  }
364
+ #getAuthClient(domain) {
365
+ const normalizedDomain = normalizeDomain(domain);
366
+ if (this.#authClient && this.#staticDomain === normalizedDomain) {
367
+ return this.#authClient;
368
+ }
369
+ return this.#createAuthClient(normalizedDomain);
370
+ }
371
+ #getSessionDomain(stateData) {
372
+ if (stateData.domain) {
373
+ return normalizeDomain(stateData.domain);
374
+ }
375
+ if (this.#staticDomain) {
376
+ return this.#staticDomain;
377
+ }
378
+ const issuerFromClaims = stateData.user?.iss;
379
+ if (typeof issuerFromClaims === "string" && issuerFromClaims.trim().length > 0) {
380
+ return normalizeDomain(issuerFromClaims);
381
+ }
382
+ return;
383
+ }
384
+ #isResolverMode() {
385
+ return typeof this.#options.domain === "function";
386
+ }
387
+ async #isSessionForCurrentDomain(stateData, storeOptions) {
388
+ const sessionDomain = this.#getSessionDomain(stateData);
389
+ if (!sessionDomain) {
390
+ return false;
391
+ }
392
+ const resolvedDomain = await this.#resolveDomain(storeOptions);
393
+ return sessionDomain === resolvedDomain;
394
+ }
184
395
  /**
185
396
  * Starts the interactive login process, and returns a URL to redirect the user-agent to to request authorization at Auth0.
186
397
  * @param options Optional options used to configure the interactive login process.
@@ -196,7 +407,9 @@ var ServerClient = class {
196
407
  throw new MissingRequiredArgumentError("authorizationParams.redirect_uri");
197
408
  }
198
409
  const scope = ensureOpenIdScope(options?.authorizationParams?.scope ?? this.#options.authorizationParams?.scope);
199
- const { codeVerifier, authorizationUrl } = await this.authClient.buildAuthorizationUrl({
410
+ const domain = await this.#resolveDomain(storeOptions);
411
+ const authClient = this.#getAuthClient(domain);
412
+ const { codeVerifier, authorizationUrl } = await authClient.buildAuthorizationUrl({
200
413
  pushedAuthorizationRequests: options?.pushedAuthorizationRequests,
201
414
  authorizationParams: {
202
415
  ...options?.authorizationParams,
@@ -206,7 +419,8 @@ var ServerClient = class {
206
419
  });
207
420
  const transactionState = {
208
421
  audience: options?.authorizationParams?.audience ?? this.#options.authorizationParams?.audience,
209
- codeVerifier
422
+ codeVerifier,
423
+ domain
210
424
  };
211
425
  if (options?.appState) {
212
426
  transactionState.appState = options.appState;
@@ -230,11 +444,15 @@ var ServerClient = class {
230
444
  if (!transactionData) {
231
445
  throw new MissingTransactionError();
232
446
  }
233
- const tokenEndpointResponse = await this.authClient.getTokenByCode(url, {
447
+ const domain = transactionData.domain ?? await this.#resolveDomain(storeOptions);
448
+ const authClient = this.#getAuthClient(domain);
449
+ const tokenEndpointResponse = await authClient.getTokenByCode(url, {
234
450
  codeVerifier: transactionData.codeVerifier
235
451
  });
236
452
  const existingStateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
237
- const stateData = updateStateData(transactionData.audience ?? "default", existingStateData, tokenEndpointResponse);
453
+ const stateData = updateStateData(transactionData.audience ?? "default", existingStateData, tokenEndpointResponse, {
454
+ domain
455
+ });
238
456
  await this.#stateStore.set(this.#stateStoreIdentifier, stateData, true, storeOptions);
239
457
  await this.#transactionStore.delete(this.#transactionStoreIdentifier, storeOptions);
240
458
  return { appState: transactionData.appState, authorizationDetails: tokenEndpointResponse.authorizationDetails };
@@ -256,7 +474,15 @@ var ServerClient = class {
256
474
  "Unable to start the user linking process without a logged in user. Ensure to login using the SDK before starting the user linking process."
257
475
  );
258
476
  }
259
- const { linkUserUrl, codeVerifier } = await this.authClient.buildLinkUserUrl({
477
+ if (this.#isResolverMode()) {
478
+ const isCurrentDomain = await this.#isSessionForCurrentDomain(stateData, storeOptions);
479
+ if (!isCurrentDomain) {
480
+ throw new MissingSessionError("Session domain does not match the current domain.");
481
+ }
482
+ }
483
+ const domain = this.#getSessionDomain(stateData);
484
+ const authClient = this.#getAuthClient(domain);
485
+ const { linkUserUrl, codeVerifier } = await authClient.buildLinkUserUrl({
260
486
  connection: options.connection,
261
487
  connectionScope: options.connectionScope,
262
488
  idToken: stateData.idToken,
@@ -264,7 +490,8 @@ var ServerClient = class {
264
490
  });
265
491
  const transactionState = {
266
492
  audience: options?.authorizationParams?.audience ?? this.#options.authorizationParams?.audience,
267
- codeVerifier
493
+ codeVerifier,
494
+ domain
268
495
  };
269
496
  if (options?.appState) {
270
497
  transactionState.appState = options.appState;
@@ -306,14 +533,23 @@ var ServerClient = class {
306
533
  "Unable to start the user unlinking process without a logged in user. Ensure to login using the SDK before starting the user unlinking process."
307
534
  );
308
535
  }
309
- const { unlinkUserUrl, codeVerifier } = await this.authClient.buildUnlinkUserUrl({
536
+ if (this.#isResolverMode()) {
537
+ const isCurrentDomain = await this.#isSessionForCurrentDomain(stateData, storeOptions);
538
+ if (!isCurrentDomain) {
539
+ throw new MissingSessionError("Session domain does not match the current domain.");
540
+ }
541
+ }
542
+ const domain = this.#getSessionDomain(stateData);
543
+ const authClient = this.#getAuthClient(domain);
544
+ const { unlinkUserUrl, codeVerifier } = await authClient.buildUnlinkUserUrl({
310
545
  connection: options.connection,
311
546
  idToken: stateData.idToken,
312
547
  authorizationParams: options.authorizationParams
313
548
  });
314
549
  const transactionState = {
315
550
  audience: options?.authorizationParams?.audience ?? this.#options.authorizationParams?.audience,
316
- codeVerifier
551
+ codeVerifier,
552
+ domain
317
553
  };
318
554
  if (options?.appState) {
319
555
  transactionState.appState = options.appState;
@@ -352,7 +588,9 @@ var ServerClient = class {
352
588
  */
353
589
  async loginBackchannel(options, storeOptions) {
354
590
  const scope = ensureOpenIdScope(options.authorizationParams?.scope ?? this.#options.authorizationParams?.scope);
355
- const tokenEndpointResponse = await this.authClient.backchannelAuthentication({
591
+ const domain = await this.#resolveDomain(storeOptions);
592
+ const authClient = this.#getAuthClient(domain);
593
+ const tokenEndpointResponse = await authClient.backchannelAuthentication({
356
594
  bindingMessage: options.bindingMessage,
357
595
  loginHint: options.loginHint,
358
596
  authorizationParams: {
@@ -364,7 +602,8 @@ var ServerClient = class {
364
602
  const stateData = updateStateData(
365
603
  this.#options.authorizationParams?.audience ?? "default",
366
604
  existingStateData,
367
- tokenEndpointResponse
605
+ tokenEndpointResponse,
606
+ { domain }
368
607
  );
369
608
  await this.#stateStore.set(this.#stateStoreIdentifier, stateData, true, storeOptions);
370
609
  return {
@@ -378,16 +617,31 @@ var ServerClient = class {
378
617
  */
379
618
  async getUser(storeOptions) {
380
619
  const stateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
381
- return stateData?.user;
620
+ if (!stateData) {
621
+ return;
622
+ }
623
+ if (this.#isResolverMode()) {
624
+ const isCurrentDomain = await this.#isSessionForCurrentDomain(stateData, storeOptions);
625
+ if (!isCurrentDomain) {
626
+ return;
627
+ }
628
+ }
629
+ return stateData.user;
382
630
  }
383
631
  /**
384
632
  * Retrieve the user session from the store, or undefined if no session found.
385
633
  * @param storeOptions Optional options used to pass to the Transaction and State Store.
386
- * @returns The sessionm or undefined if no session found in the store.
634
+ * @returns The session or undefined if no session found in the store.
387
635
  */
388
636
  async getSession(storeOptions) {
389
637
  const stateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
390
638
  if (stateData) {
639
+ if (this.#isResolverMode()) {
640
+ const isCurrentDomain = await this.#isSessionForCurrentDomain(stateData, storeOptions);
641
+ if (!isCurrentDomain) {
642
+ return;
643
+ }
644
+ }
391
645
  const { internal, ...sessionData } = stateData;
392
646
  return sessionData;
393
647
  }
@@ -395,24 +649,29 @@ var ServerClient = class {
395
649
  /**
396
650
  * 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.
397
651
  * Also updates the store when a new token was retrieved from Auth0.
398
- *
399
- * @param options Optional options for requesting specific audience/scope.
400
652
  * @param storeOptions Optional options used to pass to the Transaction and State Store.
401
653
  *
402
- * @throws {TokenByRefreshTokenError} If the refresh token was not found or there was an issue requesting the access token.
654
+ * @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`.
403
655
  *
404
656
  * @returns The Token Set, containing the access token, as well as additional information.
405
657
  */
406
- async getAccessToken(tokenOptionsOrStoreOptions, storeOptions) {
407
- const hasTokenOptions = (
408
- // If second arg exists, first arg must be GetAccessTokenOptions
409
- storeOptions !== void 0 || // OR if first arg has audience/scope properties
410
- tokenOptionsOrStoreOptions && typeof tokenOptionsOrStoreOptions === "object" && ("audience" in tokenOptionsOrStoreOptions || "scope" in tokenOptionsOrStoreOptions)
411
- );
412
- const [resolvedOptions, resolvedStoreOptions] = hasTokenOptions ? [tokenOptionsOrStoreOptions, storeOptions] : [void 0, tokenOptionsOrStoreOptions];
413
- const stateData = await this.#stateStore.get(this.#stateStoreIdentifier, resolvedStoreOptions);
414
- const audience = resolvedOptions?.audience ?? this.#options.authorizationParams?.audience ?? "default";
415
- const scope = resolvedOptions?.scope ?? this.#options.authorizationParams?.scope;
658
+ async getAccessToken(storeOptions) {
659
+ const stateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
660
+ const audience = this.#options.authorizationParams?.audience ?? "default";
661
+ const scope = this.#options.authorizationParams?.scope;
662
+ const sessionDomain = stateData ? this.#getSessionDomain(stateData) : this.#staticDomain;
663
+ if (this.#isResolverMode()) {
664
+ if (!stateData) {
665
+ throw new MissingSessionError("Unable to retrieve access token without a logged in user.");
666
+ }
667
+ if (!sessionDomain) {
668
+ throw new MissingSessionError("Session domain does not match the current domain.");
669
+ }
670
+ const resolvedDomain = await this.#resolveDomain(storeOptions);
671
+ if (sessionDomain !== resolvedDomain) {
672
+ throw new MissingSessionError("Session domain does not match the current domain.");
673
+ }
674
+ }
416
675
  const tokenSet = stateData?.tokenSets.find(
417
676
  (tokenSet2) => tokenSet2.audience === audience && (!scope || compareScopes(tokenSet2.scope, scope))
418
677
  );
@@ -424,14 +683,15 @@ var ServerClient = class {
424
683
  "The access token has expired and a refresh token was not provided. The user needs to re-authenticate."
425
684
  );
426
685
  }
427
- const tokenByRefreshTokenOptions = {
428
- refreshToken: stateData.refreshToken,
429
- ...hasTokenOptions && { audience, scope }
430
- };
431
- const tokenEndpointResponse = await this.authClient.getTokenByRefreshToken(tokenByRefreshTokenOptions);
432
- const existingStateData = await this.#stateStore.get(this.#stateStoreIdentifier, resolvedStoreOptions);
433
- const updatedStateData = updateStateData(audience, existingStateData, tokenEndpointResponse);
434
- await this.#stateStore.set(this.#stateStoreIdentifier, updatedStateData, false, resolvedStoreOptions);
686
+ const domainForSession = sessionDomain;
687
+ const tokenEndpointResponse = await this.#getAuthClient(domainForSession).getTokenByRefreshToken({
688
+ refreshToken: stateData.refreshToken
689
+ });
690
+ const existingStateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
691
+ const updatedStateData = updateStateData(audience, existingStateData, tokenEndpointResponse, {
692
+ domain: domainForSession
693
+ });
694
+ await this.#stateStore.set(this.#stateStoreIdentifier, updatedStateData, false, storeOptions);
435
695
  return {
436
696
  accessToken: tokenEndpointResponse.accessToken,
437
697
  scope: tokenEndpointResponse.scope,
@@ -456,6 +716,19 @@ var ServerClient = class {
456
716
  */
457
717
  async getAccessTokenForConnection(options, storeOptions) {
458
718
  const stateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
719
+ const sessionDomain = stateData ? this.#getSessionDomain(stateData) : this.#staticDomain;
720
+ if (this.#isResolverMode()) {
721
+ if (!stateData) {
722
+ throw new MissingSessionError("Unable to retrieve an access token for a connection without a logged in user.");
723
+ }
724
+ if (!sessionDomain) {
725
+ throw new MissingSessionError("Session domain does not match the current domain.");
726
+ }
727
+ const resolvedDomain = await this.#resolveDomain(storeOptions);
728
+ if (sessionDomain !== resolvedDomain) {
729
+ throw new MissingSessionError("Session domain does not match the current domain.");
730
+ }
731
+ }
459
732
  const connectionTokenSet = stateData?.connectionTokenSets?.find(
460
733
  (tokenSet) => tokenSet.connection === options.connection
461
734
  );
@@ -467,12 +740,20 @@ var ServerClient = class {
467
740
  "A refresh token was not found but is required to be able to retrieve an access token for a connection."
468
741
  );
469
742
  }
470
- const tokenEndpointResponse = await this.authClient.getTokenForConnection({
743
+ const domainForSession = sessionDomain;
744
+ const tokenEndpointResponse = await this.#getAuthClient(domainForSession).getTokenForConnection({
471
745
  connection: options.connection,
472
746
  loginHint: options.loginHint,
473
747
  refreshToken: stateData.refreshToken
474
748
  });
475
- const updatedStateData = updateStateDataForConnectionTokenSet(options, stateData, tokenEndpointResponse);
749
+ const updatedStateData = updateStateDataForConnectionTokenSet(
750
+ options,
751
+ {
752
+ ...stateData,
753
+ domain: stateData.domain ?? domainForSession
754
+ },
755
+ tokenEndpointResponse
756
+ );
476
757
  await this.#stateStore.set(this.#stateStoreIdentifier, updatedStateData, false, storeOptions);
477
758
  return {
478
759
  accessToken: tokenEndpointResponse.accessToken,
@@ -489,8 +770,21 @@ var ServerClient = class {
489
770
  * @returns {URL}
490
771
  */
491
772
  async logout(options, storeOptions) {
492
- await this.#stateStore.delete(this.#stateStoreIdentifier, storeOptions);
493
- return this.authClient.buildLogoutUrl(options);
773
+ if (!this.#isResolverMode()) {
774
+ await this.#stateStore.delete(this.#stateStoreIdentifier, storeOptions);
775
+ return this.authClient.buildLogoutUrl(options);
776
+ }
777
+ const resolvedDomain = await this.#resolveDomain(storeOptions);
778
+ const authClient = this.#getAuthClient(resolvedDomain);
779
+ const stateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
780
+ const sessionDomain = stateData ? this.#getSessionDomain(stateData) : void 0;
781
+ if (!stateData) {
782
+ return authClient.buildLogoutUrl(options);
783
+ }
784
+ if (sessionDomain && sessionDomain === resolvedDomain) {
785
+ await this.#stateStore.delete(this.#stateStoreIdentifier, storeOptions);
786
+ }
787
+ return authClient.buildLogoutUrl(options);
494
788
  }
495
789
  /**
496
790
  * Handles the backchannel logout process by verifying the logout token and deleting the session from the store if the logout token was considered valid.
@@ -504,8 +798,23 @@ var ServerClient = class {
504
798
  if (!logoutToken) {
505
799
  throw new BackchannelLogoutError("Missing Logout Token");
506
800
  }
507
- const logoutTokenClaims = await this.authClient.verifyLogoutToken({ logoutToken });
508
- await this.#stateStore.deleteByLogoutToken(logoutTokenClaims, storeOptions);
801
+ if (!this.#isResolverMode()) {
802
+ const logoutTokenClaims2 = await this.authClient.verifyLogoutToken({ logoutToken });
803
+ await this.#stateStore.deleteByLogoutToken(logoutTokenClaims2, storeOptions);
804
+ return;
805
+ }
806
+ const issuer = decodeIssuer(logoutToken);
807
+ if (!issuer) {
808
+ throw new BackchannelLogoutError("Logout token is missing an issuer");
809
+ }
810
+ const resolvedDomain = await this.#resolveDomain(storeOptions);
811
+ const domain = normalizeDomain(issuer);
812
+ if (domain !== resolvedDomain) {
813
+ throw new BackchannelLogoutError("Logout token issuer does not match the resolved domain");
814
+ }
815
+ const authClient = this.#getAuthClient(domain);
816
+ const logoutTokenClaims = await authClient.verifyLogoutToken({ logoutToken });
817
+ await this.#stateStore.deleteByLogoutToken({ ...logoutTokenClaims, iss: issuer }, storeOptions);
509
818
  }
510
819
  };
511
820
 
@@ -823,18 +1132,34 @@ var StatelessStateStore = class extends AbstractSessionStore {
823
1132
  };
824
1133
  }
825
1134
  };
1135
+
1136
+ // src/mfa/index.ts
1137
+ import {
1138
+ MfaListAuthenticatorsError,
1139
+ MfaEnrollmentError,
1140
+ MfaChallengeError,
1141
+ MfaVerifyError,
1142
+ isMfaRequiredError
1143
+ } from "@auth0/auth0-auth-js";
826
1144
  export {
827
1145
  AbstractStateStore,
828
1146
  AbstractTransactionStore,
829
1147
  BackchannelLogoutError,
830
1148
  CookieTransactionStore,
831
1149
  InvalidConfigurationError,
1150
+ IssuerValidationError,
1151
+ MfaChallengeError,
1152
+ MfaEnrollmentError,
1153
+ MfaListAuthenticatorsError,
1154
+ MfaVerifyError,
832
1155
  MissingRequiredArgumentError,
833
1156
  MissingSessionError,
834
1157
  MissingTransactionError,
835
1158
  ServerClient,
1159
+ ServerMfaClient,
836
1160
  StartLinkUserError,
837
1161
  StatefulStateStore,
838
- StatelessStateStore
1162
+ StatelessStateStore,
1163
+ isMfaRequiredError
839
1164
  };
840
1165
  //# sourceMappingURL=index.js.map