@vunexa/lixa 0.1.6-alpha.6 → 0.1.6-alpha.8
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 +1 -2
- package/README.template.md +1 -2
- package/dist/errors.d.ts +90 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/export-types/index.d.ts +263 -2
- package/dist/index.cjs +301 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +244 -3
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +280 -34
- package/dist/index.js.map +1 -1
- package/dist/lixa.d.ts +11 -2
- package/dist/lixa.d.ts.map +1 -1
- package/dist/utils/cookies.d.ts +142 -0
- package/dist/utils/cookies.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -31,11 +31,31 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var src_exports = {};
|
|
32
32
|
__export(src_exports, {
|
|
33
33
|
AccountLinkingStrategy: () => AccountLinkingStrategy,
|
|
34
|
+
AccountUnlinkError: () => AccountUnlinkError,
|
|
35
|
+
DEFAULT_SESSION_COOKIE_NAME: () => DEFAULT_SESSION_COOKIE_NAME,
|
|
36
|
+
DEFAULT_SESSION_MAX_AGE_SECONDS: () => DEFAULT_SESSION_MAX_AGE_SECONDS,
|
|
37
|
+
DEFAULT_STATE_COOKIE_NAME: () => DEFAULT_STATE_COOKIE_NAME,
|
|
38
|
+
DEFAULT_STATE_MAX_AGE_SECONDS: () => DEFAULT_STATE_MAX_AGE_SECONDS,
|
|
39
|
+
EmailNotVerifiedError: () => EmailNotVerifiedError,
|
|
40
|
+
InvalidOAuthCallbackError: () => InvalidOAuthCallbackError,
|
|
41
|
+
InvalidProviderConfigError: () => InvalidProviderConfigError,
|
|
42
|
+
InvalidStateError: () => InvalidStateError,
|
|
34
43
|
Lixa: () => Lixa,
|
|
44
|
+
LixaError: () => LixaError,
|
|
45
|
+
ProviderNotConfiguredError: () => ProviderNotConfiguredError,
|
|
46
|
+
RefreshTokenError: () => RefreshTokenError,
|
|
47
|
+
SessionNotFoundError: () => SessionNotFoundError,
|
|
48
|
+
TokenExchangeError: () => TokenExchangeError,
|
|
49
|
+
clearSessionCookie: () => clearSessionCookie,
|
|
50
|
+
clearStateCookie: () => clearStateCookie,
|
|
51
|
+
createSessionCookie: () => createSessionCookie,
|
|
52
|
+
createStateCookie: () => createStateCookie,
|
|
35
53
|
decodeIdToken: () => decodeIdToken,
|
|
36
54
|
determineProviderFromIssuer: () => determineProviderFromIssuer,
|
|
37
55
|
extractUserInfo: () => extractUserInfo,
|
|
38
|
-
fetchUserInfo: () => fetchUserInfo
|
|
56
|
+
fetchUserInfo: () => fetchUserInfo,
|
|
57
|
+
isProductionEnvironment: () => isProductionEnvironment,
|
|
58
|
+
serializeCookie: () => serializeCookie
|
|
39
59
|
});
|
|
40
60
|
module.exports = __toCommonJS(src_exports);
|
|
41
61
|
|
|
@@ -207,6 +227,80 @@ async function extractUserInfo(tokenData, providerMetadata) {
|
|
|
207
227
|
return { userInfo };
|
|
208
228
|
}
|
|
209
229
|
|
|
230
|
+
// src/errors.ts
|
|
231
|
+
var LixaError = class extends Error {
|
|
232
|
+
/**
|
|
233
|
+
* Standard error code string.
|
|
234
|
+
*/
|
|
235
|
+
code;
|
|
236
|
+
/**
|
|
237
|
+
* Additional error context data.
|
|
238
|
+
*/
|
|
239
|
+
details;
|
|
240
|
+
constructor(message, code = "LIXA_ERROR", details) {
|
|
241
|
+
super(message);
|
|
242
|
+
this.name = this.constructor.name;
|
|
243
|
+
this.code = code;
|
|
244
|
+
this.details = details;
|
|
245
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
var InvalidStateError = class extends LixaError {
|
|
249
|
+
constructor(message = "Invalid or expired state", details) {
|
|
250
|
+
super(message, "INVALID_STATE", details);
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
var ProviderNotConfiguredError = class extends LixaError {
|
|
254
|
+
constructor(provider, details) {
|
|
255
|
+
const message = details?.message && typeof details.message === "string" ? details.message : `Provider '${provider}' is not available. Either import it from '@vunexa/lixa-providers' and include it in the configuration, or provide a custom implementation using the 'provider' field: { provider: new CustomProvider(), clientId: '...', ... }`;
|
|
256
|
+
super(message, "PROVIDER_NOT_CONFIGURED", {
|
|
257
|
+
provider,
|
|
258
|
+
...details
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
var InvalidProviderConfigError = class extends LixaError {
|
|
263
|
+
constructor(message, details) {
|
|
264
|
+
super(message, "INVALID_PROVIDER_CONFIG", details);
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
var InvalidOAuthCallbackError = class extends LixaError {
|
|
268
|
+
constructor(message, details) {
|
|
269
|
+
super(message, "INVALID_OAUTH_CALLBACK", details);
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
var TokenExchangeError = class extends LixaError {
|
|
273
|
+
status;
|
|
274
|
+
constructor(message, status, details) {
|
|
275
|
+
super(message, "TOKEN_EXCHANGE_FAILED", { status, ...details });
|
|
276
|
+
this.status = status;
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
var SessionNotFoundError = class extends LixaError {
|
|
280
|
+
constructor(message = "Active session not found or has expired", details) {
|
|
281
|
+
super(message, "SESSION_NOT_FOUND", details);
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
var EmailNotVerifiedError = class extends LixaError {
|
|
285
|
+
constructor(email, details) {
|
|
286
|
+
super(
|
|
287
|
+
`Cannot link account: email '${email || "unknown"}' is not verified by the identity provider`,
|
|
288
|
+
"EMAIL_NOT_VERIFIED",
|
|
289
|
+
{ email, ...details }
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
var AccountUnlinkError = class extends LixaError {
|
|
294
|
+
constructor(message, details) {
|
|
295
|
+
super(message, "ACCOUNT_UNLINK_ERROR", details);
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
var RefreshTokenError = class extends LixaError {
|
|
299
|
+
constructor(message, details) {
|
|
300
|
+
super(message, "REFRESH_TOKEN_ERROR", details);
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
|
|
210
304
|
// src/lixa.ts
|
|
211
305
|
var Lixa = class _Lixa {
|
|
212
306
|
static DEFAULT_PROVIDERS = /* @__PURE__ */ new Map();
|
|
@@ -252,8 +346,9 @@ var Lixa = class _Lixa {
|
|
|
252
346
|
} else {
|
|
253
347
|
if (!_Lixa.DEFAULT_PROVIDERS.has(name) && !_Lixa.CONFIGURED_PROVIDERS.has(name)) {
|
|
254
348
|
this.log("ERROR", "Init", `Provider '${providerName}' not available`);
|
|
255
|
-
throw new
|
|
256
|
-
|
|
349
|
+
throw new ProviderNotConfiguredError(
|
|
350
|
+
providerName,
|
|
351
|
+
{ hint: `Ensure the provider is registered via '@vunexa/lixa-providers' or provided inline.` }
|
|
257
352
|
);
|
|
258
353
|
}
|
|
259
354
|
this.log("INFO", "Init", `Using registered provider: ${providerName}`);
|
|
@@ -266,7 +361,7 @@ var Lixa = class _Lixa {
|
|
|
266
361
|
*
|
|
267
362
|
* @param name - The provider name
|
|
268
363
|
* @param config - The provider configuration
|
|
269
|
-
* @throws
|
|
364
|
+
* @throws InvalidProviderConfigError when required fields are missing or invalid
|
|
270
365
|
*/
|
|
271
366
|
validateProviderConfig(name, config) {
|
|
272
367
|
const requiredFields = ["clientId", "clientSecret", "redirectUri", "scopes"];
|
|
@@ -275,18 +370,21 @@ var Lixa = class _Lixa {
|
|
|
275
370
|
return value === void 0 || value === null || typeof value === "string" && value.trim() === "";
|
|
276
371
|
});
|
|
277
372
|
if (missingFields.length > 0) {
|
|
278
|
-
throw new
|
|
279
|
-
`Provider '${name}' configuration is missing required fields: ${missingFields.join(", ")}
|
|
373
|
+
throw new InvalidProviderConfigError(
|
|
374
|
+
`Provider '${name}' configuration is missing required fields: ${missingFields.join(", ")}`,
|
|
375
|
+
{ provider: name, missingFields }
|
|
280
376
|
);
|
|
281
377
|
}
|
|
282
378
|
if (!Array.isArray(config.scopes)) {
|
|
283
|
-
throw new
|
|
284
|
-
`Provider '${name}' configuration error: 'scopes' must be an array of strings
|
|
379
|
+
throw new InvalidProviderConfigError(
|
|
380
|
+
`Provider '${name}' configuration error: 'scopes' must be an array of strings`,
|
|
381
|
+
{ provider: name }
|
|
285
382
|
);
|
|
286
383
|
}
|
|
287
384
|
if (config.scopes.length === 0) {
|
|
288
|
-
throw new
|
|
289
|
-
`Provider '${name}' configuration error: 'scopes' array cannot be empty
|
|
385
|
+
throw new InvalidProviderConfigError(
|
|
386
|
+
`Provider '${name}' configuration error: 'scopes' array cannot be empty`,
|
|
387
|
+
{ provider: name }
|
|
290
388
|
);
|
|
291
389
|
}
|
|
292
390
|
}
|
|
@@ -295,7 +393,7 @@ var Lixa = class _Lixa {
|
|
|
295
393
|
*
|
|
296
394
|
* @param name - The provider name
|
|
297
395
|
* @param provider - The provider implementation
|
|
298
|
-
* @throws
|
|
396
|
+
* @throws InvalidProviderConfigError when required properties are missing
|
|
299
397
|
*/
|
|
300
398
|
validateProviderImplementation(name, provider) {
|
|
301
399
|
const requiredProps = ["authorizationEndpoint", "tokenEndpoint", "userInfoEndpoint"];
|
|
@@ -304,8 +402,9 @@ var Lixa = class _Lixa {
|
|
|
304
402
|
return !value || typeof value !== "string" || value.trim() === "";
|
|
305
403
|
});
|
|
306
404
|
if (missingProps.length > 0) {
|
|
307
|
-
throw new
|
|
308
|
-
`Provider '${name}' implementation is missing required properties: ${missingProps.join(", ")}. All IProvider implementations must define: authorizationEndpoint, tokenEndpoint, and userInfoEndpoint
|
|
405
|
+
throw new InvalidProviderConfigError(
|
|
406
|
+
`Provider '${name}' implementation is missing required properties: ${missingProps.join(", ")}. All IProvider implementations must define: authorizationEndpoint, tokenEndpoint, and userInfoEndpoint.`,
|
|
407
|
+
{ provider: name, missingProps }
|
|
309
408
|
);
|
|
310
409
|
}
|
|
311
410
|
}
|
|
@@ -372,8 +471,9 @@ var Lixa = class _Lixa {
|
|
|
372
471
|
if (legacyProvider) {
|
|
373
472
|
return legacyProvider;
|
|
374
473
|
}
|
|
375
|
-
throw new
|
|
376
|
-
|
|
474
|
+
throw new ProviderNotConfiguredError(
|
|
475
|
+
name,
|
|
476
|
+
{ hint: `Ensure the provider is included in the configuration with a 'provider' field, or registered using Lixa.registerProvider().` }
|
|
377
477
|
);
|
|
378
478
|
}
|
|
379
479
|
/**
|
|
@@ -563,7 +663,9 @@ var Lixa = class _Lixa {
|
|
|
563
663
|
const providerConfig = this.findProviderByType(providerType);
|
|
564
664
|
if (!providerConfig) {
|
|
565
665
|
this.log("ERROR", "Auth", `Provider '${String(provider)}' is not configured`);
|
|
566
|
-
throw new
|
|
666
|
+
throw new ProviderNotConfiguredError(String(provider), {
|
|
667
|
+
message: `Provider '${String(provider)}' is not configured in this Lixa instance`
|
|
668
|
+
});
|
|
567
669
|
}
|
|
568
670
|
const providerImpl = this.getProvider(providerType, providerConfig);
|
|
569
671
|
let stateValue;
|
|
@@ -679,18 +781,18 @@ var Lixa = class _Lixa {
|
|
|
679
781
|
this.log("INFO", "Auth", `Handling OAuth callback for provider: ${providerType}`);
|
|
680
782
|
if (!code || code.trim() === "") {
|
|
681
783
|
this.log("ERROR", "Auth", "Invalid or missing authorization code in callback");
|
|
682
|
-
throw new
|
|
784
|
+
throw new InvalidOAuthCallbackError("Invalid or missing code in callback");
|
|
683
785
|
}
|
|
684
786
|
if (!state || state.trim() === "") {
|
|
685
787
|
this.log("ERROR", "Auth", "Invalid or missing state in callback");
|
|
686
|
-
throw new
|
|
788
|
+
throw new InvalidOAuthCallbackError("Invalid or missing state in callback");
|
|
687
789
|
}
|
|
688
790
|
this.log("INFO", "State", "Validating state parameter", { state });
|
|
689
791
|
const stateStorage = this.stateHandler.stateStorage || _Lixa.LOCAL_STATE_HANDLER.stateStorage;
|
|
690
792
|
const cachedState = await stateStorage.getState(state);
|
|
691
793
|
if (!cachedState) {
|
|
692
794
|
this.log("ERROR", "State", "State validation failed: state not found or expired", { state });
|
|
693
|
-
throw new
|
|
795
|
+
throw new InvalidStateError("Invalid or expired state", { state });
|
|
694
796
|
}
|
|
695
797
|
this.log("INFO", "State", "State validated successfully, removing from cache");
|
|
696
798
|
await stateStorage.deleteState(state);
|
|
@@ -698,7 +800,9 @@ var Lixa = class _Lixa {
|
|
|
698
800
|
const providerConfig = this.findProviderByType(providerType);
|
|
699
801
|
if (!providerConfig) {
|
|
700
802
|
this.log("ERROR", "Auth", `Provider '${String(provider)}' is not configured`);
|
|
701
|
-
throw new
|
|
803
|
+
throw new ProviderNotConfiguredError(String(provider), {
|
|
804
|
+
message: `Provider '${String(provider)}' is not configured in this Lixa instance`
|
|
805
|
+
});
|
|
702
806
|
}
|
|
703
807
|
const providerImpl = this.getProvider(providerType, providerConfig);
|
|
704
808
|
this.log("INFO", "Token", `Exchanging authorization code for tokens`, { provider: providerType });
|
|
@@ -791,12 +895,12 @@ var Lixa = class _Lixa {
|
|
|
791
895
|
const sessionStorage = this.sessionHandler.sessionStorage || _Lixa.LOCAL_SESSION_HANDLER.sessionStorage;
|
|
792
896
|
const existingSession = await sessionStorage.getSession(sessionId);
|
|
793
897
|
if (!existingSession) {
|
|
794
|
-
throw new
|
|
898
|
+
throw new SessionNotFoundError("Invalid session ID. User must be authenticated to link an account.", { sessionId });
|
|
795
899
|
}
|
|
796
900
|
const providerType = String(provider).toLowerCase();
|
|
797
901
|
const providerConfig = this.findProviderByType(providerType);
|
|
798
902
|
if (!providerConfig) {
|
|
799
|
-
throw new
|
|
903
|
+
throw new ProviderNotConfiguredError(String(provider));
|
|
800
904
|
}
|
|
801
905
|
const providerImpl = this.getProvider(providerType, providerConfig);
|
|
802
906
|
let codeVerifier = (0, import_crypto2.randomBytes)(32).toString("hex");
|
|
@@ -849,11 +953,14 @@ var Lixa = class _Lixa {
|
|
|
849
953
|
const sessionStorage = this.sessionHandler.sessionStorage || _Lixa.LOCAL_SESSION_HANDLER.sessionStorage;
|
|
850
954
|
const session = await sessionStorage.getSession(sessionId);
|
|
851
955
|
if (!session || !session.accounts) {
|
|
852
|
-
throw new
|
|
956
|
+
throw new AccountUnlinkError("Session not found or has no linked accounts.", { sessionId });
|
|
853
957
|
}
|
|
854
958
|
const linkedProviders = Object.keys(session.accounts);
|
|
855
959
|
if (linkedProviders.length <= 1) {
|
|
856
|
-
throw new
|
|
960
|
+
throw new AccountUnlinkError("Cannot unlink the only authentication provider for this account.", {
|
|
961
|
+
sessionId,
|
|
962
|
+
provider: providerToUnlink
|
|
963
|
+
});
|
|
857
964
|
}
|
|
858
965
|
delete session.accounts[providerToUnlink.toLowerCase()];
|
|
859
966
|
await sessionStorage.saveSession(sessionId, session, 86400);
|
|
@@ -875,12 +982,12 @@ var Lixa = class _Lixa {
|
|
|
875
982
|
const sessionStorage = this.sessionHandler.sessionStorage || _Lixa.LOCAL_SESSION_HANDLER.sessionStorage;
|
|
876
983
|
const activeSession = await sessionStorage.getSession(sessionId);
|
|
877
984
|
if (!activeSession) {
|
|
878
|
-
throw new
|
|
985
|
+
throw new SessionNotFoundError("Authentication required. Active session must exist to connect resource providers.", { sessionId });
|
|
879
986
|
}
|
|
880
987
|
const providerType = String(provider).toLowerCase();
|
|
881
988
|
const providerConfig = this.findProviderByType(providerType);
|
|
882
989
|
if (!providerConfig) {
|
|
883
|
-
throw new
|
|
990
|
+
throw new ProviderNotConfiguredError(String(provider));
|
|
884
991
|
}
|
|
885
992
|
const providerImpl = this.getProvider(providerType, providerConfig);
|
|
886
993
|
const stateValue = state || (0, import_crypto2.randomBytes)(16).toString("hex");
|
|
@@ -960,12 +1067,12 @@ var Lixa = class _Lixa {
|
|
|
960
1067
|
const sessionStorage = this.sessionHandler.sessionStorage || _Lixa.LOCAL_SESSION_HANDLER.sessionStorage;
|
|
961
1068
|
const activeSession = await sessionStorage.getSession(sessionId);
|
|
962
1069
|
if (!activeSession) {
|
|
963
|
-
throw new
|
|
1070
|
+
throw new SessionNotFoundError("Authentication required. Active session not found for resource connection.", { sessionId });
|
|
964
1071
|
}
|
|
965
1072
|
const providerType = String(provider).toLowerCase();
|
|
966
1073
|
const providerConfig = this.findProviderByType(providerType);
|
|
967
1074
|
if (!providerConfig) {
|
|
968
|
-
throw new
|
|
1075
|
+
throw new ProviderNotConfiguredError(String(provider));
|
|
969
1076
|
}
|
|
970
1077
|
const providerImpl = this.getProvider(providerType, providerConfig);
|
|
971
1078
|
let codeVerifier = (0, import_crypto2.randomBytes)(32).toString("hex");
|
|
@@ -1066,11 +1173,14 @@ var Lixa = class _Lixa {
|
|
|
1066
1173
|
const providerType = provider.toLowerCase();
|
|
1067
1174
|
let resource = existingResource || await resourceStorage.getResource(userIdOrEmail, providerType);
|
|
1068
1175
|
if (!resource || !resource.refreshToken) {
|
|
1069
|
-
throw new
|
|
1176
|
+
throw new RefreshTokenError(
|
|
1177
|
+
`No refresh token available for user '${userIdOrEmail}' on connected resource '${provider}'`,
|
|
1178
|
+
{ userId: userIdOrEmail, provider }
|
|
1179
|
+
);
|
|
1070
1180
|
}
|
|
1071
1181
|
const providerConfig = this.findProviderByType(providerType);
|
|
1072
1182
|
if (!providerConfig) {
|
|
1073
|
-
throw new
|
|
1183
|
+
throw new ProviderNotConfiguredError(provider);
|
|
1074
1184
|
}
|
|
1075
1185
|
const providerImpl = this.getProvider(providerType, providerConfig);
|
|
1076
1186
|
const body = {
|
|
@@ -1089,7 +1199,10 @@ var Lixa = class _Lixa {
|
|
|
1089
1199
|
});
|
|
1090
1200
|
if (!response.ok) {
|
|
1091
1201
|
const errorText = await response.text();
|
|
1092
|
-
throw new
|
|
1202
|
+
throw new RefreshTokenError(
|
|
1203
|
+
`Failed to refresh resource token for user '${userIdOrEmail}' on '${provider}': ${response.status} - ${errorText}`,
|
|
1204
|
+
{ userId: userIdOrEmail, provider, status: response.status }
|
|
1205
|
+
);
|
|
1093
1206
|
}
|
|
1094
1207
|
const tokens = await response.json();
|
|
1095
1208
|
const expiresAt = tokens.expires_in ? Date.now() + tokens.expires_in * 1e3 : void 0;
|
|
@@ -1112,7 +1225,7 @@ var Lixa = class _Lixa {
|
|
|
1112
1225
|
const sessionStorage = this.sessionHandler.sessionStorage || _Lixa.LOCAL_SESSION_HANDLER.sessionStorage;
|
|
1113
1226
|
const activeSession = await sessionStorage.getSession(sessionId);
|
|
1114
1227
|
if (!activeSession) {
|
|
1115
|
-
throw new
|
|
1228
|
+
throw new SessionNotFoundError("Active session not found.", { sessionId });
|
|
1116
1229
|
}
|
|
1117
1230
|
const providerType = provider.toLowerCase();
|
|
1118
1231
|
const userKey = this.getUserKeyFromSession(activeSession);
|
|
@@ -1148,10 +1261,22 @@ var Lixa = class _Lixa {
|
|
|
1148
1261
|
}
|
|
1149
1262
|
return false;
|
|
1150
1263
|
}
|
|
1264
|
+
/**
|
|
1265
|
+
* Retrieves active session details from session storage.
|
|
1266
|
+
*/
|
|
1151
1267
|
async fetchSessionInfo(sessionId) {
|
|
1152
1268
|
const sessionStorage = this.sessionHandler.sessionStorage || _Lixa.LOCAL_SESSION_HANDLER.sessionStorage;
|
|
1153
1269
|
return await sessionStorage.getSession(sessionId);
|
|
1154
1270
|
}
|
|
1271
|
+
/**
|
|
1272
|
+
* Deletes a session from session storage (e.g. on logout).
|
|
1273
|
+
*
|
|
1274
|
+
* @param sessionId - Active session identifier
|
|
1275
|
+
*/
|
|
1276
|
+
async deleteSession(sessionId) {
|
|
1277
|
+
const sessionStorage = this.sessionHandler.sessionStorage || _Lixa.LOCAL_SESSION_HANDLER.sessionStorage;
|
|
1278
|
+
await sessionStorage.deleteSession(sessionId);
|
|
1279
|
+
}
|
|
1155
1280
|
async exchangeCodeForToken(code, providerConfig, providerImpl, codeVerifier) {
|
|
1156
1281
|
const body = {
|
|
1157
1282
|
client_id: providerConfig.clientId,
|
|
@@ -1182,8 +1307,10 @@ var Lixa = class _Lixa {
|
|
|
1182
1307
|
statusText: response.statusText,
|
|
1183
1308
|
error: errorBody
|
|
1184
1309
|
});
|
|
1185
|
-
throw new
|
|
1186
|
-
`Token exchange failed: ${response.status} ${response.statusText} - ${errorBody}
|
|
1310
|
+
throw new TokenExchangeError(
|
|
1311
|
+
`Token exchange failed: ${response.status} ${response.statusText} - ${errorBody}`,
|
|
1312
|
+
response.status,
|
|
1313
|
+
{ statusText: response.statusText, errorBody }
|
|
1187
1314
|
);
|
|
1188
1315
|
}
|
|
1189
1316
|
this.log("INFO", "Token", "Token exchange response received successfully");
|
|
@@ -1198,13 +1325,152 @@ var Lixa = class _Lixa {
|
|
|
1198
1325
|
return void 0;
|
|
1199
1326
|
}
|
|
1200
1327
|
};
|
|
1328
|
+
|
|
1329
|
+
// src/utils/cookies.ts
|
|
1330
|
+
var DEFAULT_SESSION_COOKIE_NAME = "lixa_session";
|
|
1331
|
+
var DEFAULT_STATE_COOKIE_NAME = "lixa_oauth_state";
|
|
1332
|
+
var DEFAULT_SESSION_MAX_AGE_SECONDS = 24 * 60 * 60;
|
|
1333
|
+
var DEFAULT_STATE_MAX_AGE_SECONDS = 10 * 60;
|
|
1334
|
+
function isProductionEnvironment() {
|
|
1335
|
+
return typeof process !== "undefined" && process.env?.NODE_ENV === "production";
|
|
1336
|
+
}
|
|
1337
|
+
function serializeCookie(name, value, options) {
|
|
1338
|
+
const isProd = isProductionEnvironment();
|
|
1339
|
+
const path = options?.path ?? "/";
|
|
1340
|
+
const httpOnly = options?.httpOnly ?? true;
|
|
1341
|
+
const secure = options?.secure ?? isProd;
|
|
1342
|
+
const sameSite = options?.sameSite ?? "lax";
|
|
1343
|
+
const parts = [`${encodeURIComponent(name)}=${encodeURIComponent(value)}`];
|
|
1344
|
+
if (path) {
|
|
1345
|
+
parts.push(`Path=${path}`);
|
|
1346
|
+
}
|
|
1347
|
+
if (typeof options?.maxAge === "number") {
|
|
1348
|
+
parts.push(`Max-Age=${Math.floor(options.maxAge)}`);
|
|
1349
|
+
const expires = new Date(Date.now() + options.maxAge * 1e3).toUTCString();
|
|
1350
|
+
parts.push(`Expires=${expires}`);
|
|
1351
|
+
}
|
|
1352
|
+
if (options?.domain) {
|
|
1353
|
+
parts.push(`Domain=${options.domain}`);
|
|
1354
|
+
}
|
|
1355
|
+
if (httpOnly) {
|
|
1356
|
+
parts.push("HttpOnly");
|
|
1357
|
+
}
|
|
1358
|
+
if (secure) {
|
|
1359
|
+
parts.push("Secure");
|
|
1360
|
+
}
|
|
1361
|
+
if (sameSite) {
|
|
1362
|
+
const capitalized = sameSite.charAt(0).toUpperCase() + sameSite.slice(1).toLowerCase();
|
|
1363
|
+
parts.push(`SameSite=${capitalized}`);
|
|
1364
|
+
}
|
|
1365
|
+
return parts.join("; ");
|
|
1366
|
+
}
|
|
1367
|
+
function createSessionCookie(sessionId, options) {
|
|
1368
|
+
const isProd = isProductionEnvironment();
|
|
1369
|
+
const resolvedOptions = {
|
|
1370
|
+
name: options?.name || DEFAULT_SESSION_COOKIE_NAME,
|
|
1371
|
+
path: options?.path ?? "/",
|
|
1372
|
+
maxAge: options?.maxAge ?? DEFAULT_SESSION_MAX_AGE_SECONDS,
|
|
1373
|
+
httpOnly: options?.httpOnly ?? true,
|
|
1374
|
+
secure: options?.secure ?? isProd,
|
|
1375
|
+
sameSite: options?.sameSite ?? "lax",
|
|
1376
|
+
domain: options?.domain
|
|
1377
|
+
};
|
|
1378
|
+
const name = resolvedOptions.name;
|
|
1379
|
+
const header = serializeCookie(name, sessionId, resolvedOptions);
|
|
1380
|
+
return {
|
|
1381
|
+
name,
|
|
1382
|
+
value: sessionId,
|
|
1383
|
+
options: resolvedOptions,
|
|
1384
|
+
header
|
|
1385
|
+
};
|
|
1386
|
+
}
|
|
1387
|
+
function clearSessionCookie(options) {
|
|
1388
|
+
const isProd = isProductionEnvironment();
|
|
1389
|
+
const resolvedOptions = {
|
|
1390
|
+
name: options?.name || DEFAULT_SESSION_COOKIE_NAME,
|
|
1391
|
+
path: options?.path ?? "/",
|
|
1392
|
+
maxAge: 0,
|
|
1393
|
+
httpOnly: options?.httpOnly ?? true,
|
|
1394
|
+
secure: options?.secure ?? isProd,
|
|
1395
|
+
sameSite: options?.sameSite ?? "lax",
|
|
1396
|
+
domain: options?.domain
|
|
1397
|
+
};
|
|
1398
|
+
const name = resolvedOptions.name;
|
|
1399
|
+
const header = serializeCookie(name, "", resolvedOptions);
|
|
1400
|
+
return {
|
|
1401
|
+
name,
|
|
1402
|
+
value: "",
|
|
1403
|
+
options: resolvedOptions,
|
|
1404
|
+
header
|
|
1405
|
+
};
|
|
1406
|
+
}
|
|
1407
|
+
function createStateCookie(state, options) {
|
|
1408
|
+
const isProd = isProductionEnvironment();
|
|
1409
|
+
const resolvedOptions = {
|
|
1410
|
+
name: options?.name || DEFAULT_STATE_COOKIE_NAME,
|
|
1411
|
+
path: options?.path ?? "/",
|
|
1412
|
+
maxAge: options?.maxAge ?? DEFAULT_STATE_MAX_AGE_SECONDS,
|
|
1413
|
+
httpOnly: options?.httpOnly ?? true,
|
|
1414
|
+
secure: options?.secure ?? isProd,
|
|
1415
|
+
sameSite: options?.sameSite ?? "lax",
|
|
1416
|
+
domain: options?.domain
|
|
1417
|
+
};
|
|
1418
|
+
const name = resolvedOptions.name;
|
|
1419
|
+
const header = serializeCookie(name, state, resolvedOptions);
|
|
1420
|
+
return {
|
|
1421
|
+
name,
|
|
1422
|
+
value: state,
|
|
1423
|
+
options: resolvedOptions,
|
|
1424
|
+
header
|
|
1425
|
+
};
|
|
1426
|
+
}
|
|
1427
|
+
function clearStateCookie(options) {
|
|
1428
|
+
const isProd = isProductionEnvironment();
|
|
1429
|
+
const resolvedOptions = {
|
|
1430
|
+
name: options?.name || DEFAULT_STATE_COOKIE_NAME,
|
|
1431
|
+
path: options?.path ?? "/",
|
|
1432
|
+
maxAge: 0,
|
|
1433
|
+
httpOnly: options?.httpOnly ?? true,
|
|
1434
|
+
secure: options?.secure ?? isProd,
|
|
1435
|
+
sameSite: options?.sameSite ?? "lax",
|
|
1436
|
+
domain: options?.domain
|
|
1437
|
+
};
|
|
1438
|
+
const name = resolvedOptions.name;
|
|
1439
|
+
const header = serializeCookie(name, "", resolvedOptions);
|
|
1440
|
+
return {
|
|
1441
|
+
name,
|
|
1442
|
+
value: "",
|
|
1443
|
+
options: resolvedOptions,
|
|
1444
|
+
header
|
|
1445
|
+
};
|
|
1446
|
+
}
|
|
1201
1447
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1202
1448
|
0 && (module.exports = {
|
|
1203
1449
|
AccountLinkingStrategy,
|
|
1450
|
+
AccountUnlinkError,
|
|
1451
|
+
DEFAULT_SESSION_COOKIE_NAME,
|
|
1452
|
+
DEFAULT_SESSION_MAX_AGE_SECONDS,
|
|
1453
|
+
DEFAULT_STATE_COOKIE_NAME,
|
|
1454
|
+
DEFAULT_STATE_MAX_AGE_SECONDS,
|
|
1455
|
+
EmailNotVerifiedError,
|
|
1456
|
+
InvalidOAuthCallbackError,
|
|
1457
|
+
InvalidProviderConfigError,
|
|
1458
|
+
InvalidStateError,
|
|
1204
1459
|
Lixa,
|
|
1460
|
+
LixaError,
|
|
1461
|
+
ProviderNotConfiguredError,
|
|
1462
|
+
RefreshTokenError,
|
|
1463
|
+
SessionNotFoundError,
|
|
1464
|
+
TokenExchangeError,
|
|
1465
|
+
clearSessionCookie,
|
|
1466
|
+
clearStateCookie,
|
|
1467
|
+
createSessionCookie,
|
|
1468
|
+
createStateCookie,
|
|
1205
1469
|
decodeIdToken,
|
|
1206
1470
|
determineProviderFromIssuer,
|
|
1207
1471
|
extractUserInfo,
|
|
1208
|
-
fetchUserInfo
|
|
1472
|
+
fetchUserInfo,
|
|
1473
|
+
isProductionEnvironment,
|
|
1474
|
+
serializeCookie
|
|
1209
1475
|
});
|
|
1210
1476
|
//# sourceMappingURL=index.cjs.map
|