@auth0/auth0-server-js 1.7.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +95 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -2
- package/dist/index.d.ts +24 -2
- package/dist/index.js +94 -21
- package/dist/index.js.map +1 -1
- package/package.json +14 -14
package/dist/index.d.cts
CHANGED
|
@@ -92,6 +92,15 @@ interface SessionData {
|
|
|
92
92
|
tokenSets: TokenSet[];
|
|
93
93
|
connectionTokenSets?: ConnectionTokenSet[];
|
|
94
94
|
domain?: string;
|
|
95
|
+
/**
|
|
96
|
+
* IPSIE SL1 `session_expiry` ceiling for this session, as an absolute Unix timestamp in
|
|
97
|
+
* seconds. Present only when the user logged in through an enterprise connection configured
|
|
98
|
+
* with `id_token_session_expiry_supported: true`. When set, the SDK treats the session as
|
|
99
|
+
* expired once this time is reached (minus a small leeway) and forces re-authentication.
|
|
100
|
+
* Absent for database/social logins, connections without the option, and sessions created
|
|
101
|
+
* before this feature — those behave unchanged.
|
|
102
|
+
*/
|
|
103
|
+
sessionExpiresAt?: number;
|
|
95
104
|
[key: string]: unknown;
|
|
96
105
|
}
|
|
97
106
|
interface TransactionData {
|
|
@@ -619,6 +628,7 @@ declare class ServerClient<TStoreOptions = unknown> {
|
|
|
619
628
|
*
|
|
620
629
|
* @throws {MissingTransactionError} When no transaction was found.
|
|
621
630
|
* @throws {TokenByCodeError} If there was an issue requesting the access token.
|
|
631
|
+
* @throws {SessionExpiredError} When the ID token's `session_expiry` is already in the past at login (the session is born expired); nothing is persisted.
|
|
622
632
|
*
|
|
623
633
|
* @returns A promise resolving to an object, containing the original appState (if present) and the authorizationDetails (when RAR was used).
|
|
624
634
|
*/
|
|
@@ -633,6 +643,7 @@ declare class ServerClient<TStoreOptions = unknown> {
|
|
|
633
643
|
*
|
|
634
644
|
* @throws {MissingSessionError} If there is no active session.
|
|
635
645
|
* @throws {BuildLinkUserUrlError} If there was an issue when building the Authorization URL.
|
|
646
|
+
* @throws {SessionExpiredError} When the session's `session_expiry` ceiling has been reached; the session is cleared and re-authentication is required.
|
|
636
647
|
*
|
|
637
648
|
* @returns A promise resolving to a URL object, representing the URL to redirect the user-agent to to request authorization at Auth0.
|
|
638
649
|
*/
|
|
@@ -658,6 +669,7 @@ declare class ServerClient<TStoreOptions = unknown> {
|
|
|
658
669
|
*
|
|
659
670
|
* @throws {MissingSessionError} If there is no active session.
|
|
660
671
|
* @throws {BuildUnlinkUserUrlError} If there was an issue when building the User Unlinking URL.
|
|
672
|
+
* @throws {SessionExpiredError} When the session's `session_expiry` ceiling has been reached; the session is cleared and re-authentication is required.
|
|
661
673
|
*
|
|
662
674
|
* @returns A promise resolving to a URL object, representing the URL to redirect the user-agent to to request authorization at Auth0.
|
|
663
675
|
*/
|
|
@@ -685,6 +697,7 @@ declare class ServerClient<TStoreOptions = unknown> {
|
|
|
685
697
|
* @param storeOptions Optional options used to pass to the Transaction and State Store.
|
|
686
698
|
*
|
|
687
699
|
* @throws {BackchannelAuthenticationError} If there was an issue when doing backchannel authentication.
|
|
700
|
+
* @throws {SessionExpiredError} When the ID token's `session_expiry` is already in the past at login (the session is born expired); nothing is persisted.
|
|
688
701
|
*
|
|
689
702
|
* @returns A promise resolving to an object, containing the authorizationDetails (when RAR was used).
|
|
690
703
|
*/
|
|
@@ -954,8 +967,9 @@ declare abstract class AbstractSessionStore<TStoreOptions> extends AbstractState
|
|
|
954
967
|
constructor(options: SessionConfiguration & EncryptedStoreOptions);
|
|
955
968
|
/**
|
|
956
969
|
* calculateMaxAge calculates the max age of the session based on createdAt and the rolling and absolute durations.
|
|
970
|
+
* When sessionExpiresAt is provided, caps the maxAge to not exceed the time until that ceiling.
|
|
957
971
|
*/
|
|
958
|
-
protected calculateMaxAge(createdAt: number): number;
|
|
972
|
+
protected calculateMaxAge(createdAt: number, sessionExpiresAt?: number): number;
|
|
959
973
|
}
|
|
960
974
|
|
|
961
975
|
interface StatefulStateStoreOptions<TStoreOptions> extends EncryptedStoreOptions {
|
|
@@ -1030,5 +1044,13 @@ declare class IssuerValidationError extends Error {
|
|
|
1030
1044
|
code: string;
|
|
1031
1045
|
constructor(message: string);
|
|
1032
1046
|
}
|
|
1047
|
+
/**
|
|
1048
|
+
* Error thrown when the session has passed its upstream IdP-asserted
|
|
1049
|
+
* `session_expiry` ceiling (IPSIE SL1). The user must re-authenticate.
|
|
1050
|
+
*/
|
|
1051
|
+
declare class SessionExpiredError extends Error {
|
|
1052
|
+
code: string;
|
|
1053
|
+
constructor(message?: string);
|
|
1054
|
+
}
|
|
1033
1055
|
|
|
1034
|
-
export { type AbstractDataStore, AbstractStateStore, AbstractTransactionStore, type AccessTokenForConnectionOptions, type AuthorizationParameters, BackchannelLogoutError, type CompletePasswordlessEmailOptions, type CompletePasswordlessOptions, type CompletePasswordlessResult, type CompletePasswordlessSmsOptions, type ConnectionTokenSet, type CookieHandler, type CookieSerializeOptions, CookieTransactionStore, type CustomTokenExchangeOptions, type DomainResolver, type EncryptedStoreOptions, type GetAccessTokenOptions, type InternalStateData, InvalidConfigurationError, IssuerValidationError, type LoginBackchannelOptions, type LoginBackchannelResult, type LoginWithCustomTokenExchangeOptions, type LoginWithCustomTokenExchangeResult, type LogoutOptions, type LogoutTokenClaims, type MfaVerifyResponse, MissingRequiredArgumentError, MissingSessionError, MissingTransactionError, type PasskeyGetTokenResult, ServerClient, type ServerClientOptions, ServerMfaClient, ServerPasskeyClient, type SessionConfiguration, type SessionCookieOptions, type SessionData, type SessionStore, type StartInteractiveLoginOptions, StartLinkUserError, type StartLinkUserOptions, type StartPasswordlessEmailCodeOptions, type StartPasswordlessEmailLinkOptions, type StartPasswordlessOptions, type StartPasswordlessSmsOptions, type StartUnlinkUserOptions, type StateData, type StateStore, StatefulStateStore, type StatefulStateStoreOptions, StatelessStateStore, type TokenSet, type TransactionData, type TransactionStore, type UserClaims };
|
|
1056
|
+
export { type AbstractDataStore, AbstractStateStore, AbstractTransactionStore, type AccessTokenForConnectionOptions, type AuthorizationParameters, BackchannelLogoutError, type CompletePasswordlessEmailOptions, type CompletePasswordlessOptions, type CompletePasswordlessResult, type CompletePasswordlessSmsOptions, type ConnectionTokenSet, type CookieHandler, type CookieSerializeOptions, CookieTransactionStore, type CustomTokenExchangeOptions, type DomainResolver, type EncryptedStoreOptions, type GetAccessTokenOptions, type InternalStateData, InvalidConfigurationError, IssuerValidationError, type LoginBackchannelOptions, type LoginBackchannelResult, type LoginWithCustomTokenExchangeOptions, type LoginWithCustomTokenExchangeResult, type LogoutOptions, type LogoutTokenClaims, type MfaVerifyResponse, MissingRequiredArgumentError, MissingSessionError, MissingTransactionError, type PasskeyGetTokenResult, ServerClient, type ServerClientOptions, ServerMfaClient, ServerPasskeyClient, type SessionConfiguration, type SessionCookieOptions, type SessionData, SessionExpiredError, type SessionStore, type StartInteractiveLoginOptions, StartLinkUserError, type StartLinkUserOptions, type StartPasswordlessEmailCodeOptions, type StartPasswordlessEmailLinkOptions, type StartPasswordlessOptions, type StartPasswordlessSmsOptions, type StartUnlinkUserOptions, type StateData, type StateStore, StatefulStateStore, type StatefulStateStoreOptions, StatelessStateStore, type TokenSet, type TransactionData, type TransactionStore, type UserClaims };
|
package/dist/index.d.ts
CHANGED
|
@@ -92,6 +92,15 @@ interface SessionData {
|
|
|
92
92
|
tokenSets: TokenSet[];
|
|
93
93
|
connectionTokenSets?: ConnectionTokenSet[];
|
|
94
94
|
domain?: string;
|
|
95
|
+
/**
|
|
96
|
+
* IPSIE SL1 `session_expiry` ceiling for this session, as an absolute Unix timestamp in
|
|
97
|
+
* seconds. Present only when the user logged in through an enterprise connection configured
|
|
98
|
+
* with `id_token_session_expiry_supported: true`. When set, the SDK treats the session as
|
|
99
|
+
* expired once this time is reached (minus a small leeway) and forces re-authentication.
|
|
100
|
+
* Absent for database/social logins, connections without the option, and sessions created
|
|
101
|
+
* before this feature — those behave unchanged.
|
|
102
|
+
*/
|
|
103
|
+
sessionExpiresAt?: number;
|
|
95
104
|
[key: string]: unknown;
|
|
96
105
|
}
|
|
97
106
|
interface TransactionData {
|
|
@@ -619,6 +628,7 @@ declare class ServerClient<TStoreOptions = unknown> {
|
|
|
619
628
|
*
|
|
620
629
|
* @throws {MissingTransactionError} When no transaction was found.
|
|
621
630
|
* @throws {TokenByCodeError} If there was an issue requesting the access token.
|
|
631
|
+
* @throws {SessionExpiredError} When the ID token's `session_expiry` is already in the past at login (the session is born expired); nothing is persisted.
|
|
622
632
|
*
|
|
623
633
|
* @returns A promise resolving to an object, containing the original appState (if present) and the authorizationDetails (when RAR was used).
|
|
624
634
|
*/
|
|
@@ -633,6 +643,7 @@ declare class ServerClient<TStoreOptions = unknown> {
|
|
|
633
643
|
*
|
|
634
644
|
* @throws {MissingSessionError} If there is no active session.
|
|
635
645
|
* @throws {BuildLinkUserUrlError} If there was an issue when building the Authorization URL.
|
|
646
|
+
* @throws {SessionExpiredError} When the session's `session_expiry` ceiling has been reached; the session is cleared and re-authentication is required.
|
|
636
647
|
*
|
|
637
648
|
* @returns A promise resolving to a URL object, representing the URL to redirect the user-agent to to request authorization at Auth0.
|
|
638
649
|
*/
|
|
@@ -658,6 +669,7 @@ declare class ServerClient<TStoreOptions = unknown> {
|
|
|
658
669
|
*
|
|
659
670
|
* @throws {MissingSessionError} If there is no active session.
|
|
660
671
|
* @throws {BuildUnlinkUserUrlError} If there was an issue when building the User Unlinking URL.
|
|
672
|
+
* @throws {SessionExpiredError} When the session's `session_expiry` ceiling has been reached; the session is cleared and re-authentication is required.
|
|
661
673
|
*
|
|
662
674
|
* @returns A promise resolving to a URL object, representing the URL to redirect the user-agent to to request authorization at Auth0.
|
|
663
675
|
*/
|
|
@@ -685,6 +697,7 @@ declare class ServerClient<TStoreOptions = unknown> {
|
|
|
685
697
|
* @param storeOptions Optional options used to pass to the Transaction and State Store.
|
|
686
698
|
*
|
|
687
699
|
* @throws {BackchannelAuthenticationError} If there was an issue when doing backchannel authentication.
|
|
700
|
+
* @throws {SessionExpiredError} When the ID token's `session_expiry` is already in the past at login (the session is born expired); nothing is persisted.
|
|
688
701
|
*
|
|
689
702
|
* @returns A promise resolving to an object, containing the authorizationDetails (when RAR was used).
|
|
690
703
|
*/
|
|
@@ -954,8 +967,9 @@ declare abstract class AbstractSessionStore<TStoreOptions> extends AbstractState
|
|
|
954
967
|
constructor(options: SessionConfiguration & EncryptedStoreOptions);
|
|
955
968
|
/**
|
|
956
969
|
* calculateMaxAge calculates the max age of the session based on createdAt and the rolling and absolute durations.
|
|
970
|
+
* When sessionExpiresAt is provided, caps the maxAge to not exceed the time until that ceiling.
|
|
957
971
|
*/
|
|
958
|
-
protected calculateMaxAge(createdAt: number): number;
|
|
972
|
+
protected calculateMaxAge(createdAt: number, sessionExpiresAt?: number): number;
|
|
959
973
|
}
|
|
960
974
|
|
|
961
975
|
interface StatefulStateStoreOptions<TStoreOptions> extends EncryptedStoreOptions {
|
|
@@ -1030,5 +1044,13 @@ declare class IssuerValidationError extends Error {
|
|
|
1030
1044
|
code: string;
|
|
1031
1045
|
constructor(message: string);
|
|
1032
1046
|
}
|
|
1047
|
+
/**
|
|
1048
|
+
* Error thrown when the session has passed its upstream IdP-asserted
|
|
1049
|
+
* `session_expiry` ceiling (IPSIE SL1). The user must re-authenticate.
|
|
1050
|
+
*/
|
|
1051
|
+
declare class SessionExpiredError extends Error {
|
|
1052
|
+
code: string;
|
|
1053
|
+
constructor(message?: string);
|
|
1054
|
+
}
|
|
1033
1055
|
|
|
1034
|
-
export { type AbstractDataStore, AbstractStateStore, AbstractTransactionStore, type AccessTokenForConnectionOptions, type AuthorizationParameters, BackchannelLogoutError, type CompletePasswordlessEmailOptions, type CompletePasswordlessOptions, type CompletePasswordlessResult, type CompletePasswordlessSmsOptions, type ConnectionTokenSet, type CookieHandler, type CookieSerializeOptions, CookieTransactionStore, type CustomTokenExchangeOptions, type DomainResolver, type EncryptedStoreOptions, type GetAccessTokenOptions, type InternalStateData, InvalidConfigurationError, IssuerValidationError, type LoginBackchannelOptions, type LoginBackchannelResult, type LoginWithCustomTokenExchangeOptions, type LoginWithCustomTokenExchangeResult, type LogoutOptions, type LogoutTokenClaims, type MfaVerifyResponse, MissingRequiredArgumentError, MissingSessionError, MissingTransactionError, type PasskeyGetTokenResult, ServerClient, type ServerClientOptions, ServerMfaClient, ServerPasskeyClient, type SessionConfiguration, type SessionCookieOptions, type SessionData, type SessionStore, type StartInteractiveLoginOptions, StartLinkUserError, type StartLinkUserOptions, type StartPasswordlessEmailCodeOptions, type StartPasswordlessEmailLinkOptions, type StartPasswordlessOptions, type StartPasswordlessSmsOptions, type StartUnlinkUserOptions, type StateData, type StateStore, StatefulStateStore, type StatefulStateStoreOptions, StatelessStateStore, type TokenSet, type TransactionData, type TransactionStore, type UserClaims };
|
|
1056
|
+
export { type AbstractDataStore, AbstractStateStore, AbstractTransactionStore, type AccessTokenForConnectionOptions, type AuthorizationParameters, BackchannelLogoutError, type CompletePasswordlessEmailOptions, type CompletePasswordlessOptions, type CompletePasswordlessResult, type CompletePasswordlessSmsOptions, type ConnectionTokenSet, type CookieHandler, type CookieSerializeOptions, CookieTransactionStore, type CustomTokenExchangeOptions, type DomainResolver, type EncryptedStoreOptions, type GetAccessTokenOptions, type InternalStateData, InvalidConfigurationError, IssuerValidationError, type LoginBackchannelOptions, type LoginBackchannelResult, type LoginWithCustomTokenExchangeOptions, type LoginWithCustomTokenExchangeResult, type LogoutOptions, type LogoutTokenClaims, type MfaVerifyResponse, MissingRequiredArgumentError, MissingSessionError, MissingTransactionError, type PasskeyGetTokenResult, ServerClient, type ServerClientOptions, ServerMfaClient, ServerPasskeyClient, type SessionConfiguration, type SessionCookieOptions, type SessionData, SessionExpiredError, type SessionStore, type StartInteractiveLoginOptions, StartLinkUserError, type StartLinkUserOptions, type StartPasswordlessEmailCodeOptions, type StartPasswordlessEmailLinkOptions, type StartPasswordlessOptions, type StartPasswordlessSmsOptions, type StartUnlinkUserOptions, type StateData, type StateStore, StatefulStateStore, type StatefulStateStoreOptions, StatelessStateStore, type TokenSet, type TransactionData, type TransactionStore, type UserClaims };
|
package/dist/index.js
CHANGED
|
@@ -48,14 +48,55 @@ var IssuerValidationError = class extends Error {
|
|
|
48
48
|
this.name = "IssuerValidationError";
|
|
49
49
|
}
|
|
50
50
|
};
|
|
51
|
+
var SessionExpiredError = class extends Error {
|
|
52
|
+
code = "session_expired";
|
|
53
|
+
constructor(message) {
|
|
54
|
+
super(
|
|
55
|
+
message ?? "The session has expired because the upstream identity provider session ceiling was reached. The user needs to re-authenticate."
|
|
56
|
+
);
|
|
57
|
+
this.name = "SessionExpiredError";
|
|
58
|
+
}
|
|
59
|
+
};
|
|
51
60
|
|
|
52
61
|
// src/state/utils.ts
|
|
62
|
+
var SESSION_EXPIRY_LEEWAY = 30;
|
|
63
|
+
var MAX_PLAUSIBLE_UNIX_SECONDS = 1e10;
|
|
64
|
+
function isPlausibleUnixSeconds(value) {
|
|
65
|
+
return typeof value === "number" && Number.isInteger(value) && value > 0 && value < MAX_PLAUSIBLE_UNIX_SECONDS;
|
|
66
|
+
}
|
|
67
|
+
function extractSessionExpiry(claims) {
|
|
68
|
+
const value = claims?.session_expiry;
|
|
69
|
+
return isPlausibleUnixSeconds(value) ? value : void 0;
|
|
70
|
+
}
|
|
71
|
+
function isSessionExpiryReached(sessionExpiresAt, nowSeconds) {
|
|
72
|
+
if (sessionExpiresAt === void 0) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
const now = nowSeconds ?? Math.floor(Date.now() / 1e3);
|
|
76
|
+
return now >= sessionExpiresAt - SESSION_EXPIRY_LEEWAY;
|
|
77
|
+
}
|
|
53
78
|
var createUpdatedTokenSet = (audience, response) => ({
|
|
54
79
|
audience,
|
|
55
80
|
accessToken: response.accessToken,
|
|
56
81
|
scope: response.scope,
|
|
57
82
|
expiresAt: response.expiresAt
|
|
58
83
|
});
|
|
84
|
+
function isSessionExpiryInPast(sessionExpiresAt, issuedAt) {
|
|
85
|
+
if (sessionExpiresAt === void 0) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
const reference = isPlausibleUnixSeconds(issuedAt) ? issuedAt : Math.floor(Date.now() / 1e3);
|
|
89
|
+
return sessionExpiresAt <= reference + SESSION_EXPIRY_LEEWAY;
|
|
90
|
+
}
|
|
91
|
+
function applySessionExpiryAtLogin(stateData, claims) {
|
|
92
|
+
const sessionExpiresAt = extractSessionExpiry(claims);
|
|
93
|
+
if (isSessionExpiryInPast(sessionExpiresAt, claims?.iat)) {
|
|
94
|
+
throw new SessionExpiredError(
|
|
95
|
+
"The upstream identity provider session_expiry is at or before the issued-at time; refusing to create an already-expired session."
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
return { ...stateData, sessionExpiresAt };
|
|
99
|
+
}
|
|
59
100
|
function updateStateData(audience, stateData, tokenEndpointResponse, context) {
|
|
60
101
|
if (stateData && tokenEndpointResponse.claims) {
|
|
61
102
|
const newSub = tokenEndpointResponse.claims.sub;
|
|
@@ -163,7 +204,7 @@ function getTelemetryConfig(config) {
|
|
|
163
204
|
return {
|
|
164
205
|
enabled: true,
|
|
165
206
|
name: config?.name ?? "@auth0/auth0-server-js",
|
|
166
|
-
version: config?.version ?? "1.
|
|
207
|
+
version: config?.version ?? "1.8.0"
|
|
167
208
|
};
|
|
168
209
|
}
|
|
169
210
|
|
|
@@ -225,9 +266,12 @@ var ServerMfaClient = class {
|
|
|
225
266
|
this.#options.stateStoreIdentifier,
|
|
226
267
|
storeOptions
|
|
227
268
|
);
|
|
228
|
-
const updatedStateData =
|
|
229
|
-
|
|
230
|
-
|
|
269
|
+
const updatedStateData = applySessionExpiryAtLogin(
|
|
270
|
+
updateStateData(audience, existingStateData, tokenResponse, {
|
|
271
|
+
domain: this.#options.domain
|
|
272
|
+
}),
|
|
273
|
+
tokenResponse.claims
|
|
274
|
+
);
|
|
231
275
|
await this.#options.stateStore.set(
|
|
232
276
|
this.#options.stateStoreIdentifier,
|
|
233
277
|
updatedStateData,
|
|
@@ -553,6 +597,7 @@ var ServerClient = class {
|
|
|
553
597
|
*
|
|
554
598
|
* @throws {MissingTransactionError} When no transaction was found.
|
|
555
599
|
* @throws {TokenByCodeError} If there was an issue requesting the access token.
|
|
600
|
+
* @throws {SessionExpiredError} When the ID token's `session_expiry` is already in the past at login (the session is born expired); nothing is persisted.
|
|
556
601
|
*
|
|
557
602
|
* @returns A promise resolving to an object, containing the original appState (if present) and the authorizationDetails (when RAR was used).
|
|
558
603
|
*/
|
|
@@ -567,12 +612,15 @@ var ServerClient = class {
|
|
|
567
612
|
// TransactionData.codeVerifier is optional only to accommodate magic-link transactions.
|
|
568
613
|
codeVerifier: transactionData.codeVerifier
|
|
569
614
|
});
|
|
615
|
+
await this.#transactionStore.delete(this.#transactionStoreIdentifier, storeOptions);
|
|
570
616
|
const existingStateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
|
|
571
|
-
const stateData =
|
|
572
|
-
|
|
573
|
-
|
|
617
|
+
const stateData = applySessionExpiryAtLogin(
|
|
618
|
+
updateStateData(transactionData.audience ?? "default", existingStateData, tokenEndpointResponse, {
|
|
619
|
+
domain
|
|
620
|
+
}),
|
|
621
|
+
tokenEndpointResponse.claims
|
|
622
|
+
);
|
|
574
623
|
await this.#stateStore.set(this.#stateStoreIdentifier, stateData, true, storeOptions);
|
|
575
|
-
await this.#transactionStore.delete(this.#transactionStoreIdentifier, storeOptions);
|
|
576
624
|
return { appState: transactionData.appState, authorizationDetails: tokenEndpointResponse.authorizationDetails };
|
|
577
625
|
}
|
|
578
626
|
/**
|
|
@@ -582,6 +630,7 @@ var ServerClient = class {
|
|
|
582
630
|
*
|
|
583
631
|
* @throws {MissingSessionError} If there is no active session.
|
|
584
632
|
* @throws {BuildLinkUserUrlError} If there was an issue when building the Authorization URL.
|
|
633
|
+
* @throws {SessionExpiredError} When the session's `session_expiry` ceiling has been reached; the session is cleared and re-authentication is required.
|
|
585
634
|
*
|
|
586
635
|
* @returns A promise resolving to a URL object, representing the URL to redirect the user-agent to to request authorization at Auth0.
|
|
587
636
|
*/
|
|
@@ -598,6 +647,10 @@ var ServerClient = class {
|
|
|
598
647
|
throw new MissingSessionError("Session domain does not match the current domain.");
|
|
599
648
|
}
|
|
600
649
|
}
|
|
650
|
+
if (isSessionExpiryReached(stateData.sessionExpiresAt)) {
|
|
651
|
+
await this.#stateStore.delete(this.#stateStoreIdentifier, storeOptions);
|
|
652
|
+
throw new SessionExpiredError();
|
|
653
|
+
}
|
|
601
654
|
const domain = this.#getSessionDomain(stateData);
|
|
602
655
|
const authClient = this.#getAuthClient(domain);
|
|
603
656
|
const { linkUserUrl, codeVerifier } = await authClient.buildLinkUserUrl({
|
|
@@ -641,6 +694,7 @@ var ServerClient = class {
|
|
|
641
694
|
*
|
|
642
695
|
* @throws {MissingSessionError} If there is no active session.
|
|
643
696
|
* @throws {BuildUnlinkUserUrlError} If there was an issue when building the User Unlinking URL.
|
|
697
|
+
* @throws {SessionExpiredError} When the session's `session_expiry` ceiling has been reached; the session is cleared and re-authentication is required.
|
|
644
698
|
*
|
|
645
699
|
* @returns A promise resolving to a URL object, representing the URL to redirect the user-agent to to request authorization at Auth0.
|
|
646
700
|
*/
|
|
@@ -657,6 +711,10 @@ var ServerClient = class {
|
|
|
657
711
|
throw new MissingSessionError("Session domain does not match the current domain.");
|
|
658
712
|
}
|
|
659
713
|
}
|
|
714
|
+
if (isSessionExpiryReached(stateData.sessionExpiresAt)) {
|
|
715
|
+
await this.#stateStore.delete(this.#stateStoreIdentifier, storeOptions);
|
|
716
|
+
throw new SessionExpiredError();
|
|
717
|
+
}
|
|
660
718
|
const domain = this.#getSessionDomain(stateData);
|
|
661
719
|
const authClient = this.#getAuthClient(domain);
|
|
662
720
|
const { unlinkUserUrl, codeVerifier } = await authClient.buildUnlinkUserUrl({
|
|
@@ -701,6 +759,7 @@ var ServerClient = class {
|
|
|
701
759
|
* @param storeOptions Optional options used to pass to the Transaction and State Store.
|
|
702
760
|
*
|
|
703
761
|
* @throws {BackchannelAuthenticationError} If there was an issue when doing backchannel authentication.
|
|
762
|
+
* @throws {SessionExpiredError} When the ID token's `session_expiry` is already in the past at login (the session is born expired); nothing is persisted.
|
|
704
763
|
*
|
|
705
764
|
* @returns A promise resolving to an object, containing the authorizationDetails (when RAR was used).
|
|
706
765
|
*/
|
|
@@ -717,11 +776,11 @@ var ServerClient = class {
|
|
|
717
776
|
}
|
|
718
777
|
});
|
|
719
778
|
const existingStateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
|
|
720
|
-
const stateData =
|
|
721
|
-
this.#options.authorizationParams?.audience ?? "default",
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
779
|
+
const stateData = applySessionExpiryAtLogin(
|
|
780
|
+
updateStateData(this.#options.authorizationParams?.audience ?? "default", existingStateData, tokenEndpointResponse, {
|
|
781
|
+
domain
|
|
782
|
+
}),
|
|
783
|
+
tokenEndpointResponse.claims
|
|
725
784
|
);
|
|
726
785
|
await this.#stateStore.set(this.#stateStoreIdentifier, stateData, true, storeOptions);
|
|
727
786
|
return {
|
|
@@ -916,6 +975,10 @@ var ServerClient = class {
|
|
|
916
975
|
return;
|
|
917
976
|
}
|
|
918
977
|
}
|
|
978
|
+
if (isSessionExpiryReached(stateData.sessionExpiresAt)) {
|
|
979
|
+
await this.#stateStore.delete(this.#stateStoreIdentifier, storeOptions);
|
|
980
|
+
return;
|
|
981
|
+
}
|
|
919
982
|
return stateData.user;
|
|
920
983
|
}
|
|
921
984
|
/**
|
|
@@ -932,6 +995,10 @@ var ServerClient = class {
|
|
|
932
995
|
return;
|
|
933
996
|
}
|
|
934
997
|
}
|
|
998
|
+
if (isSessionExpiryReached(stateData.sessionExpiresAt)) {
|
|
999
|
+
await this.#stateStore.delete(this.#stateStoreIdentifier, storeOptions);
|
|
1000
|
+
return;
|
|
1001
|
+
}
|
|
935
1002
|
const { internal, ...sessionData } = stateData;
|
|
936
1003
|
return sessionData;
|
|
937
1004
|
}
|
|
@@ -948,6 +1015,7 @@ var ServerClient = class {
|
|
|
948
1015
|
* @param storeOptions Optional options used to pass to the Transaction and State Store.
|
|
949
1016
|
*
|
|
950
1017
|
* @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`.
|
|
1018
|
+
* @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.
|
|
951
1019
|
*
|
|
952
1020
|
* @returns The Token Set, containing the access token, as well as additional information.
|
|
953
1021
|
*/
|
|
@@ -975,6 +1043,10 @@ var ServerClient = class {
|
|
|
975
1043
|
throw new MissingSessionError("Session domain does not match the current domain.");
|
|
976
1044
|
}
|
|
977
1045
|
}
|
|
1046
|
+
if (stateData && isSessionExpiryReached(stateData.sessionExpiresAt)) {
|
|
1047
|
+
await this.#stateStore.delete(this.#stateStoreIdentifier, resolvedStoreOptions);
|
|
1048
|
+
throw new SessionExpiredError();
|
|
1049
|
+
}
|
|
978
1050
|
const tokenSet = stateData?.tokenSets.find(
|
|
979
1051
|
(tokenSet2) => tokenSet2.audience === audience && (!scope || compareScopes(tokenSet2.scope, scope))
|
|
980
1052
|
);
|
|
@@ -1349,14 +1421,14 @@ var AbstractSessionStore = class extends AbstractStateStore {
|
|
|
1349
1421
|
}
|
|
1350
1422
|
/**
|
|
1351
1423
|
* calculateMaxAge calculates the max age of the session based on createdAt and the rolling and absolute durations.
|
|
1424
|
+
* When sessionExpiresAt is provided, caps the maxAge to not exceed the time until that ceiling.
|
|
1352
1425
|
*/
|
|
1353
|
-
calculateMaxAge(createdAt) {
|
|
1354
|
-
if (!this.#rolling) {
|
|
1355
|
-
return this.#absoluteDuration;
|
|
1356
|
-
}
|
|
1426
|
+
calculateMaxAge(createdAt, sessionExpiresAt) {
|
|
1357
1427
|
const now = Date.now() / 1e3 | 0;
|
|
1358
|
-
|
|
1359
|
-
|
|
1428
|
+
let maxAge = this.#rolling ? Math.min(now + this.#inactivityDuration, createdAt + this.#absoluteDuration) - now : this.#absoluteDuration;
|
|
1429
|
+
if (sessionExpiresAt !== void 0) {
|
|
1430
|
+
maxAge = Math.min(maxAge, sessionExpiresAt - now);
|
|
1431
|
+
}
|
|
1360
1432
|
return maxAge > 0 ? maxAge : 0;
|
|
1361
1433
|
}
|
|
1362
1434
|
};
|
|
@@ -1384,7 +1456,7 @@ var StatefulStateStore = class extends AbstractSessionStore {
|
|
|
1384
1456
|
sessionId = generateId();
|
|
1385
1457
|
}
|
|
1386
1458
|
sessionId ??= generateId();
|
|
1387
|
-
const maxAge = this.calculateMaxAge(stateData.internal.createdAt);
|
|
1459
|
+
const maxAge = this.calculateMaxAge(stateData.internal.createdAt, stateData.sessionExpiresAt);
|
|
1388
1460
|
const cookieOpts = this.#getCookieOptions({
|
|
1389
1461
|
maxAge
|
|
1390
1462
|
});
|
|
@@ -1449,7 +1521,7 @@ var StatelessStateStore = class extends AbstractSessionStore {
|
|
|
1449
1521
|
this.#cookieHandler = cookieHandler;
|
|
1450
1522
|
}
|
|
1451
1523
|
async set(identifier, stateData, removeIfExists, options) {
|
|
1452
|
-
const maxAge = this.calculateMaxAge(stateData.internal.createdAt);
|
|
1524
|
+
const maxAge = this.calculateMaxAge(stateData.internal.createdAt, stateData.sessionExpiresAt);
|
|
1453
1525
|
const cookieOpts = this.#getCookieOptions({
|
|
1454
1526
|
maxAge
|
|
1455
1527
|
});
|
|
@@ -1543,6 +1615,7 @@ export {
|
|
|
1543
1615
|
ServerClient,
|
|
1544
1616
|
ServerMfaClient,
|
|
1545
1617
|
ServerPasskeyClient,
|
|
1618
|
+
SessionExpiredError,
|
|
1546
1619
|
StartLinkUserError,
|
|
1547
1620
|
StatefulStateStore,
|
|
1548
1621
|
StatelessStateStore,
|