@auth0/auth0-server-js 1.2.0 → 1.3.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.d.cts CHANGED
@@ -1,4 +1,5 @@
1
- import { AuthorizationDetails, AuthClient } from '@auth0/auth0-auth-js';
1
+ import { AuthorizationDetails, TelemetryConfig, AuthClient } from '@auth0/auth0-auth-js';
2
+ export { TelemetryConfig } from '@auth0/auth0-auth-js';
2
3
  import { JWTPayload } from 'jose';
3
4
 
4
5
  interface ServerClientOptions<TStoreOptions = unknown> {
@@ -22,6 +23,11 @@ interface ServerClientOptions<TStoreOptions = unknown> {
22
23
  * When set to `true`, using a `customFetch` is required.
23
24
  */
24
25
  useMtls?: boolean;
26
+ /**
27
+ * Optional telemetry configuration.
28
+ * Telemetry is enabled by default and sends the Auth0-Client header with package name and version.
29
+ */
30
+ telemetry?: TelemetryConfig;
25
31
  }
26
32
  interface UserClaims {
27
33
  sub: string;
@@ -89,7 +95,11 @@ interface StateStore<TStoreOptions = unknown> extends AbstractDataStore<StateDat
89
95
  interface TransactionStore<TStoreOptions = unknown> extends AbstractDataStore<TransactionData, TStoreOptions> {
90
96
  }
91
97
  interface EncryptedStoreOptions {
92
- secret: string;
98
+ /**
99
+ * The secret(s) to use for encryption and decryption. Can be a single string or an array of strings for secret rotation support.
100
+ * When using an array of secrets, the first one is used for encryption, while all secrets are tried, in-order, for decryption.
101
+ */
102
+ secret: string | string[];
93
103
  }
94
104
  interface StartInteractiveLoginOptions<TAppState = unknown> {
95
105
  pushedAuthorizationRequests?: boolean;
@@ -110,6 +120,25 @@ interface AccessTokenForConnectionOptions {
110
120
  connection: string;
111
121
  loginHint?: string;
112
122
  }
123
+ /**
124
+ * Options for retrieving an access token with MRRT support.
125
+ * Allows requesting tokens for specific audiences and scopes at runtime.
126
+ */
127
+ interface GetAccessTokenOptions {
128
+ /**
129
+ * Optional audience for the requested access token.
130
+ * If not provided, falls back to configuration audience or 'default'.
131
+ * @example 'https://api.example.com'
132
+ */
133
+ audience?: string;
134
+ /**
135
+ * Optional scope for the requested access token.
136
+ * If not provided, falls back to configuration scope.
137
+ * Space-separated scope string.
138
+ * @example 'read:data write:data'
139
+ */
140
+ scope?: string;
141
+ }
113
142
  interface LogoutOptions {
114
143
  returnTo: string;
115
144
  }
@@ -306,16 +335,8 @@ declare class ServerClient<TStoreOptions = unknown> {
306
335
  * @returns The sessionm or undefined if no session found in the store.
307
336
  */
308
337
  getSession(storeOptions?: TStoreOptions): Promise<SessionData | undefined>;
309
- /**
310
- * 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.
311
- * Also updates the store when a new token was retrieved from Auth0.
312
- * @param storeOptions Optional options used to pass to the Transaction and State Store.
313
- *
314
- * @throws {TokenByRefreshTokenError} If the refresh token was not found or there was an issue requesting the access token.
315
- *
316
- * @returns The Token Set, containing the access token, as well as additional information.
317
- */
318
338
  getAccessToken(storeOptions?: TStoreOptions): Promise<TokenSet>;
339
+ getAccessToken(options: GetAccessTokenOptions, storeOptions?: TStoreOptions): Promise<TokenSet>;
319
340
  /**
320
341
  * Retrieves an access token for a connection.
321
342
  *
@@ -360,7 +381,7 @@ declare abstract class AbstractStore<TData extends JWTPayload, TStoreOptions = u
360
381
  abstract get(identifier: string, options?: TStoreOptions | undefined): Promise<TData | undefined>;
361
382
  abstract delete(identifier: string, options?: TStoreOptions | undefined): Promise<void>;
362
383
  protected encrypt<TData extends JWTPayload>(identifier: string, stateData: TData, expiration: number): Promise<string>;
363
- protected decrypt<TData>(identifier: string, encryptedStateData: string): Promise<TData>;
384
+ protected decrypt<TData>(identifier: string, encryptedStateData: string): Promise<TData | undefined>;
364
385
  }
365
386
 
366
387
  /**
@@ -386,6 +407,13 @@ interface CookieSerializeOptions {
386
407
  domain?: string;
387
408
  expires?: Date;
388
409
  httpOnly?: boolean;
410
+ /**
411
+ * MaxAge value of the cookie in seconds.
412
+ *
413
+ * Note for implementors of {@link CookieHandler}: this value is always in seconds.
414
+ * Some frameworks (e.g. Express) expect `maxAge` in milliseconds, so you may need to convert
415
+ * before passing it to the underlying framework (e.g. `maxAge * 1000`).
416
+ */
389
417
  maxAge?: number;
390
418
  path?: string;
391
419
  secure?: boolean;
@@ -503,5 +531,12 @@ declare class MissingSessionError extends Error {
503
531
  code: string;
504
532
  constructor(message: string);
505
533
  }
534
+ /**
535
+ * Error thrown when a configuration is invalid.
536
+ */
537
+ declare class InvalidConfigurationError extends Error {
538
+ code: string;
539
+ constructor(message: string);
540
+ }
506
541
 
507
- export { type AbstractDataStore, AbstractStateStore, AbstractTransactionStore, type AccessTokenForConnectionOptions, type AuthorizationParameters, BackchannelLogoutError, type ConnectionTokenSet, type CookieHandler, type CookieSerializeOptions, CookieTransactionStore, type EncryptedStoreOptions, type InternalStateData, type LoginBackchannelOptions, type LoginBackchannelResult, type LogoutOptions, type LogoutTokenClaims, MissingRequiredArgumentError, MissingSessionError, MissingTransactionError, ServerClient, type ServerClientOptions, type SessionConfiguration, type SessionCookieOptions, type SessionData, type SessionStore, type StartInteractiveLoginOptions, StartLinkUserError, type StartLinkUserOptions, type StartUnlinkUserOptions, type StateData, type StateStore, StatefulStateStore, type StatefulStateStoreOptions, StatelessStateStore, type TokenSet, type TransactionData, type TransactionStore, type UserClaims };
542
+ export { type AbstractDataStore, AbstractStateStore, AbstractTransactionStore, type AccessTokenForConnectionOptions, type AuthorizationParameters, BackchannelLogoutError, type ConnectionTokenSet, type CookieHandler, type CookieSerializeOptions, CookieTransactionStore, type EncryptedStoreOptions, type GetAccessTokenOptions, type InternalStateData, InvalidConfigurationError, type LoginBackchannelOptions, type LoginBackchannelResult, type LogoutOptions, type LogoutTokenClaims, MissingRequiredArgumentError, MissingSessionError, MissingTransactionError, ServerClient, type ServerClientOptions, type SessionConfiguration, type SessionCookieOptions, type SessionData, type SessionStore, type StartInteractiveLoginOptions, StartLinkUserError, type StartLinkUserOptions, type StartUnlinkUserOptions, type StateData, type StateStore, StatefulStateStore, type StatefulStateStoreOptions, StatelessStateStore, type TokenSet, type TransactionData, type TransactionStore, type UserClaims };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { AuthorizationDetails, AuthClient } from '@auth0/auth0-auth-js';
1
+ import { AuthorizationDetails, TelemetryConfig, AuthClient } from '@auth0/auth0-auth-js';
2
+ export { TelemetryConfig } from '@auth0/auth0-auth-js';
2
3
  import { JWTPayload } from 'jose';
3
4
 
4
5
  interface ServerClientOptions<TStoreOptions = unknown> {
@@ -22,6 +23,11 @@ interface ServerClientOptions<TStoreOptions = unknown> {
22
23
  * When set to `true`, using a `customFetch` is required.
23
24
  */
24
25
  useMtls?: boolean;
26
+ /**
27
+ * Optional telemetry configuration.
28
+ * Telemetry is enabled by default and sends the Auth0-Client header with package name and version.
29
+ */
30
+ telemetry?: TelemetryConfig;
25
31
  }
26
32
  interface UserClaims {
27
33
  sub: string;
@@ -89,7 +95,11 @@ interface StateStore<TStoreOptions = unknown> extends AbstractDataStore<StateDat
89
95
  interface TransactionStore<TStoreOptions = unknown> extends AbstractDataStore<TransactionData, TStoreOptions> {
90
96
  }
91
97
  interface EncryptedStoreOptions {
92
- secret: string;
98
+ /**
99
+ * The secret(s) to use for encryption and decryption. Can be a single string or an array of strings for secret rotation support.
100
+ * When using an array of secrets, the first one is used for encryption, while all secrets are tried, in-order, for decryption.
101
+ */
102
+ secret: string | string[];
93
103
  }
94
104
  interface StartInteractiveLoginOptions<TAppState = unknown> {
95
105
  pushedAuthorizationRequests?: boolean;
@@ -110,6 +120,25 @@ interface AccessTokenForConnectionOptions {
110
120
  connection: string;
111
121
  loginHint?: string;
112
122
  }
123
+ /**
124
+ * Options for retrieving an access token with MRRT support.
125
+ * Allows requesting tokens for specific audiences and scopes at runtime.
126
+ */
127
+ interface GetAccessTokenOptions {
128
+ /**
129
+ * Optional audience for the requested access token.
130
+ * If not provided, falls back to configuration audience or 'default'.
131
+ * @example 'https://api.example.com'
132
+ */
133
+ audience?: string;
134
+ /**
135
+ * Optional scope for the requested access token.
136
+ * If not provided, falls back to configuration scope.
137
+ * Space-separated scope string.
138
+ * @example 'read:data write:data'
139
+ */
140
+ scope?: string;
141
+ }
113
142
  interface LogoutOptions {
114
143
  returnTo: string;
115
144
  }
@@ -306,16 +335,8 @@ declare class ServerClient<TStoreOptions = unknown> {
306
335
  * @returns The sessionm or undefined if no session found in the store.
307
336
  */
308
337
  getSession(storeOptions?: TStoreOptions): Promise<SessionData | undefined>;
309
- /**
310
- * 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.
311
- * Also updates the store when a new token was retrieved from Auth0.
312
- * @param storeOptions Optional options used to pass to the Transaction and State Store.
313
- *
314
- * @throws {TokenByRefreshTokenError} If the refresh token was not found or there was an issue requesting the access token.
315
- *
316
- * @returns The Token Set, containing the access token, as well as additional information.
317
- */
318
338
  getAccessToken(storeOptions?: TStoreOptions): Promise<TokenSet>;
339
+ getAccessToken(options: GetAccessTokenOptions, storeOptions?: TStoreOptions): Promise<TokenSet>;
319
340
  /**
320
341
  * Retrieves an access token for a connection.
321
342
  *
@@ -360,7 +381,7 @@ declare abstract class AbstractStore<TData extends JWTPayload, TStoreOptions = u
360
381
  abstract get(identifier: string, options?: TStoreOptions | undefined): Promise<TData | undefined>;
361
382
  abstract delete(identifier: string, options?: TStoreOptions | undefined): Promise<void>;
362
383
  protected encrypt<TData extends JWTPayload>(identifier: string, stateData: TData, expiration: number): Promise<string>;
363
- protected decrypt<TData>(identifier: string, encryptedStateData: string): Promise<TData>;
384
+ protected decrypt<TData>(identifier: string, encryptedStateData: string): Promise<TData | undefined>;
364
385
  }
365
386
 
366
387
  /**
@@ -386,6 +407,13 @@ interface CookieSerializeOptions {
386
407
  domain?: string;
387
408
  expires?: Date;
388
409
  httpOnly?: boolean;
410
+ /**
411
+ * MaxAge value of the cookie in seconds.
412
+ *
413
+ * Note for implementors of {@link CookieHandler}: this value is always in seconds.
414
+ * Some frameworks (e.g. Express) expect `maxAge` in milliseconds, so you may need to convert
415
+ * before passing it to the underlying framework (e.g. `maxAge * 1000`).
416
+ */
389
417
  maxAge?: number;
390
418
  path?: string;
391
419
  secure?: boolean;
@@ -503,5 +531,12 @@ declare class MissingSessionError extends Error {
503
531
  code: string;
504
532
  constructor(message: string);
505
533
  }
534
+ /**
535
+ * Error thrown when a configuration is invalid.
536
+ */
537
+ declare class InvalidConfigurationError extends Error {
538
+ code: string;
539
+ constructor(message: string);
540
+ }
506
541
 
507
- export { type AbstractDataStore, AbstractStateStore, AbstractTransactionStore, type AccessTokenForConnectionOptions, type AuthorizationParameters, BackchannelLogoutError, type ConnectionTokenSet, type CookieHandler, type CookieSerializeOptions, CookieTransactionStore, type EncryptedStoreOptions, type InternalStateData, type LoginBackchannelOptions, type LoginBackchannelResult, type LogoutOptions, type LogoutTokenClaims, MissingRequiredArgumentError, MissingSessionError, MissingTransactionError, ServerClient, type ServerClientOptions, type SessionConfiguration, type SessionCookieOptions, type SessionData, type SessionStore, type StartInteractiveLoginOptions, StartLinkUserError, type StartLinkUserOptions, type StartUnlinkUserOptions, type StateData, type StateStore, StatefulStateStore, type StatefulStateStoreOptions, StatelessStateStore, type TokenSet, type TransactionData, type TransactionStore, type UserClaims };
542
+ export { type AbstractDataStore, AbstractStateStore, AbstractTransactionStore, type AccessTokenForConnectionOptions, type AuthorizationParameters, BackchannelLogoutError, type ConnectionTokenSet, type CookieHandler, type CookieSerializeOptions, CookieTransactionStore, type EncryptedStoreOptions, type GetAccessTokenOptions, type InternalStateData, InvalidConfigurationError, type LoginBackchannelOptions, type LoginBackchannelResult, type LogoutOptions, type LogoutTokenClaims, MissingRequiredArgumentError, MissingSessionError, MissingTransactionError, ServerClient, type ServerClientOptions, type SessionConfiguration, type SessionCookieOptions, type SessionData, type SessionStore, type StartInteractiveLoginOptions, StartLinkUserError, type StartLinkUserOptions, type StartUnlinkUserOptions, type StateData, type StateStore, StatefulStateStore, type StatefulStateStoreOptions, StatelessStateStore, type TokenSet, type TransactionData, type TransactionStore, type UserClaims };
package/dist/index.js CHANGED
@@ -34,6 +34,13 @@ var MissingSessionError = class extends Error {
34
34
  this.name = "MissingSessionError";
35
35
  }
36
36
  };
37
+ var InvalidConfigurationError = class extends Error {
38
+ code = "invalid_configuration_error";
39
+ constructor(message) {
40
+ super(message);
41
+ this.name = "InvalidConfigurationError";
42
+ }
43
+ };
37
44
 
38
45
  // src/state/utils.ts
39
46
  var createUpdatedTokenSet = (audience, response) => ({
@@ -42,18 +49,18 @@ var createUpdatedTokenSet = (audience, response) => ({
42
49
  scope: response.scope,
43
50
  expiresAt: response.expiresAt
44
51
  });
45
- function updateStateData(audience, stateDate, tokenEndpointResponse) {
46
- if (stateDate) {
47
- const isNewTokenSet = !stateDate.tokenSets.some(
52
+ function updateStateData(audience, stateData, tokenEndpointResponse) {
53
+ if (stateData) {
54
+ const isNewTokenSet = !stateData.tokenSets.some(
48
55
  (tokenSet) => tokenSet.audience === audience && tokenSet.scope === tokenEndpointResponse.scope
49
56
  );
50
- const tokenSets = isNewTokenSet ? [...stateDate.tokenSets, createUpdatedTokenSet(audience, tokenEndpointResponse)] : stateDate.tokenSets.map(
57
+ const tokenSets = isNewTokenSet ? [...stateData.tokenSets, createUpdatedTokenSet(audience, tokenEndpointResponse)] : stateData.tokenSets.map(
51
58
  (tokenSet) => tokenSet.audience === audience && tokenSet.scope === tokenEndpointResponse.scope ? createUpdatedTokenSet(audience, tokenEndpointResponse) : tokenSet
52
59
  );
53
60
  return {
54
- ...stateDate,
55
- idToken: tokenEndpointResponse.idToken,
56
- refreshToken: tokenEndpointResponse.refreshToken ?? stateDate.refreshToken,
61
+ ...stateData,
62
+ idToken: tokenEndpointResponse.idToken ?? stateData.idToken,
63
+ refreshToken: tokenEndpointResponse.refreshToken ?? stateData.refreshToken,
57
64
  tokenSets
58
65
  };
59
66
  } else {
@@ -72,9 +79,9 @@ function updateStateData(audience, stateDate, tokenEndpointResponse) {
72
79
  };
73
80
  }
74
81
  }
75
- function updateStateDataForConnectionTokenSet(options, stateDate, tokenEndpointResponse) {
76
- stateDate.connectionTokenSets = stateDate.connectionTokenSets || [];
77
- const isNewTokenSet = !stateDate.connectionTokenSets.some(
82
+ function updateStateDataForConnectionTokenSet(options, stateData, tokenEndpointResponse) {
83
+ stateData.connectionTokenSets = stateData.connectionTokenSets || [];
84
+ const isNewTokenSet = !stateData.connectionTokenSets.some(
78
85
  (tokenSet) => tokenSet.connection === options.connection && (!options.loginHint || tokenSet.loginHint === options.loginHint)
79
86
  );
80
87
  const connectionTokenSet = {
@@ -84,11 +91,11 @@ function updateStateDataForConnectionTokenSet(options, stateDate, tokenEndpointR
84
91
  scope: tokenEndpointResponse.scope,
85
92
  expiresAt: tokenEndpointResponse.expiresAt
86
93
  };
87
- const connectionTokenSets = isNewTokenSet ? [...stateDate.connectionTokenSets, connectionTokenSet] : stateDate.connectionTokenSets.map(
94
+ const connectionTokenSets = isNewTokenSet ? [...stateData.connectionTokenSets, connectionTokenSet] : stateData.connectionTokenSets.map(
88
95
  (tokenSet) => tokenSet.connection === options.connection && (!options.loginHint || tokenSet.loginHint === options.loginHint) ? connectionTokenSet : tokenSet
89
96
  );
90
97
  return {
91
- ...stateDate,
98
+ ...stateData,
92
99
  connectionTokenSets
93
100
  };
94
101
  }
@@ -113,7 +120,30 @@ var compareScopes = (scopes, requiredScopes) => {
113
120
  return requiredScopesArray.every((scope) => scopesSet.has(scope));
114
121
  };
115
122
 
123
+ // src/telemetry.ts
124
+ function getTelemetryConfig(config) {
125
+ if (config?.enabled === false) {
126
+ return config;
127
+ }
128
+ return {
129
+ enabled: true,
130
+ name: config?.name ?? "@auth0/auth0-server-js",
131
+ version: config?.version ?? "1.3.0"
132
+ };
133
+ }
134
+
116
135
  // src/server-client.ts
136
+ var DEFAULT_SCOPES = "openid profile email offline_access";
137
+ function ensureOpenIdScope(scope) {
138
+ if (!scope) {
139
+ return DEFAULT_SCOPES;
140
+ }
141
+ const scopes = scope.split(" ");
142
+ if (!scopes.includes("openid")) {
143
+ scopes.unshift("openid");
144
+ }
145
+ return scopes.join(" ");
146
+ }
117
147
  var ServerClient = class {
118
148
  #options;
119
149
  #transactionStore;
@@ -147,7 +177,8 @@ var ServerClient = class {
147
177
  clientAssertionSigningAlg: this.#options.clientAssertionSigningAlg,
148
178
  authorizationParams: this.#options.authorizationParams,
149
179
  customFetch: this.#options.customFetch,
150
- useMtls: this.#options.useMtls
180
+ useMtls: this.#options.useMtls,
181
+ telemetry: getTelemetryConfig(this.#options.telemetry)
151
182
  });
152
183
  }
153
184
  /**
@@ -164,11 +195,13 @@ var ServerClient = class {
164
195
  if (!redirectUri) {
165
196
  throw new MissingRequiredArgumentError("authorizationParams.redirect_uri");
166
197
  }
198
+ const scope = ensureOpenIdScope(options?.authorizationParams?.scope ?? this.#options.authorizationParams?.scope);
167
199
  const { codeVerifier, authorizationUrl } = await this.authClient.buildAuthorizationUrl({
168
200
  pushedAuthorizationRequests: options?.pushedAuthorizationRequests,
169
201
  authorizationParams: {
170
202
  ...options?.authorizationParams,
171
- redirect_uri: redirectUri
203
+ redirect_uri: redirectUri,
204
+ scope
172
205
  }
173
206
  });
174
207
  const transactionState = {
@@ -318,10 +351,14 @@ var ServerClient = class {
318
351
  * @returns A promise resolving to an object, containing the authorizationDetails (when RAR was used).
319
352
  */
320
353
  async loginBackchannel(options, storeOptions) {
354
+ const scope = ensureOpenIdScope(options.authorizationParams?.scope ?? this.#options.authorizationParams?.scope);
321
355
  const tokenEndpointResponse = await this.authClient.backchannelAuthentication({
322
356
  bindingMessage: options.bindingMessage,
323
357
  loginHint: options.loginHint,
324
- authorizationParams: options.authorizationParams
358
+ authorizationParams: {
359
+ ...options.authorizationParams,
360
+ scope
361
+ }
325
362
  });
326
363
  const existingStateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
327
364
  const stateData = updateStateData(
@@ -358,16 +395,24 @@ var ServerClient = class {
358
395
  /**
359
396
  * 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.
360
397
  * Also updates the store when a new token was retrieved from Auth0.
398
+ *
399
+ * @param options Optional options for requesting specific audience/scope.
361
400
  * @param storeOptions Optional options used to pass to the Transaction and State Store.
362
401
  *
363
402
  * @throws {TokenByRefreshTokenError} If the refresh token was not found or there was an issue requesting the access token.
364
403
  *
365
404
  * @returns The Token Set, containing the access token, as well as additional information.
366
405
  */
367
- async getAccessToken(storeOptions) {
368
- const stateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
369
- const audience = this.#options.authorizationParams?.audience ?? "default";
370
- const scope = this.#options.authorizationParams?.scope;
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;
371
416
  const tokenSet = stateData?.tokenSets.find(
372
417
  (tokenSet2) => tokenSet2.audience === audience && (!scope || compareScopes(tokenSet2.scope, scope))
373
418
  );
@@ -379,12 +424,14 @@ var ServerClient = class {
379
424
  "The access token has expired and a refresh token was not provided. The user needs to re-authenticate."
380
425
  );
381
426
  }
382
- const tokenEndpointResponse = await this.authClient.getTokenByRefreshToken({
383
- refreshToken: stateData.refreshToken
384
- });
385
- const existingStateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
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);
386
433
  const updatedStateData = updateStateData(audience, existingStateData, tokenEndpointResponse);
387
- await this.#stateStore.set(this.#stateStoreIdentifier, updatedStateData, false, storeOptions);
434
+ await this.#stateStore.set(this.#stateStoreIdentifier, updatedStateData, false, resolvedStoreOptions);
388
435
  return {
389
436
  accessToken: tokenEndpointResponse.accessToken,
390
437
  scope: tokenEndpointResponse.scope,
@@ -463,13 +510,16 @@ var ServerClient = class {
463
510
  };
464
511
 
465
512
  // src/encryption/index.ts
466
- import { EncryptJWT, jwtDecrypt } from "jose";
513
+ import { EncryptJWT, jwtDecrypt, errors } from "jose";
467
514
  var ENC = "A256CBC-HS512";
468
515
  var ALG = "dir";
469
516
  var DIGEST = "SHA-256";
470
517
  var BIT_LENGTH = 512;
471
518
  var HKDF_INFO = "derived cookie encryption secret";
472
519
  var encoder;
520
+ function isDecryptionError(e) {
521
+ return e instanceof errors.JWEDecryptionFailed || e instanceof errors.JWEInvalid;
522
+ }
473
523
  async function deriveEncryptionSecret(secret, salt, kid) {
474
524
  encoder ||= new TextEncoder();
475
525
  const key = await crypto.subtle.importKey("raw", encoder.encode(secret), "HKDF", false, ["deriveBits"]);
@@ -486,12 +536,23 @@ async function deriveEncryptionSecret(secret, salt, kid) {
486
536
  )
487
537
  );
488
538
  }
489
- async function encrypt(payload, secret, salt, expiration) {
539
+ async function _encrypt(payload, secret, salt, expiration) {
490
540
  const kid = crypto.randomUUID();
491
541
  const encryptionSecret = await deriveEncryptionSecret(secret, salt, kid);
492
542
  return await new EncryptJWT(payload).setProtectedHeader({ enc: ENC, alg: ALG, kid }).setExpirationTime(expiration).encrypt(encryptionSecret);
493
543
  }
494
- async function decrypt(value, secret, salt) {
544
+ async function encrypt(payload, secret, salt, expiration) {
545
+ if (typeof secret === "string") {
546
+ return await _encrypt(payload, secret, salt, expiration);
547
+ } else {
548
+ const [newSecret] = secret;
549
+ if (!newSecret) {
550
+ throw new InvalidConfigurationError("At least one secret must be provided");
551
+ }
552
+ return await _encrypt(payload, newSecret, salt, expiration);
553
+ }
554
+ }
555
+ async function _decrypt(value, secret, salt) {
495
556
  const res = await jwtDecrypt(
496
557
  value,
497
558
  async (protectedHeader) => {
@@ -504,6 +565,35 @@ async function decrypt(value, secret, salt) {
504
565
  );
505
566
  return res.payload;
506
567
  }
568
+ async function decrypt(value, secret, salt) {
569
+ if (typeof secret === "string") {
570
+ return await _decrypt(value, secret, salt);
571
+ } else {
572
+ const [newSecret, ...oldSecrets] = secret;
573
+ if (!newSecret) {
574
+ throw new InvalidConfigurationError("At least one secret must be provided");
575
+ }
576
+ let firstError;
577
+ try {
578
+ return await _decrypt(value, newSecret, salt);
579
+ } catch (err) {
580
+ firstError = err;
581
+ if (!isDecryptionError(err)) {
582
+ throw firstError;
583
+ }
584
+ for (const oldSecret of oldSecrets) {
585
+ try {
586
+ return await _decrypt(value, oldSecret, salt);
587
+ } catch (fallbackErr) {
588
+ if (!isDecryptionError(fallbackErr)) {
589
+ throw fallbackErr;
590
+ }
591
+ }
592
+ }
593
+ throw firstError;
594
+ }
595
+ }
596
+ }
507
597
 
508
598
  // src/store/abstract-store.ts
509
599
  var AbstractStore = class {
@@ -515,7 +605,14 @@ var AbstractStore = class {
515
605
  return await encrypt(stateData, this.options.secret, identifier, expiration);
516
606
  }
517
607
  async decrypt(identifier, encryptedStateData) {
518
- return await decrypt(encryptedStateData, this.options.secret, identifier);
608
+ try {
609
+ return await decrypt(encryptedStateData, this.options.secret, identifier);
610
+ } catch (e) {
611
+ if (isDecryptionError(e)) {
612
+ return;
613
+ }
614
+ throw e;
615
+ }
519
616
  }
520
617
  };
521
618
 
@@ -642,7 +739,9 @@ var StatefulStateStore = class extends AbstractSessionStore {
642
739
  const cookieValue = this.#cookieHandler.getCookie(identifier, options);
643
740
  if (cookieValue) {
644
741
  const sessionCookie = await this.decrypt(identifier, cookieValue);
645
- return sessionCookie.id;
742
+ if (sessionCookie) {
743
+ return sessionCookie.id;
744
+ }
646
745
  }
647
746
  }
648
747
  deleteByLogoutToken(claims, options) {
@@ -729,6 +828,7 @@ export {
729
828
  AbstractTransactionStore,
730
829
  BackchannelLogoutError,
731
830
  CookieTransactionStore,
831
+ InvalidConfigurationError,
732
832
  MissingRequiredArgumentError,
733
833
  MissingSessionError,
734
834
  MissingTransactionError,