@auth0/auth0-server-js 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +428 -0
- package/dist/index.cjs +558 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +333 -0
- package/dist/index.d.ts +333 -0
- package/dist/index.js +528 -0
- package/dist/index.js.map +1 -0
- package/package.json +54 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,558 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
AbstractStateStore: () => AbstractStateStore,
|
|
24
|
+
AbstractTransactionStore: () => AbstractTransactionStore,
|
|
25
|
+
BackchannelLogoutError: () => BackchannelLogoutError,
|
|
26
|
+
MissingRequiredArgumentError: () => MissingRequiredArgumentError,
|
|
27
|
+
MissingSessionError: () => MissingSessionError,
|
|
28
|
+
MissingTransactionError: () => MissingTransactionError,
|
|
29
|
+
ServerClient: () => ServerClient,
|
|
30
|
+
StartLinkUserError: () => StartLinkUserError
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(index_exports);
|
|
33
|
+
|
|
34
|
+
// src/errors.ts
|
|
35
|
+
var MissingTransactionError = class extends Error {
|
|
36
|
+
code = "missing_transaction_error";
|
|
37
|
+
constructor(message) {
|
|
38
|
+
super(message ?? "The transaction is missing.");
|
|
39
|
+
this.name = "MissingTransactionError";
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
var BackchannelLogoutError = class extends Error {
|
|
43
|
+
code = "backchannel_logout_error";
|
|
44
|
+
constructor(message) {
|
|
45
|
+
super(message);
|
|
46
|
+
this.name = "BackchannelLogoutError";
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
var StartLinkUserError = class extends Error {
|
|
50
|
+
code = "start_link_user_error";
|
|
51
|
+
constructor(message) {
|
|
52
|
+
super(message);
|
|
53
|
+
this.name = "StartLinkUserError";
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
var MissingRequiredArgumentError = class extends Error {
|
|
57
|
+
code = "missing_required_argument_error";
|
|
58
|
+
constructor(argument) {
|
|
59
|
+
super(`The argument '${argument}' is required but was not provided.`);
|
|
60
|
+
this.name = "MissingRequiredArgumentError";
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
var MissingSessionError = class extends Error {
|
|
64
|
+
code = "missing_session_error";
|
|
65
|
+
constructor(message) {
|
|
66
|
+
super(message);
|
|
67
|
+
this.name = "MissingSessionError";
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// src/state/utils.ts
|
|
72
|
+
function updateStateData(audience, stateDate, tokenEndpointResponse) {
|
|
73
|
+
if (stateDate) {
|
|
74
|
+
const isNewTokenSet = !stateDate.tokenSets.some(
|
|
75
|
+
(tokenSet) => tokenSet.audience === audience && tokenSet.scope === tokenEndpointResponse.scope
|
|
76
|
+
);
|
|
77
|
+
const createUpdatedTokenSet = (response) => ({
|
|
78
|
+
audience,
|
|
79
|
+
accessToken: response.accessToken,
|
|
80
|
+
scope: response.scope,
|
|
81
|
+
expiresAt: Math.floor(Date.now() / 1e3) + Number(response.expiresAt)
|
|
82
|
+
});
|
|
83
|
+
const tokenSets = isNewTokenSet ? [...stateDate.tokenSets, createUpdatedTokenSet(tokenEndpointResponse)] : stateDate.tokenSets.map(
|
|
84
|
+
(tokenSet) => tokenSet.audience === audience && tokenSet.scope === tokenEndpointResponse.scope ? createUpdatedTokenSet(tokenEndpointResponse) : tokenSet
|
|
85
|
+
);
|
|
86
|
+
return {
|
|
87
|
+
...stateDate,
|
|
88
|
+
idToken: tokenEndpointResponse.idToken,
|
|
89
|
+
refreshToken: tokenEndpointResponse.refreshToken ?? stateDate.refreshToken,
|
|
90
|
+
tokenSets
|
|
91
|
+
};
|
|
92
|
+
} else {
|
|
93
|
+
const user = tokenEndpointResponse.claims;
|
|
94
|
+
return {
|
|
95
|
+
user,
|
|
96
|
+
idToken: tokenEndpointResponse.idToken,
|
|
97
|
+
refreshToken: tokenEndpointResponse.refreshToken,
|
|
98
|
+
tokenSets: [
|
|
99
|
+
{
|
|
100
|
+
audience,
|
|
101
|
+
accessToken: tokenEndpointResponse.accessToken,
|
|
102
|
+
scope: tokenEndpointResponse.scope,
|
|
103
|
+
expiresAt: tokenEndpointResponse.expiresAt
|
|
104
|
+
}
|
|
105
|
+
],
|
|
106
|
+
internal: {
|
|
107
|
+
sid: user?.sid,
|
|
108
|
+
createdAt: Math.floor(Date.now() / 1e3)
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function updateStateDataForConnectionTokenSet(options, stateDate, tokenEndpointResponse) {
|
|
114
|
+
stateDate.connectionTokenSets = stateDate.connectionTokenSets || [];
|
|
115
|
+
const isNewTokenSet = !stateDate.connectionTokenSets.some(
|
|
116
|
+
(tokenSet) => tokenSet.connection === options.connection && (!options.loginHint || tokenSet.loginHint === options.loginHint)
|
|
117
|
+
);
|
|
118
|
+
const connectionTokenSet = {
|
|
119
|
+
connection: options.connection,
|
|
120
|
+
loginHint: options.loginHint,
|
|
121
|
+
accessToken: tokenEndpointResponse.accessToken,
|
|
122
|
+
scope: tokenEndpointResponse.scope,
|
|
123
|
+
expiresAt: tokenEndpointResponse.expiresAt
|
|
124
|
+
};
|
|
125
|
+
const connectionTokenSets = isNewTokenSet ? [...stateDate.connectionTokenSets, connectionTokenSet] : stateDate.connectionTokenSets.map(
|
|
126
|
+
(tokenSet) => tokenSet.connection === options.connection && (!options.loginHint || tokenSet.loginHint === options.loginHint) ? connectionTokenSet : tokenSet
|
|
127
|
+
);
|
|
128
|
+
return {
|
|
129
|
+
...stateDate,
|
|
130
|
+
connectionTokenSets
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// src/server-client.ts
|
|
135
|
+
var import_auth0_auth_js = require("@auth0/auth0-auth-js");
|
|
136
|
+
var ServerClient = class {
|
|
137
|
+
#options;
|
|
138
|
+
#transactionStore;
|
|
139
|
+
#transactionStoreIdentifier;
|
|
140
|
+
#stateStore;
|
|
141
|
+
#stateStoreIdentifier;
|
|
142
|
+
#authClient;
|
|
143
|
+
constructor(options) {
|
|
144
|
+
this.#options = options;
|
|
145
|
+
this.#stateStoreIdentifier = this.#options.stateIdentifier || "__a0_session";
|
|
146
|
+
this.#transactionStoreIdentifier = this.#options.transactionIdentifier || "__a0_tx";
|
|
147
|
+
this.#transactionStore = options.transactionStore;
|
|
148
|
+
this.#stateStore = options.stateStore;
|
|
149
|
+
if (!this.#options.stateStore) {
|
|
150
|
+
throw new MissingRequiredArgumentError("stateStore");
|
|
151
|
+
}
|
|
152
|
+
if (!this.#options.transactionStore) {
|
|
153
|
+
throw new MissingRequiredArgumentError("transactionStore");
|
|
154
|
+
}
|
|
155
|
+
this.#authClient = new import_auth0_auth_js.AuthClient({
|
|
156
|
+
domain: this.#options.domain,
|
|
157
|
+
clientId: this.#options.clientId,
|
|
158
|
+
clientSecret: this.#options.clientSecret,
|
|
159
|
+
clientAssertionSigningKey: this.#options.clientAssertionSigningKey,
|
|
160
|
+
clientAssertionSigningAlg: this.#options.clientAssertionSigningAlg,
|
|
161
|
+
authorizationParams: this.#options.authorizationParams,
|
|
162
|
+
customFetch: this.#options.customFetch
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Starts the interactive login process, and returns a URL to redirect the user-agent to to request authorization at Auth0.
|
|
167
|
+
* @param options Optional options used to configure the interactive login process.
|
|
168
|
+
* @param storeOptions Optional options used to pass to the Transaction and State Store.
|
|
169
|
+
*
|
|
170
|
+
* @throws {BuildAuthorizationUrlError} If there was an issue when building the Authorization URL.
|
|
171
|
+
*
|
|
172
|
+
* @returns A promise resolving to a URL object, representing the URL to redirect the user-agent to to request authorization at Auth0.
|
|
173
|
+
*/
|
|
174
|
+
async startInteractiveLogin(options, storeOptions) {
|
|
175
|
+
const redirectUri = options?.authorizationParams?.redirect_uri ?? this.#options.authorizationParams?.redirect_uri;
|
|
176
|
+
if (!redirectUri) {
|
|
177
|
+
throw new MissingRequiredArgumentError("authorizationParams.redirect_uri");
|
|
178
|
+
}
|
|
179
|
+
const { codeVerifier, authorizationUrl } = await this.#authClient.buildAuthorizationUrl({
|
|
180
|
+
pushedAuthorizationRequests: options?.pushedAuthorizationRequests,
|
|
181
|
+
authorizationParams: {
|
|
182
|
+
...options?.authorizationParams,
|
|
183
|
+
redirect_uri: redirectUri
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
const transactionState = {
|
|
187
|
+
audience: options?.authorizationParams?.audience ?? this.#options.authorizationParams?.audience,
|
|
188
|
+
codeVerifier
|
|
189
|
+
};
|
|
190
|
+
if (options?.appState) {
|
|
191
|
+
transactionState.appState = options.appState;
|
|
192
|
+
}
|
|
193
|
+
await this.#transactionStore.set(this.#transactionStoreIdentifier, transactionState, false, storeOptions);
|
|
194
|
+
return authorizationUrl;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Completes the interactive login process.
|
|
198
|
+
* Takes an URL, extract the Authorization Code flow query parameters and requests a token.
|
|
199
|
+
* @param url The URl from which the query params should be extracted to exchange for a token.
|
|
200
|
+
* @param storeOptions Optional options used to pass to the Transaction and State Store.
|
|
201
|
+
*
|
|
202
|
+
* @throws {MissingTransactionError} When no transaction was found.
|
|
203
|
+
* @throws {TokenByCodeError} If there was an issue requesting the access token.
|
|
204
|
+
*
|
|
205
|
+
* @returns A promise resolving to an object, containing the original appState (if present) and the authorizationDetails (when RAR was used).
|
|
206
|
+
*/
|
|
207
|
+
async completeInteractiveLogin(url, storeOptions) {
|
|
208
|
+
const transactionData = await this.#transactionStore.get(this.#transactionStoreIdentifier, storeOptions);
|
|
209
|
+
if (!transactionData) {
|
|
210
|
+
throw new MissingTransactionError();
|
|
211
|
+
}
|
|
212
|
+
const tokenEndpointResponse = await this.#authClient.getTokenByCode(url, {
|
|
213
|
+
codeVerifier: transactionData.codeVerifier
|
|
214
|
+
});
|
|
215
|
+
const existingStateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
|
|
216
|
+
const stateData = updateStateData(transactionData.audience ?? "default", existingStateData, tokenEndpointResponse);
|
|
217
|
+
await this.#stateStore.set(this.#stateStoreIdentifier, stateData, true, storeOptions);
|
|
218
|
+
await this.#transactionStore.delete(this.#transactionStoreIdentifier, storeOptions);
|
|
219
|
+
return { appState: transactionData.appState, authorizationDetails: tokenEndpointResponse.authorizationDetails };
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Starts the user linking process, and returns a URL to redirect the user-agent to to request authorization at Auth0.
|
|
223
|
+
* @param options Options used to configure the user linking process.
|
|
224
|
+
* @param storeOptions Optional options used to pass to the Transaction and State Store.
|
|
225
|
+
*
|
|
226
|
+
* @throws {MissingSessionError} If there is no active session.
|
|
227
|
+
* @throws {BuildLinkUserUrlError} If there was an issue when building the Authorization URL.
|
|
228
|
+
*
|
|
229
|
+
* @returns A promise resolving to a URL object, representing the URL to redirect the user-agent to to request authorization at Auth0.
|
|
230
|
+
*/
|
|
231
|
+
async startLinkUser(options, storeOptions) {
|
|
232
|
+
const stateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
|
|
233
|
+
if (!stateData || !stateData.idToken) {
|
|
234
|
+
throw new MissingSessionError(
|
|
235
|
+
"Unable to start the user linking process without a logged in user. Ensure to login using the SDK before starting the user linking process."
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
const { linkUserUrl, codeVerifier } = await this.#authClient.buildLinkUserUrl({
|
|
239
|
+
connection: options.connection,
|
|
240
|
+
connectionScope: options.connectionScope,
|
|
241
|
+
idToken: stateData.idToken,
|
|
242
|
+
authorizationParams: options.authorizationParams
|
|
243
|
+
});
|
|
244
|
+
const transactionState = {
|
|
245
|
+
audience: options?.authorizationParams?.audience ?? this.#options.authorizationParams?.audience,
|
|
246
|
+
codeVerifier
|
|
247
|
+
};
|
|
248
|
+
if (options?.appState) {
|
|
249
|
+
transactionState.appState = options.appState;
|
|
250
|
+
}
|
|
251
|
+
await this.#transactionStore.set(this.#transactionStoreIdentifier, transactionState, false, storeOptions);
|
|
252
|
+
return linkUserUrl;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Completes the user linking process.
|
|
256
|
+
* Takes an URL, extract the Authorization Code flow query parameters and requests a token.
|
|
257
|
+
* @param url The URl from which the query params should be extracted to exchange for a token.
|
|
258
|
+
* @param storeOptions Optional options used to pass to the Transaction and State Store.
|
|
259
|
+
*
|
|
260
|
+
* @throws {MissingTransactionError} When no transaction was found.
|
|
261
|
+
* @throws {TokenByCodeError} If there was an issue requesting the access token.
|
|
262
|
+
*
|
|
263
|
+
* @returns A promise resolving to an object, containing the original appState (if present).
|
|
264
|
+
*/
|
|
265
|
+
async completeLinkUser(url, storeOptions) {
|
|
266
|
+
const result = await this.completeInteractiveLogin(url, storeOptions);
|
|
267
|
+
return {
|
|
268
|
+
appState: result.appState
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Starts the user unlinking process, and returns a URL to redirect the user-agent to to initialize user unlinking at Auth0.
|
|
273
|
+
* @param options Options used to configure the user unlinking process.
|
|
274
|
+
* @param storeOptions Optional options used to pass to the Transaction and State Store.
|
|
275
|
+
*
|
|
276
|
+
* @throws {MissingSessionError} If there is no active session.
|
|
277
|
+
* @throws {BuildUnlinkUserUrlError} If there was an issue when building the User Unlinking URL.
|
|
278
|
+
*
|
|
279
|
+
* @returns A promise resolving to a URL object, representing the URL to redirect the user-agent to to request authorization at Auth0.
|
|
280
|
+
*/
|
|
281
|
+
async startUnlinkUser(options, storeOptions) {
|
|
282
|
+
const stateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
|
|
283
|
+
if (!stateData || !stateData.idToken) {
|
|
284
|
+
throw new MissingSessionError(
|
|
285
|
+
"Unable to start the user unlinking process without a logged in user. Ensure to login using the SDK before starting the user unlinking process."
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
const { unlinkUserUrl, codeVerifier } = await this.#authClient.buildUnlinkUserUrl({
|
|
289
|
+
connection: options.connection,
|
|
290
|
+
idToken: stateData.idToken,
|
|
291
|
+
authorizationParams: options.authorizationParams
|
|
292
|
+
});
|
|
293
|
+
const transactionState = {
|
|
294
|
+
audience: options?.authorizationParams?.audience ?? this.#options.authorizationParams?.audience,
|
|
295
|
+
codeVerifier
|
|
296
|
+
};
|
|
297
|
+
if (options?.appState) {
|
|
298
|
+
transactionState.appState = options.appState;
|
|
299
|
+
}
|
|
300
|
+
await this.#transactionStore.set(this.#transactionStoreIdentifier, transactionState, false, storeOptions);
|
|
301
|
+
return unlinkUserUrl;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Completes the user unlinking process.
|
|
305
|
+
* Takes an URL, extract the Authorization Code flow query parameters and requests a token.
|
|
306
|
+
* @param url The URl from which the query params should be extracted to exchange for a token.
|
|
307
|
+
* @param storeOptions Optional options used to pass to the Transaction and State Store.
|
|
308
|
+
*
|
|
309
|
+
* @throws {MissingTransactionError} When no transaction was found.
|
|
310
|
+
* @throws {TokenByCodeError} If there was an issue requesting the access token.
|
|
311
|
+
*
|
|
312
|
+
* @returns A promise resolving to an object, containing the original appState (if present).
|
|
313
|
+
*/
|
|
314
|
+
async completeUnlinkUser(url, storeOptions) {
|
|
315
|
+
const result = await this.completeInteractiveLogin(url, storeOptions);
|
|
316
|
+
return {
|
|
317
|
+
appState: result.appState
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Logs in using Client-Initiated Backchannel Authentication.
|
|
322
|
+
*
|
|
323
|
+
* Using Client-Initiated Backchannel Authentication requires the feature to be enabled in the Auth0 dashboard.
|
|
324
|
+
* @see https://auth0.com/docs/get-started/authentication-and-authorization-flow/client-initiated-backchannel-authentication-flow
|
|
325
|
+
* @param options Options used to configure the backchannel login process.
|
|
326
|
+
* @param storeOptions Optional options used to pass to the Transaction and State Store.
|
|
327
|
+
*
|
|
328
|
+
* @throws {BackchannelAuthenticationError} If there was an issue when doing backchannel authentication.
|
|
329
|
+
*
|
|
330
|
+
* @returns A promise resolving to an object, containing the authorizationDetails (when RAR was used).
|
|
331
|
+
*/
|
|
332
|
+
async loginBackchannel(options, storeOptions) {
|
|
333
|
+
const tokenEndpointResponse = await this.#authClient.backchannelAuthentication({
|
|
334
|
+
bindingMessage: options.bindingMessage,
|
|
335
|
+
loginHint: options.loginHint,
|
|
336
|
+
authorizationParams: options.authorizationParams
|
|
337
|
+
});
|
|
338
|
+
const existingStateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
|
|
339
|
+
const stateData = updateStateData(
|
|
340
|
+
this.#options.authorizationParams?.audience ?? "default",
|
|
341
|
+
existingStateData,
|
|
342
|
+
tokenEndpointResponse
|
|
343
|
+
);
|
|
344
|
+
await this.#stateStore.set(this.#stateStoreIdentifier, stateData, true, storeOptions);
|
|
345
|
+
return {
|
|
346
|
+
authorizationDetails: tokenEndpointResponse.authorizationDetails
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Retrieves the user from the store, or undefined if no user found.
|
|
351
|
+
* @param storeOptions Optional options used to pass to the Transaction and State Store.
|
|
352
|
+
* @returns The user, or undefined if no user found in the store.
|
|
353
|
+
*/
|
|
354
|
+
async getUser(storeOptions) {
|
|
355
|
+
const stateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
|
|
356
|
+
return stateData?.user;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Retrieve the user session from the store, or undefined if no session found.
|
|
360
|
+
* @param storeOptions Optional options used to pass to the Transaction and State Store.
|
|
361
|
+
* @returns The sessionm or undefined if no session found in the store.
|
|
362
|
+
*/
|
|
363
|
+
async getSession(storeOptions) {
|
|
364
|
+
const stateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
|
|
365
|
+
if (stateData) {
|
|
366
|
+
const { internal, ...sessionData } = stateData;
|
|
367
|
+
return sessionData;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* 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.
|
|
372
|
+
* Also updates the store when a new token was retrieved from Auth0.
|
|
373
|
+
* @param storeOptions Optional options used to pass to the Transaction and State Store.
|
|
374
|
+
*
|
|
375
|
+
* @throws {TokenByRefreshTokenError} If the refresh token was not found or there was an issue requesting the access token.
|
|
376
|
+
*
|
|
377
|
+
* @returns The Token Set, containing the access token, as well as additional information.
|
|
378
|
+
*/
|
|
379
|
+
async getAccessToken(storeOptions) {
|
|
380
|
+
const stateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
|
|
381
|
+
const audience = this.#options.authorizationParams?.audience ?? "default";
|
|
382
|
+
const scope = this.#options.authorizationParams?.scope;
|
|
383
|
+
const tokenSet = stateData?.tokenSets.find(
|
|
384
|
+
(tokenSet2) => tokenSet2.audience === audience && (!scope || tokenSet2.scope === scope)
|
|
385
|
+
);
|
|
386
|
+
if (tokenSet && tokenSet.expiresAt > Date.now() / 1e3) {
|
|
387
|
+
return tokenSet;
|
|
388
|
+
}
|
|
389
|
+
if (!stateData?.refreshToken) {
|
|
390
|
+
throw new import_auth0_auth_js.TokenByRefreshTokenError(
|
|
391
|
+
"The access token has expired and a refresh token was not provided. The user needs to re-authenticate."
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
const tokenEndpointResponse = await this.#authClient.getTokenByRefreshToken({
|
|
395
|
+
refreshToken: stateData.refreshToken
|
|
396
|
+
});
|
|
397
|
+
const existingStateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
|
|
398
|
+
const updatedStateData = updateStateData(audience, existingStateData, tokenEndpointResponse);
|
|
399
|
+
await this.#stateStore.set(this.#stateStoreIdentifier, updatedStateData, false, storeOptions);
|
|
400
|
+
return {
|
|
401
|
+
accessToken: tokenEndpointResponse.accessToken,
|
|
402
|
+
scope: tokenEndpointResponse.scope,
|
|
403
|
+
expiresAt: tokenEndpointResponse.expiresAt,
|
|
404
|
+
audience
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Retrieves an access token for a connection.
|
|
409
|
+
*
|
|
410
|
+
* This method attempts to obtain an access token for a specified connection.
|
|
411
|
+
* It first checks if a refresh token exists in the store.
|
|
412
|
+
* If no refresh token is found, it throws an `AccessTokenForConnectionError` indicating
|
|
413
|
+
* that the refresh token was not found.
|
|
414
|
+
*
|
|
415
|
+
* @param options - Options for retrieving an access token for a connection.
|
|
416
|
+
* @param storeOptions Optional options used to pass to the Transaction and State Store.
|
|
417
|
+
*
|
|
418
|
+
* @throws {TokenForConnectionError} If the refresh token was not found or there was an issue requesting the access token.
|
|
419
|
+
*
|
|
420
|
+
* @returns The Connection Token Set, containing the access token for the connection, as well as additional information.
|
|
421
|
+
*/
|
|
422
|
+
async getAccessTokenForConnection(options, storeOptions) {
|
|
423
|
+
const stateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);
|
|
424
|
+
const connectionTokenSet = stateData?.connectionTokenSets?.find(
|
|
425
|
+
(tokenSet) => tokenSet.connection === options.connection
|
|
426
|
+
);
|
|
427
|
+
if (connectionTokenSet && connectionTokenSet.expiresAt > Date.now() / 1e3) {
|
|
428
|
+
return connectionTokenSet;
|
|
429
|
+
}
|
|
430
|
+
if (!stateData?.refreshToken) {
|
|
431
|
+
throw new import_auth0_auth_js.TokenForConnectionError(
|
|
432
|
+
"A refresh token was not found but is required to be able to retrieve an access token for a connection."
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
const tokenEndpointResponse = await this.#authClient.getTokenForConnection({
|
|
436
|
+
connection: options.connection,
|
|
437
|
+
loginHint: options.loginHint,
|
|
438
|
+
refreshToken: stateData.refreshToken
|
|
439
|
+
});
|
|
440
|
+
const updatedStateData = updateStateDataForConnectionTokenSet(options, stateData, tokenEndpointResponse);
|
|
441
|
+
await this.#stateStore.set(this.#stateStoreIdentifier, updatedStateData, false, storeOptions);
|
|
442
|
+
return {
|
|
443
|
+
accessToken: tokenEndpointResponse.accessToken,
|
|
444
|
+
scope: tokenEndpointResponse.scope,
|
|
445
|
+
expiresAt: tokenEndpointResponse.expiresAt,
|
|
446
|
+
connection: options.connection,
|
|
447
|
+
loginHint: options.loginHint
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Logs the user out and returns a URL to redirect the user-agent to after they log out.
|
|
452
|
+
* @param options Options used to configure the logout process.
|
|
453
|
+
* @param storeOptions Optional options used to pass to the Transaction and State Store.
|
|
454
|
+
* @returns {URL}
|
|
455
|
+
*/
|
|
456
|
+
async logout(options, storeOptions) {
|
|
457
|
+
await this.#stateStore.delete(this.#stateStoreIdentifier, storeOptions);
|
|
458
|
+
return this.#authClient.buildLogoutUrl(options);
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Handles the backchannel logout process by verifying the logout token and deleting the session from the store if the logout token was considered valid.
|
|
462
|
+
* @param logoutToken The logout token to verify and use to delete the session from the store.
|
|
463
|
+
* @param storeOptions Optional options used to pass to the Transaction and State Store.
|
|
464
|
+
*
|
|
465
|
+
* @throws {BackchannelLogoutError} If the logout token is missing.
|
|
466
|
+
* @throws {VerifyLogoutTokenError} If the logout token is invalid.
|
|
467
|
+
*/
|
|
468
|
+
async handleBackchannelLogout(logoutToken, storeOptions) {
|
|
469
|
+
if (!logoutToken) {
|
|
470
|
+
throw new BackchannelLogoutError("Missing Logout Token");
|
|
471
|
+
}
|
|
472
|
+
const logoutTokenClaims = await this.#authClient.verifyLogoutToken({ logoutToken });
|
|
473
|
+
await this.#stateStore.deleteByLogoutToken(logoutTokenClaims, storeOptions);
|
|
474
|
+
}
|
|
475
|
+
};
|
|
476
|
+
|
|
477
|
+
// src/encryption/index.ts
|
|
478
|
+
var import_jose = require("jose");
|
|
479
|
+
var ENC = "A256CBC-HS512";
|
|
480
|
+
var ALG = "dir";
|
|
481
|
+
var DIGEST = "SHA-256";
|
|
482
|
+
var BIT_LENGTH = 512;
|
|
483
|
+
var HKDF_INFO = "derived cookie encryption secret";
|
|
484
|
+
var encoder;
|
|
485
|
+
async function deriveEncryptionSecret(secret, salt, kid) {
|
|
486
|
+
encoder ||= new TextEncoder();
|
|
487
|
+
const key = await crypto.subtle.importKey("raw", encoder.encode(secret), "HKDF", false, ["deriveBits"]);
|
|
488
|
+
return new Uint8Array(
|
|
489
|
+
await crypto.subtle.deriveBits(
|
|
490
|
+
{
|
|
491
|
+
name: "HKDF",
|
|
492
|
+
hash: DIGEST,
|
|
493
|
+
info: encoder.encode(HKDF_INFO),
|
|
494
|
+
salt: encoder.encode(`${salt}${kid}`)
|
|
495
|
+
},
|
|
496
|
+
key,
|
|
497
|
+
BIT_LENGTH
|
|
498
|
+
)
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
async function encrypt(payload, secret, salt, expiration) {
|
|
502
|
+
const kid = crypto.randomUUID();
|
|
503
|
+
const encryptionSecret = await deriveEncryptionSecret(secret, salt, kid);
|
|
504
|
+
return await new import_jose.EncryptJWT(payload).setProtectedHeader({ enc: ENC, alg: ALG, kid }).setExpirationTime(expiration).encrypt(encryptionSecret);
|
|
505
|
+
}
|
|
506
|
+
async function decrypt(value, secret, salt) {
|
|
507
|
+
const res = await (0, import_jose.jwtDecrypt)(
|
|
508
|
+
value,
|
|
509
|
+
async (protectedHeader) => {
|
|
510
|
+
if (!protectedHeader.kid) {
|
|
511
|
+
throw new Error('Missing "kid" in JWE header');
|
|
512
|
+
}
|
|
513
|
+
return await deriveEncryptionSecret(secret, salt, protectedHeader.kid);
|
|
514
|
+
},
|
|
515
|
+
{ clockTolerance: 15 }
|
|
516
|
+
);
|
|
517
|
+
return res.payload;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// src/store/abstract-store.ts
|
|
521
|
+
var AbstractStore = class {
|
|
522
|
+
options;
|
|
523
|
+
constructor(options) {
|
|
524
|
+
this.options = options;
|
|
525
|
+
}
|
|
526
|
+
async encrypt(identifier, stateData, expiration) {
|
|
527
|
+
return await encrypt(stateData, this.options.secret, identifier, expiration);
|
|
528
|
+
}
|
|
529
|
+
async decrypt(identifier, encryptedStateData) {
|
|
530
|
+
return await decrypt(encryptedStateData, this.options.secret, identifier);
|
|
531
|
+
}
|
|
532
|
+
};
|
|
533
|
+
|
|
534
|
+
// src/store/abstract-state-store.ts
|
|
535
|
+
var AbstractStateStore = class extends AbstractStore {
|
|
536
|
+
constructor(options) {
|
|
537
|
+
super(options);
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
|
|
541
|
+
// src/store/abstract-transaction-store.ts
|
|
542
|
+
var AbstractTransactionStore = class extends AbstractStore {
|
|
543
|
+
constructor(options) {
|
|
544
|
+
super(options);
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
548
|
+
0 && (module.exports = {
|
|
549
|
+
AbstractStateStore,
|
|
550
|
+
AbstractTransactionStore,
|
|
551
|
+
BackchannelLogoutError,
|
|
552
|
+
MissingRequiredArgumentError,
|
|
553
|
+
MissingSessionError,
|
|
554
|
+
MissingTransactionError,
|
|
555
|
+
ServerClient,
|
|
556
|
+
StartLinkUserError
|
|
557
|
+
});
|
|
558
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/state/utils.ts","../src/server-client.ts","../src/encryption/index.ts","../src/store/abstract-store.ts","../src/store/abstract-state-store.ts","../src/store/abstract-transaction-store.ts"],"sourcesContent":["export { ServerClient } from './server-client.js';\nexport { AbstractStateStore } from './store/abstract-state-store.js';\nexport { AbstractTransactionStore } from './store/abstract-transaction-store.js';\nexport * from './errors.js';\nexport * from './types.js';","/**\n * Error thrown when there is no transaction available.\n */\nexport class MissingTransactionError extends Error {\n public code: string = 'missing_transaction_error';\n\n constructor(message?: string) {\n super(message ?? 'The transaction is missing.');\n this.name = 'MissingTransactionError';\n }\n}\n\n\n/**\n * Error thrown when backchannel logout fails.\n */\nexport class BackchannelLogoutError extends Error {\n public code: string = 'backchannel_logout_error';\n\n constructor(message: string) {\n super(message);\n this.name = 'BackchannelLogoutError';\n }\n}\n\n/**\n * Error thrown when starting the user-linking failed.\n */\nexport class StartLinkUserError extends Error {\n public code: string = 'start_link_user_error';\n\n constructor(message: string) {\n super(message);\n this.name = 'StartLinkUserError';\n }\n}\n\n/**\n * Error thrown when a required argument is missing.\n */\nexport class MissingRequiredArgumentError extends Error {\n public code: string = 'missing_required_argument_error';\n\n constructor(argument: string) {\n super(`The argument '${argument}' is required but was not provided.`);\n this.name = 'MissingRequiredArgumentError';\n }\n}\n\n/**\n * Error thrown when a session is missing.\n */\nexport class MissingSessionError extends Error {\n public code: string = 'missing_session_error';\n\n constructor(message: string) {\n super(message);\n this.name = 'MissingSessionError';\n }\n}","import type { AccessTokenForConnectionOptions, StateData } from '../types.js';\nimport { TokenResponse } from '@auth0/auth0-auth-js';\n\n/**\n * Utility function to update the state with a new response from the token endpoint\n * @param audience The audience of the token endpoint response\n * @param stateDate The existing state data to update, or undefined if no state data available.\n * @param tokenEndpointResponse The response from the token endpoint.\n * @returns Updated state data.\n */\nexport function updateStateData(\n audience: string,\n stateDate: StateData | undefined,\n tokenEndpointResponse: TokenResponse\n): StateData {\n if (stateDate) {\n const isNewTokenSet = !stateDate.tokenSets.some(\n (tokenSet) => tokenSet.audience === audience && tokenSet.scope === tokenEndpointResponse.scope\n );\n\n const createUpdatedTokenSet = (response: TokenResponse) => ({\n audience,\n accessToken: response.accessToken,\n scope: response.scope,\n expiresAt: Math.floor(Date.now() / 1000) + Number(response.expiresAt),\n });\n\n const tokenSets = isNewTokenSet\n ? [...stateDate.tokenSets, createUpdatedTokenSet(tokenEndpointResponse)]\n : stateDate.tokenSets.map((tokenSet) =>\n tokenSet.audience === audience && tokenSet.scope === tokenEndpointResponse.scope\n ? createUpdatedTokenSet(tokenEndpointResponse)\n : tokenSet\n );\n\n return {\n ...stateDate,\n idToken: tokenEndpointResponse.idToken,\n refreshToken: tokenEndpointResponse.refreshToken ?? stateDate.refreshToken,\n tokenSets,\n };\n } else {\n const user = tokenEndpointResponse.claims;\n return {\n user,\n idToken: tokenEndpointResponse.idToken,\n refreshToken: tokenEndpointResponse.refreshToken,\n tokenSets: [\n {\n audience,\n accessToken: tokenEndpointResponse.accessToken,\n scope: tokenEndpointResponse.scope,\n expiresAt:tokenEndpointResponse.expiresAt,\n },\n ],\n internal: {\n sid: user?.sid as string,\n createdAt: Math.floor(Date.now() / 1000),\n },\n };\n }\n}\n\nexport function updateStateDataForConnectionTokenSet(\n options: AccessTokenForConnectionOptions,\n stateDate: StateData,\n tokenEndpointResponse: TokenResponse\n) {\n stateDate.connectionTokenSets = stateDate.connectionTokenSets || [];\n\n const isNewTokenSet = !stateDate.connectionTokenSets.some(\n (tokenSet) =>\n tokenSet.connection === options.connection && (!options.loginHint || tokenSet.loginHint === options.loginHint)\n );\n\n const connectionTokenSet = {\n connection: options.connection,\n loginHint: options.loginHint,\n accessToken: tokenEndpointResponse.accessToken,\n scope: tokenEndpointResponse.scope,\n expiresAt: tokenEndpointResponse.expiresAt,\n };\n\n const connectionTokenSets = isNewTokenSet\n ? [...stateDate.connectionTokenSets, connectionTokenSet]\n : stateDate.connectionTokenSets.map((tokenSet) =>\n tokenSet.connection === options.connection &&\n (!options.loginHint || tokenSet.loginHint === options.loginHint)\n ? connectionTokenSet\n : tokenSet\n );\n\n return {\n ...stateDate,\n connectionTokenSets,\n };\n}\n","import {\n AccessTokenForConnectionOptions,\n ConnectionTokenSet,\n LoginBackchannelOptions,\n LoginBackchannelResult,\n LogoutOptions,\n ServerClientOptions,\n SessionData,\n StartInteractiveLoginOptions,\n StartLinkUserOptions,\n StartUnlinkUserOptions,\n StateStore,\n TokenSet,\n TransactionData,\n TransactionStore,\n} from './types.js';\nimport {\n BackchannelLogoutError,\n MissingRequiredArgumentError,\n MissingSessionError,\n MissingTransactionError,\n} from './errors.js';\nimport { updateStateData, updateStateDataForConnectionTokenSet } from './state/utils.js';\nimport {\n TokenForConnectionError,\n AuthClient,\n AuthorizationDetails,\n TokenByRefreshTokenError,\n} from '@auth0/auth0-auth-js';\n\nexport class ServerClient<TStoreOptions = unknown> {\n readonly #options: ServerClientOptions<TStoreOptions>;\n readonly #transactionStore: TransactionStore<TStoreOptions>;\n readonly #transactionStoreIdentifier: string;\n readonly #stateStore: StateStore<TStoreOptions>;\n readonly #stateStoreIdentifier: string;\n readonly #authClient: AuthClient;\n\n constructor(options: ServerClientOptions<TStoreOptions>) {\n this.#options = options;\n this.#stateStoreIdentifier = this.#options.stateIdentifier || '__a0_session';\n this.#transactionStoreIdentifier = this.#options.transactionIdentifier || '__a0_tx';\n this.#transactionStore = options.transactionStore;\n this.#stateStore = options.stateStore;\n\n if (!this.#options.stateStore) {\n throw new MissingRequiredArgumentError('stateStore');\n }\n\n if (!this.#options.transactionStore) {\n throw new MissingRequiredArgumentError('transactionStore');\n }\n\n this.#authClient = new AuthClient({\n domain: this.#options.domain,\n clientId: this.#options.clientId,\n clientSecret: this.#options.clientSecret,\n clientAssertionSigningKey: this.#options.clientAssertionSigningKey,\n clientAssertionSigningAlg: this.#options.clientAssertionSigningAlg,\n authorizationParams: this.#options.authorizationParams,\n customFetch: this.#options.customFetch,\n });\n }\n\n /**\n * Starts the interactive login process, and returns a URL to redirect the user-agent to to request authorization at Auth0.\n * @param options Optional options used to configure the interactive login process.\n * @param storeOptions Optional options used to pass to the Transaction and State Store.\n *\n * @throws {BuildAuthorizationUrlError} If there was an issue when building the Authorization URL.\n *\n * @returns A promise resolving to a URL object, representing the URL to redirect the user-agent to to request authorization at Auth0.\n */\n public async startInteractiveLogin(options?: StartInteractiveLoginOptions, storeOptions?: TStoreOptions) {\n const redirectUri = options?.authorizationParams?.redirect_uri ?? this.#options.authorizationParams?.redirect_uri;\n if (!redirectUri) {\n throw new MissingRequiredArgumentError('authorizationParams.redirect_uri');\n }\n\n const { codeVerifier, authorizationUrl } = await this.#authClient.buildAuthorizationUrl({\n pushedAuthorizationRequests: options?.pushedAuthorizationRequests,\n authorizationParams: {\n ...options?.authorizationParams,\n redirect_uri: redirectUri,\n },\n });\n\n const transactionState: TransactionData = {\n audience: options?.authorizationParams?.audience ?? this.#options.authorizationParams?.audience,\n codeVerifier,\n };\n\n if (options?.appState) {\n transactionState.appState = options.appState;\n }\n\n await this.#transactionStore.set(this.#transactionStoreIdentifier, transactionState, false, storeOptions);\n\n return authorizationUrl;\n }\n\n /**\n * Completes the interactive login process.\n * Takes an URL, extract the Authorization Code flow query parameters and requests a token.\n * @param url The URl from which the query params should be extracted to exchange for a token.\n * @param storeOptions Optional options used to pass to the Transaction and State Store.\n *\n * @throws {MissingTransactionError} When no transaction was found.\n * @throws {TokenByCodeError} If there was an issue requesting the access token.\n *\n * @returns A promise resolving to an object, containing the original appState (if present) and the authorizationDetails (when RAR was used).\n */\n public async completeInteractiveLogin<TAppState = unknown>(url: URL, storeOptions?: TStoreOptions) {\n const transactionData = await this.#transactionStore.get(this.#transactionStoreIdentifier, storeOptions);\n\n if (!transactionData) {\n throw new MissingTransactionError();\n }\n\n const tokenEndpointResponse = await this.#authClient.getTokenByCode(url, {\n codeVerifier: transactionData.codeVerifier,\n });\n\n const existingStateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);\n\n const stateData = updateStateData(transactionData.audience ?? 'default', existingStateData, tokenEndpointResponse);\n\n await this.#stateStore.set(this.#stateStoreIdentifier, stateData, true, storeOptions);\n await this.#transactionStore.delete(this.#transactionStoreIdentifier, storeOptions);\n\n return { appState: transactionData.appState, authorizationDetails: tokenEndpointResponse.authorizationDetails } as {\n appState?: TAppState;\n authorizationDetails?: AuthorizationDetails[];\n };\n }\n\n /**\n * Starts the user linking process, and returns a URL to redirect the user-agent to to request authorization at Auth0.\n * @param options Options used to configure the user linking process.\n * @param storeOptions Optional options used to pass to the Transaction and State Store.\n *\n * @throws {MissingSessionError} If there is no active session.\n * @throws {BuildLinkUserUrlError} If there was an issue when building the Authorization URL.\n *\n * @returns A promise resolving to a URL object, representing the URL to redirect the user-agent to to request authorization at Auth0.\n */\n public async startLinkUser(options: StartLinkUserOptions, storeOptions?: TStoreOptions) {\n const stateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);\n\n if (!stateData || !stateData.idToken) {\n throw new MissingSessionError(\n 'Unable to start the user linking process without a logged in user. Ensure to login using the SDK before starting the user linking process.'\n );\n }\n\n const { linkUserUrl, codeVerifier } = await this.#authClient.buildLinkUserUrl({\n connection: options.connection,\n connectionScope: options.connectionScope,\n idToken: stateData.idToken,\n authorizationParams: options.authorizationParams,\n });\n\n const transactionState: TransactionData = {\n audience: options?.authorizationParams?.audience ?? this.#options.authorizationParams?.audience,\n codeVerifier,\n };\n\n if (options?.appState) {\n transactionState.appState = options.appState;\n }\n\n await this.#transactionStore.set(this.#transactionStoreIdentifier, transactionState, false, storeOptions);\n\n return linkUserUrl;\n }\n\n /**\n * Completes the user linking process.\n * Takes an URL, extract the Authorization Code flow query parameters and requests a token.\n * @param url The URl from which the query params should be extracted to exchange for a token.\n * @param storeOptions Optional options used to pass to the Transaction and State Store.\n *\n * @throws {MissingTransactionError} When no transaction was found.\n * @throws {TokenByCodeError} If there was an issue requesting the access token.\n *\n * @returns A promise resolving to an object, containing the original appState (if present).\n */\n public async completeLinkUser<TAppState = unknown>(url: URL, storeOptions?: TStoreOptions) {\n // In order to complete the link user flow, we need to exchange the code for a token in the same\n // way as we do for the interactive login flow.\n const result = await this.completeInteractiveLogin<TAppState>(url, storeOptions);\n\n // As we currently do not support RAR when starting the user linking flow, we will ommit it from being returned as optional altogether.\n return {\n appState: result.appState,\n };\n }\n\n /**\n * Starts the user unlinking process, and returns a URL to redirect the user-agent to to initialize user unlinking at Auth0.\n * @param options Options used to configure the user unlinking process.\n * @param storeOptions Optional options used to pass to the Transaction and State Store.\n *\n * @throws {MissingSessionError} If there is no active session.\n * @throws {BuildUnlinkUserUrlError} If there was an issue when building the User Unlinking URL.\n *\n * @returns A promise resolving to a URL object, representing the URL to redirect the user-agent to to request authorization at Auth0.\n */\n public async startUnlinkUser(options: StartUnlinkUserOptions, storeOptions?: TStoreOptions) {\n const stateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);\n\n if (!stateData || !stateData.idToken) {\n throw new MissingSessionError(\n 'Unable to start the user unlinking process without a logged in user. Ensure to login using the SDK before starting the user unlinking process.'\n );\n }\n\n const { unlinkUserUrl, codeVerifier } = await this.#authClient.buildUnlinkUserUrl({\n connection: options.connection,\n idToken: stateData.idToken,\n authorizationParams: options.authorizationParams,\n });\n\n const transactionState: TransactionData = {\n audience: options?.authorizationParams?.audience ?? this.#options.authorizationParams?.audience,\n codeVerifier,\n };\n\n if (options?.appState) {\n transactionState.appState = options.appState;\n }\n\n await this.#transactionStore.set(this.#transactionStoreIdentifier, transactionState, false, storeOptions);\n\n return unlinkUserUrl;\n }\n\n /**\n * Completes the user unlinking process.\n * Takes an URL, extract the Authorization Code flow query parameters and requests a token.\n * @param url The URl from which the query params should be extracted to exchange for a token.\n * @param storeOptions Optional options used to pass to the Transaction and State Store.\n *\n * @throws {MissingTransactionError} When no transaction was found.\n * @throws {TokenByCodeError} If there was an issue requesting the access token.\n *\n * @returns A promise resolving to an object, containing the original appState (if present).\n */\n public async completeUnlinkUser<TAppState = unknown>(url: URL, storeOptions?: TStoreOptions) {\n // In order to complete the link user flow, we need to exchange the code for a token in the same\n // way as we do for the interactive login flow.\n const result = await this.completeInteractiveLogin<TAppState>(url, storeOptions);\n\n // As we currently do not support RAR when starting the user unlinking flow, we will ommit it from being returned as optional altogether.\n return {\n appState: result.appState,\n };\n }\n\n /**\n * Logs in using Client-Initiated Backchannel Authentication.\n *\n * Using Client-Initiated Backchannel Authentication requires the feature to be enabled in the Auth0 dashboard.\n * @see https://auth0.com/docs/get-started/authentication-and-authorization-flow/client-initiated-backchannel-authentication-flow\n * @param options Options used to configure the backchannel login process.\n * @param storeOptions Optional options used to pass to the Transaction and State Store.\n *\n * @throws {BackchannelAuthenticationError} If there was an issue when doing backchannel authentication.\n *\n * @returns A promise resolving to an object, containing the authorizationDetails (when RAR was used).\n */\n public async loginBackchannel(\n options: LoginBackchannelOptions,\n storeOptions?: TStoreOptions\n ): Promise<LoginBackchannelResult> {\n const tokenEndpointResponse = await this.#authClient.backchannelAuthentication({\n bindingMessage: options.bindingMessage,\n loginHint: options.loginHint,\n authorizationParams: options.authorizationParams,\n });\n\n const existingStateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);\n\n const stateData = updateStateData(\n this.#options.authorizationParams?.audience ?? 'default',\n existingStateData,\n tokenEndpointResponse\n );\n\n await this.#stateStore.set(this.#stateStoreIdentifier, stateData, true, storeOptions);\n\n return {\n authorizationDetails: tokenEndpointResponse.authorizationDetails,\n };\n }\n\n /**\n * Retrieves the user from the store, or undefined if no user found.\n * @param storeOptions Optional options used to pass to the Transaction and State Store.\n * @returns The user, or undefined if no user found in the store.\n */\n public async getUser(storeOptions?: TStoreOptions) {\n const stateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);\n\n return stateData?.user;\n }\n\n /**\n * Retrieve the user session from the store, or undefined if no session found.\n * @param storeOptions Optional options used to pass to the Transaction and State Store.\n * @returns The sessionm or undefined if no session found in the store.\n */\n public async getSession(storeOptions?: TStoreOptions): Promise<SessionData | undefined> {\n const stateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);\n\n if (stateData) {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { internal, ...sessionData } = stateData;\n return sessionData;\n }\n }\n\n /**\n * 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.\n * Also updates the store when a new token was retrieved from Auth0.\n * @param storeOptions Optional options used to pass to the Transaction and State Store.\n *\n * @throws {TokenByRefreshTokenError} If the refresh token was not found or there was an issue requesting the access token.\n *\n * @returns The Token Set, containing the access token, as well as additional information.\n */\n public async getAccessToken(storeOptions?: TStoreOptions): Promise<TokenSet> {\n const stateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);\n const audience = this.#options.authorizationParams?.audience ?? 'default';\n const scope = this.#options.authorizationParams?.scope;\n\n const tokenSet = stateData?.tokenSets.find(\n (tokenSet) => tokenSet.audience === audience && (!scope || tokenSet.scope === scope)\n );\n\n if (tokenSet && tokenSet.expiresAt > Date.now() / 1000) {\n return tokenSet;\n }\n\n if (!stateData?.refreshToken) {\n throw new TokenByRefreshTokenError(\n 'The access token has expired and a refresh token was not provided. The user needs to re-authenticate.'\n );\n }\n\n const tokenEndpointResponse = await this.#authClient.getTokenByRefreshToken({\n refreshToken: stateData.refreshToken,\n });\n const existingStateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);\n const updatedStateData = updateStateData(audience, existingStateData, tokenEndpointResponse);\n\n await this.#stateStore.set(this.#stateStoreIdentifier, updatedStateData, false, storeOptions);\n\n return {\n accessToken: tokenEndpointResponse.accessToken,\n scope: tokenEndpointResponse.scope,\n expiresAt: tokenEndpointResponse.expiresAt,\n audience: audience,\n };\n }\n\n /**\n * Retrieves an access token for a connection.\n *\n * This method attempts to obtain an access token for a specified connection.\n * It first checks if a refresh token exists in the store.\n * If no refresh token is found, it throws an `AccessTokenForConnectionError` indicating\n * that the refresh token was not found.\n *\n * @param options - Options for retrieving an access token for a connection.\n * @param storeOptions Optional options used to pass to the Transaction and State Store.\n *\n * @throws {TokenForConnectionError} If the refresh token was not found or there was an issue requesting the access token.\n *\n * @returns The Connection Token Set, containing the access token for the connection, as well as additional information.\n */\n public async getAccessTokenForConnection(options: AccessTokenForConnectionOptions, storeOptions?: TStoreOptions): Promise<ConnectionTokenSet> {\n const stateData = await this.#stateStore.get(this.#stateStoreIdentifier, storeOptions);\n\n const connectionTokenSet = stateData?.connectionTokenSets?.find(\n (tokenSet) => tokenSet.connection === options.connection\n );\n\n if (connectionTokenSet && connectionTokenSet.expiresAt > Date.now() / 1000) {\n return connectionTokenSet;\n }\n\n if (!stateData?.refreshToken) {\n throw new TokenForConnectionError(\n 'A refresh token was not found but is required to be able to retrieve an access token for a connection.'\n );\n }\n\n const tokenEndpointResponse = await this.#authClient.getTokenForConnection({\n connection: options.connection,\n loginHint: options.loginHint,\n refreshToken: stateData.refreshToken,\n });\n\n const updatedStateData = updateStateDataForConnectionTokenSet(options, stateData, tokenEndpointResponse);\n\n await this.#stateStore.set(this.#stateStoreIdentifier, updatedStateData, false, storeOptions);\n\n return {\n accessToken: tokenEndpointResponse.accessToken,\n scope: tokenEndpointResponse.scope,\n expiresAt: tokenEndpointResponse.expiresAt,\n connection: options.connection,\n loginHint: options.loginHint,\n };\n }\n\n /**\n * Logs the user out and returns a URL to redirect the user-agent to after they log out.\n * @param options Options used to configure the logout process.\n * @param storeOptions Optional options used to pass to the Transaction and State Store.\n * @returns {URL}\n */\n public async logout(options: LogoutOptions, storeOptions?: TStoreOptions) {\n await this.#stateStore.delete(this.#stateStoreIdentifier, storeOptions);\n\n return this.#authClient.buildLogoutUrl(options);\n }\n\n /**\n * Handles the backchannel logout process by verifying the logout token and deleting the session from the store if the logout token was considered valid.\n * @param logoutToken The logout token to verify and use to delete the session from the store.\n * @param storeOptions Optional options used to pass to the Transaction and State Store.\n *\n * @throws {BackchannelLogoutError} If the logout token is missing.\n * @throws {VerifyLogoutTokenError} If the logout token is invalid.\n */\n public async handleBackchannelLogout(logoutToken: string, storeOptions?: TStoreOptions) {\n if (!logoutToken) {\n throw new BackchannelLogoutError('Missing Logout Token');\n }\n\n const logoutTokenClaims = await this.#authClient.verifyLogoutToken({ logoutToken });\n\n await this.#stateStore.deleteByLogoutToken(logoutTokenClaims, storeOptions);\n }\n}\n","import { EncryptJWT, jwtDecrypt } from 'jose';\nimport type { JWTPayload } from 'jose';\n\nconst ENC = 'A256CBC-HS512';\nconst ALG = 'dir';\nconst DIGEST = 'SHA-256';\nconst BIT_LENGTH = 512;\nconst HKDF_INFO = 'derived cookie encryption secret';\n\nlet encoder: TextEncoder | undefined;\n\nasync function deriveEncryptionSecret(secret: string, salt: string, kid: string) {\n encoder ||= new TextEncoder();\n const key = await crypto.subtle.importKey('raw', encoder.encode(secret), 'HKDF', false, ['deriveBits']);\n\n return new Uint8Array(\n await crypto.subtle.deriveBits(\n {\n name: 'HKDF',\n hash: DIGEST,\n info: encoder.encode(HKDF_INFO),\n salt: encoder.encode(`${salt}${kid}`),\n } as HkdfParams,\n key,\n BIT_LENGTH\n )\n );\n}\n\nexport async function encrypt(payload: JWTPayload, secret: string, salt: string, expiration: number) {\n const kid = crypto.randomUUID();\n const encryptionSecret = await deriveEncryptionSecret(secret, salt, kid);\n\n return await new EncryptJWT(payload)\n .setProtectedHeader({ enc: ENC, alg: ALG, kid: kid })\n .setExpirationTime(expiration)\n .encrypt(encryptionSecret);\n}\n\nexport async function decrypt<T>(value: string, secret: string, salt: string) {\n const res = await jwtDecrypt<T>(\n value,\n async (protectedHeader) => {\n\n // This error shouldn't happen, as we always set a kid.\n // However, leaving this here as a safety net.\n if (!protectedHeader.kid) {\n throw new Error('Missing \"kid\" in JWE header');\n }\n\n return await deriveEncryptionSecret(secret, salt, protectedHeader.kid);\n },\n { clockTolerance: 15 }\n );\n return res.payload;\n}\n","import type { EncryptedStoreOptions, AbstractDataStore } from '../types.js';\nimport { encrypt, decrypt } from '../encryption/index.js';\nimport { JWTPayload } from 'jose';\n\n/**\n * Abstract class that can be used to implement an Encrypted JWT State Store, using the 'A256CBC-HS512' encryption algorithm.\n */\nexport abstract class AbstractStore<TData extends JWTPayload, TStoreOptions = unknown> implements AbstractDataStore<TData, TStoreOptions>\n{\n protected readonly options: EncryptedStoreOptions;\n\n constructor(options: EncryptedStoreOptions) {\n this.options = options;\n }\n\n abstract set(identifier: string, state: TData, removeIfExists?: boolean, options?: TStoreOptions | undefined): Promise<void>;\n abstract get(identifier: string, options?: TStoreOptions | undefined): Promise<TData | undefined>;\n abstract delete(identifier: string, options?: TStoreOptions | undefined): Promise<void>;\n\n protected async encrypt<TData extends JWTPayload>(identifier: string, stateData: TData, expiration: number) {\n return await encrypt(stateData, this.options.secret, identifier, expiration);\n }\n\n protected async decrypt<TData>(identifier: string, encryptedStateData: string) {\n return await decrypt(encryptedStateData, this.options.secret, identifier) as TData;\n }\n}\n","import type { StateData, EncryptedStoreOptions, StateStore, LogoutTokenClaims } from '../types.js';\nimport { AbstractStore } from './abstract-store.js';\n\n/**\n * Abstract class that can be used to implement an Encrypted JWT State Store, using the 'A256CBC-HS512' encryption algorithm.\n */\nexport abstract class AbstractStateStore<TStoreOptions = unknown> extends AbstractStore<StateData, TStoreOptions> implements StateStore<TStoreOptions> {\n constructor(options: EncryptedStoreOptions) {\n super(options);\n }\n\n abstract deleteByLogoutToken(claims: LogoutTokenClaims, options?: TStoreOptions | undefined): Promise<void>;\n}","import type { EncryptedStoreOptions, TransactionData, TransactionStore } from '../types.js';\nimport { AbstractStore } from './abstract-store.js';\n\n/**\n * Abstract class that can be used to implement an Encrypted JWT Transaction Store, using the 'A256CBC-HS512' encryption algorithm.\n */\nexport abstract class AbstractTransactionStore<TStoreOptions = unknown> extends AbstractStore<TransactionData, TStoreOptions> implements TransactionStore<TStoreOptions> {\n constructor(options: EncryptedStoreOptions) {\n super(options);\n }\n}"],"mappings":"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","names":["tokenSet"]}
|