@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.cjs +129 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +48 -13
- package/dist/index.d.ts +48 -13
- package/dist/index.js +129 -29
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
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
|
-
|
|
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
|
-
|
|
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,
|
|
46
|
-
if (
|
|
47
|
-
const isNewTokenSet = !
|
|
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 ? [...
|
|
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
|
-
...
|
|
55
|
-
idToken: tokenEndpointResponse.idToken,
|
|
56
|
-
refreshToken: tokenEndpointResponse.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,
|
|
76
|
-
|
|
77
|
-
const isNewTokenSet = !
|
|
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 ? [...
|
|
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
|
-
...
|
|
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:
|
|
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
|
|
369
|
-
|
|
370
|
-
|
|
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
|
|
383
|
-
refreshToken: stateData.refreshToken
|
|
384
|
-
|
|
385
|
-
|
|
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,
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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,
|