@vunexa/lixa 0.1.6-alpha.7 → 0.1.6-alpha.9

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.js CHANGED
@@ -28,7 +28,7 @@ var LocalStateHandler = class {
28
28
  }
29
29
  };
30
30
  }
31
- // Default GenerateState implementation
31
+ // Default generateState implementation
32
32
  async generateState(provider) {
33
33
  const state = randomBytes(16).toString("hex");
34
34
  const codeVerifier = randomBytes(32).toString("hex");
@@ -41,6 +41,10 @@ var LocalStateHandler = class {
41
41
  }
42
42
  };
43
43
  }
44
+ // PascalCase alias for backward compatibility
45
+ async GenerateState(provider) {
46
+ return this.generateState(provider);
47
+ }
44
48
  };
45
49
 
46
50
  // src/lixa.ts
@@ -53,7 +57,20 @@ var LocalSessionHandler = class {
53
57
  emailToSessionMap = /* @__PURE__ */ new Map();
54
58
  sessionStorage;
55
59
  constructor(defaultTtlSeconds = 600) {
56
- this.cache = new NodeCache2({ stdTTL: defaultTtlSeconds });
60
+ this.cache = new NodeCache2({ stdTTL: defaultTtlSeconds, checkperiod: 60 });
61
+ this.cache.on("expired", (_key, value) => {
62
+ if (value && typeof value === "object" && value.email) {
63
+ this.emailToSessionMap.delete(String(value.email).toLowerCase());
64
+ }
65
+ });
66
+ this.cache.on("del", (_key, value) => {
67
+ if (value && typeof value === "object" && value.email) {
68
+ this.emailToSessionMap.delete(String(value.email).toLowerCase());
69
+ }
70
+ });
71
+ this.cache.on("flush", () => {
72
+ this.emailToSessionMap.clear();
73
+ });
57
74
  this.sessionStorage = {
58
75
  saveSession: async (sessionId, session, expiresInSeconds) => {
59
76
  this.cache.set(sessionId, session, expiresInSeconds);
@@ -84,8 +101,8 @@ var LocalSessionHandler = class {
84
101
  }
85
102
  };
86
103
  }
87
- // Default GenerateSession implementation
88
- async GenerateSession(tokenData, providerMetadata) {
104
+ // Default generateSession implementation
105
+ async generateSession(tokenData, _providerMetadata) {
89
106
  if (!tokenData.access_token || typeof tokenData.access_token !== "string") {
90
107
  throw new Error("No valid access token found in OAuth response");
91
108
  }
@@ -95,6 +112,10 @@ var LocalSessionHandler = class {
95
112
  };
96
113
  return session;
97
114
  }
115
+ // PascalCase alias for backward compatibility
116
+ async GenerateSession(tokenData, providerMetadata) {
117
+ return this.generateSession(tokenData, providerMetadata);
118
+ }
98
119
  };
99
120
 
100
121
  // src/utils/user-info.ts
@@ -166,13 +187,91 @@ async function extractUserInfo(tokenData, providerMetadata) {
166
187
  return { userInfo };
167
188
  }
168
189
 
190
+ // src/errors.ts
191
+ var LixaError = class extends Error {
192
+ /**
193
+ * Standard error code string.
194
+ */
195
+ code;
196
+ /**
197
+ * Additional error context data.
198
+ */
199
+ details;
200
+ constructor(message, code = "LIXA_ERROR", details) {
201
+ super(message);
202
+ this.name = this.constructor.name;
203
+ this.code = code;
204
+ this.details = details;
205
+ Object.setPrototypeOf(this, new.target.prototype);
206
+ }
207
+ };
208
+ var InvalidStateError = class extends LixaError {
209
+ constructor(message = "Invalid or expired state", details) {
210
+ super(message, "INVALID_STATE", details);
211
+ }
212
+ };
213
+ var ProviderNotConfiguredError = class extends LixaError {
214
+ constructor(provider, details) {
215
+ 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: '...', ... }`;
216
+ super(message, "PROVIDER_NOT_CONFIGURED", {
217
+ provider,
218
+ ...details
219
+ });
220
+ }
221
+ };
222
+ var InvalidProviderConfigError = class extends LixaError {
223
+ constructor(message, details) {
224
+ super(message, "INVALID_PROVIDER_CONFIG", details);
225
+ }
226
+ };
227
+ var InvalidOAuthCallbackError = class extends LixaError {
228
+ constructor(message, details) {
229
+ super(message, "INVALID_OAUTH_CALLBACK", details);
230
+ }
231
+ };
232
+ var TokenExchangeError = class extends LixaError {
233
+ status;
234
+ constructor(message, status, details) {
235
+ super(message, "TOKEN_EXCHANGE_FAILED", { status, ...details });
236
+ this.status = status;
237
+ }
238
+ };
239
+ var SessionNotFoundError = class extends LixaError {
240
+ constructor(message = "Active session not found or has expired", details) {
241
+ super(message, "SESSION_NOT_FOUND", details);
242
+ }
243
+ };
244
+ var EmailNotVerifiedError = class extends LixaError {
245
+ constructor(email, details) {
246
+ super(
247
+ `Cannot link account: email '${email || "unknown"}' is not verified by the identity provider`,
248
+ "EMAIL_NOT_VERIFIED",
249
+ { email, ...details }
250
+ );
251
+ }
252
+ };
253
+ var AccountUnlinkError = class extends LixaError {
254
+ constructor(message, details) {
255
+ super(message, "ACCOUNT_UNLINK_ERROR", details);
256
+ }
257
+ };
258
+ var RefreshTokenError = class extends LixaError {
259
+ constructor(message, details) {
260
+ super(message, "REFRESH_TOKEN_ERROR", details);
261
+ }
262
+ };
263
+
169
264
  // src/lixa.ts
170
265
  var Lixa = class _Lixa {
171
266
  static DEFAULT_PROVIDERS = /* @__PURE__ */ new Map();
172
267
  static CONFIGURED_PROVIDERS = /* @__PURE__ */ new Map();
173
268
  // Legacy registry for backward compatibility
174
- static LOCAL_STATE_HANDLER = new LocalStateHandler();
175
- static LOCAL_SESSION_HANDLER = new LocalSessionHandler();
269
+ // Instance-scoped fallback handlers to ensure no cross-instance state pollution
270
+ localStateHandler;
271
+ localSessionHandler;
272
+ localResourceHandler;
273
+ userResourceStore = /* @__PURE__ */ new Map();
274
+ refreshMutexes = /* @__PURE__ */ new Map();
176
275
  config;
177
276
  stateHandler;
178
277
  sessionHandler;
@@ -193,10 +292,44 @@ var Lixa = class _Lixa {
193
292
  */
194
293
  constructor(config) {
195
294
  this.config = config;
196
- this.stateHandler = config.stateHandler || _Lixa.LOCAL_STATE_HANDLER;
197
- this.sessionHandler = config.sessionHandler || _Lixa.LOCAL_SESSION_HANDLER;
198
- this.resourceHandler = config.resourceHandler || _Lixa.LOCAL_RESOURCE_HANDLER;
199
295
  this.debug = config.debug || false;
296
+ this.localStateHandler = new LocalStateHandler();
297
+ this.localSessionHandler = new LocalSessionHandler();
298
+ this.localResourceHandler = {
299
+ resourceStorage: {
300
+ saveResource: async (userId, provider, resource) => {
301
+ let userMap = this.userResourceStore.get(userId);
302
+ if (!userMap) {
303
+ userMap = /* @__PURE__ */ new Map();
304
+ this.userResourceStore.set(userId, userMap);
305
+ }
306
+ userMap.set(provider.toLowerCase(), resource);
307
+ },
308
+ getResource: async (userId, provider) => {
309
+ const userMap = this.userResourceStore.get(userId);
310
+ return userMap?.get(provider.toLowerCase()) || null;
311
+ },
312
+ getUserResources: async (userId) => {
313
+ const userMap = this.userResourceStore.get(userId);
314
+ const result = {};
315
+ if (userMap) {
316
+ for (const [p, r] of userMap.entries()) {
317
+ result[p] = r;
318
+ }
319
+ }
320
+ return result;
321
+ },
322
+ deleteResource: async (userId, provider) => {
323
+ const userMap = this.userResourceStore.get(userId);
324
+ if (userMap) {
325
+ userMap.delete(provider.toLowerCase());
326
+ }
327
+ }
328
+ }
329
+ };
330
+ this.stateHandler = config.stateHandler || this.localStateHandler;
331
+ this.sessionHandler = config.sessionHandler || this.localSessionHandler;
332
+ this.resourceHandler = config.resourceHandler || this.localResourceHandler;
200
333
  this.log("INFO", "Init", "Initializing Lixa instance", {
201
334
  providers: Object.keys(config.providers),
202
335
  debug: this.debug
@@ -211,8 +344,9 @@ var Lixa = class _Lixa {
211
344
  } else {
212
345
  if (!_Lixa.DEFAULT_PROVIDERS.has(name) && !_Lixa.CONFIGURED_PROVIDERS.has(name)) {
213
346
  this.log("ERROR", "Init", `Provider '${providerName}' not available`);
214
- throw new Error(
215
- `Provider '${providerName}' 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: '...', ... }`
347
+ throw new ProviderNotConfiguredError(
348
+ providerName,
349
+ { hint: `Ensure the provider is registered via '@vunexa/lixa-providers' or provided inline.` }
216
350
  );
217
351
  }
218
352
  this.log("INFO", "Init", `Using registered provider: ${providerName}`);
@@ -225,7 +359,7 @@ var Lixa = class _Lixa {
225
359
  *
226
360
  * @param name - The provider name
227
361
  * @param config - The provider configuration
228
- * @throws Error when required fields are missing or invalid
362
+ * @throws InvalidProviderConfigError when required fields are missing or invalid
229
363
  */
230
364
  validateProviderConfig(name, config) {
231
365
  const requiredFields = ["clientId", "clientSecret", "redirectUri", "scopes"];
@@ -234,18 +368,21 @@ var Lixa = class _Lixa {
234
368
  return value === void 0 || value === null || typeof value === "string" && value.trim() === "";
235
369
  });
236
370
  if (missingFields.length > 0) {
237
- throw new Error(
238
- `Provider '${name}' configuration is missing required fields: ${missingFields.join(", ")}`
371
+ throw new InvalidProviderConfigError(
372
+ `Provider '${name}' configuration is missing required fields: ${missingFields.join(", ")}`,
373
+ { provider: name, missingFields }
239
374
  );
240
375
  }
241
376
  if (!Array.isArray(config.scopes)) {
242
- throw new Error(
243
- `Provider '${name}' configuration error: 'scopes' must be an array of strings`
377
+ throw new InvalidProviderConfigError(
378
+ `Provider '${name}' configuration error: 'scopes' must be an array of strings`,
379
+ { provider: name }
244
380
  );
245
381
  }
246
382
  if (config.scopes.length === 0) {
247
- throw new Error(
248
- `Provider '${name}' configuration error: 'scopes' array cannot be empty`
383
+ throw new InvalidProviderConfigError(
384
+ `Provider '${name}' configuration error: 'scopes' array cannot be empty`,
385
+ { provider: name }
249
386
  );
250
387
  }
251
388
  }
@@ -254,7 +391,7 @@ var Lixa = class _Lixa {
254
391
  *
255
392
  * @param name - The provider name
256
393
  * @param provider - The provider implementation
257
- * @throws Error when required properties are missing
394
+ * @throws InvalidProviderConfigError when required properties are missing
258
395
  */
259
396
  validateProviderImplementation(name, provider) {
260
397
  const requiredProps = ["authorizationEndpoint", "tokenEndpoint", "userInfoEndpoint"];
@@ -263,24 +400,27 @@ var Lixa = class _Lixa {
263
400
  return !value || typeof value !== "string" || value.trim() === "";
264
401
  });
265
402
  if (missingProps.length > 0) {
266
- throw new Error(
267
- `Provider '${name}' implementation is missing required properties: ${missingProps.join(", ")}. All IProvider implementations must define: authorizationEndpoint, tokenEndpoint, and userInfoEndpoint.`
403
+ throw new InvalidProviderConfigError(
404
+ `Provider '${name}' implementation is missing required properties: ${missingProps.join(", ")}. All IProvider implementations must define: authorizationEndpoint, tokenEndpoint, and userInfoEndpoint.`,
405
+ { provider: name, missingProps }
268
406
  );
269
407
  }
270
408
  }
271
409
  /**
272
- * Structured debug logging with standardized format.
410
+ * Structured logging with standardized format and custom logger support.
273
411
  *
274
- * @param level - Log level (INFO, WARN, ERROR)
275
- * @param context - Context of the log (Init, Auth, Token, Session, State)
412
+ * @param level - Log level (INFO, WARN, ERROR, DEBUG)
413
+ * @param context - Context of the log (Init, Auth, Token, Session, State, AccountLinking, Resource)
276
414
  * @param message - Log message
277
415
  * @param data - Optional data to log
278
- *
279
- * @remarks
280
- * Format: [Lixa] [timestamp] [level] [context] message
281
- * Only logs when debug mode is enabled.
282
416
  */
283
417
  log(level, context, message, data) {
418
+ if (this.config.logger) {
419
+ try {
420
+ this.config.logger.log(level, context, message, data);
421
+ } catch {
422
+ }
423
+ }
284
424
  if (!this.debug) return;
285
425
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
286
426
  const prefix = `[Lixa] [${timestamp}] [${level}] [${context}]`;
@@ -331,8 +471,9 @@ var Lixa = class _Lixa {
331
471
  if (legacyProvider) {
332
472
  return legacyProvider;
333
473
  }
334
- throw new Error(
335
- `Provider '${name}' not found. Ensure the provider is included in the configuration with a 'provider' field, or registered using Lixa.registerProvider().`
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().` }
336
477
  );
337
478
  }
338
479
  /**
@@ -522,23 +663,26 @@ var Lixa = class _Lixa {
522
663
  const providerConfig = this.findProviderByType(providerType);
523
664
  if (!providerConfig) {
524
665
  this.log("ERROR", "Auth", `Provider '${String(provider)}' is not configured`);
525
- throw new Error(`Provider '${String(provider)}' is not configured in this Lixa instance`);
666
+ throw new ProviderNotConfiguredError(String(provider), {
667
+ message: `Provider '${String(provider)}' is not configured in this Lixa instance`
668
+ });
526
669
  }
527
670
  const providerImpl = this.getProvider(providerType, providerConfig);
528
671
  let stateValue;
529
672
  let codeVerifier;
530
- if (this.stateHandler.generateState) {
531
- this.log("INFO", "State", "Calling custom GenerateState");
532
- const generated = await this.stateHandler.generateState(providerType);
673
+ const generateStateFn = this.stateHandler.generateState || this.stateHandler.GenerateState;
674
+ if (generateStateFn) {
675
+ this.log("INFO", "State", "Calling custom generateState");
676
+ const generated = await generateStateFn(providerType);
533
677
  stateValue = state || generated.state;
534
678
  codeVerifier = generated.data.codeVerifier;
535
- const storage = this.stateHandler.stateStorage || _Lixa.LOCAL_STATE_HANDLER.stateStorage;
679
+ const storage = this.stateHandler.stateStorage || this.localStateHandler.stateStorage;
536
680
  await storage.saveState(stateValue, generated.data, 300);
537
681
  } else {
538
682
  this.log("INFO", "State", "Using default state generation");
539
683
  stateValue = state || randomBytes2(16).toString("hex");
540
684
  codeVerifier = randomBytes2(32).toString("hex");
541
- const storage = this.stateHandler.stateStorage || _Lixa.LOCAL_STATE_HANDLER.stateStorage;
685
+ const storage = this.stateHandler.stateStorage || this.localStateHandler.stateStorage;
542
686
  await storage.saveState(
543
687
  stateValue,
544
688
  {
@@ -547,12 +691,17 @@ var Lixa = class _Lixa {
547
691
  codeVerifier
548
692
  },
549
693
  300
550
- // 5 minutes in seconds
694
+ // 5 minutes in seconds (synchronized with cookie TTL)
551
695
  );
552
696
  }
553
697
  const codeChallenge = _Lixa.buildCodeChallenge(codeVerifier);
554
698
  this.log("INFO", "State", `Saved state for provider: ${providerType}`, { state: stateValue });
555
- const authNScopes = this.resolveAuthNScopes(providerType, providerConfig.scopes, providerImpl);
699
+ const authNScopes = this.resolveAuthNScopes(
700
+ providerType,
701
+ providerConfig.scopes,
702
+ providerImpl,
703
+ providerConfig.allowNonAuthScopes
704
+ );
556
705
  const params = new URLSearchParams({
557
706
  client_id: providerConfig.clientId,
558
707
  redirect_uri: providerConfig.redirectUri,
@@ -571,9 +720,12 @@ var Lixa = class _Lixa {
571
720
  return authUrl;
572
721
  }
573
722
  /**
574
- * Restricts primary authentication scopes strictly to AuthN identity scopes.
723
+ * Restricts primary authentication scopes strictly to AuthN identity scopes unless allowNonAuthScopes is true.
575
724
  */
576
- resolveAuthNScopes(providerType, configuredScopes, providerImpl) {
725
+ resolveAuthNScopes(providerType, configuredScopes, providerImpl, allowNonAuthScopes) {
726
+ if (allowNonAuthScopes) {
727
+ return configuredScopes && configuredScopes.length > 0 ? configuredScopes : providerImpl.authScopes || ["openid", "email", "profile"];
728
+ }
577
729
  const defaultAuthScopes = {
578
730
  google: ["openid", "email", "profile"],
579
731
  github: ["read:user", "user:email"],
@@ -602,7 +754,7 @@ var Lixa = class _Lixa {
602
754
  "Auth",
603
755
  `Primary authentication is strictly limited to AuthN scopes. Excluded non-AuthN resource scopes: [${nonAuthNScopes.join(
604
756
  ", "
605
- )}]. Use lixa.getResourceAuthUrl() post-login to connect resource providers.`
757
+ )}]. Set 'allowNonAuthScopes: true' on provider config to include them, or use lixa.getResourceAuthUrl() post-login to connect resource providers.`
606
758
  );
607
759
  }
608
760
  if (validAuthNScopes.length > 0) {
@@ -638,18 +790,18 @@ var Lixa = class _Lixa {
638
790
  this.log("INFO", "Auth", `Handling OAuth callback for provider: ${providerType}`);
639
791
  if (!code || code.trim() === "") {
640
792
  this.log("ERROR", "Auth", "Invalid or missing authorization code in callback");
641
- throw new Error("Invalid or missing code in callback");
793
+ throw new InvalidOAuthCallbackError("Invalid or missing code in callback");
642
794
  }
643
795
  if (!state || state.trim() === "") {
644
796
  this.log("ERROR", "Auth", "Invalid or missing state in callback");
645
- throw new Error("Invalid or missing state in callback");
797
+ throw new InvalidOAuthCallbackError("Invalid or missing state in callback");
646
798
  }
647
799
  this.log("INFO", "State", "Validating state parameter", { state });
648
- const stateStorage = this.stateHandler.stateStorage || _Lixa.LOCAL_STATE_HANDLER.stateStorage;
800
+ const stateStorage = this.stateHandler.stateStorage || this.localStateHandler.stateStorage;
649
801
  const cachedState = await stateStorage.getState(state);
650
802
  if (!cachedState) {
651
803
  this.log("ERROR", "State", "State validation failed: state not found or expired", { state });
652
- throw new Error("Invalid or expired state");
804
+ throw new InvalidStateError("Invalid or expired state", { state });
653
805
  }
654
806
  this.log("INFO", "State", "State validated successfully, removing from cache");
655
807
  await stateStorage.deleteState(state);
@@ -657,7 +809,9 @@ var Lixa = class _Lixa {
657
809
  const providerConfig = this.findProviderByType(providerType);
658
810
  if (!providerConfig) {
659
811
  this.log("ERROR", "Auth", `Provider '${String(provider)}' is not configured`);
660
- throw new Error(`Provider '${String(provider)}' is not configured in this Lixa instance`);
812
+ throw new ProviderNotConfiguredError(String(provider), {
813
+ message: `Provider '${String(provider)}' is not configured in this Lixa instance`
814
+ });
661
815
  }
662
816
  const providerImpl = this.getProvider(providerType, providerConfig);
663
817
  this.log("INFO", "Token", `Exchanging authorization code for tokens`, { provider: providerType });
@@ -683,9 +837,12 @@ var Lixa = class _Lixa {
683
837
  extractedUserInfo = userInfo;
684
838
  } catch {
685
839
  }
686
- const generateSession = this.sessionHandler.generateSession || _Lixa.LOCAL_SESSION_HANDLER.GenerateSession.bind(_Lixa.LOCAL_SESSION_HANDLER);
687
- if (this.sessionHandler.generateSession) {
688
- this.log("INFO", "Session", "Calling custom GenerateSession");
840
+ const generateSession = this.sessionHandler.generateSession || this.sessionHandler.GenerateSession || (this.localSessionHandler.generateSession ? this.localSessionHandler.generateSession.bind(this.localSessionHandler) : void 0);
841
+ if (!generateSession) {
842
+ throw new Error("No session generation handler available");
843
+ }
844
+ if (this.sessionHandler.generateSession || this.sessionHandler.GenerateSession) {
845
+ this.log("INFO", "Session", "Calling custom generateSession");
689
846
  } else {
690
847
  this.log("INFO", "Session", "Using default session generation");
691
848
  }
@@ -694,7 +851,7 @@ var Lixa = class _Lixa {
694
851
  if (extractedUserInfo?.email && !session.email) {
695
852
  session.email = extractedUserInfo.email;
696
853
  }
697
- const sessionStorage = this.sessionHandler.sessionStorage || _Lixa.LOCAL_SESSION_HANDLER.sessionStorage;
854
+ const sessionStorage = this.sessionHandler.sessionStorage || this.localSessionHandler.sessionStorage;
698
855
  const linkingConfig = this.config.accountLinking;
699
856
  const mode = String(linkingConfig?.mode || "");
700
857
  const isLinkByEmail = mode === "AUTO_LINK_BY_VERIFIED_EMAIL" /* AUTO_LINK_BY_VERIFIED_EMAIL */ || mode === "AUTO_LINK_BY_VERIFIED_EMAIL" || mode === "linkByEmail";
@@ -747,27 +904,31 @@ var Lixa = class _Lixa {
747
904
  */
748
905
  async linkAccount(params) {
749
906
  const { sessionId, provider, code, state } = params;
750
- const sessionStorage = this.sessionHandler.sessionStorage || _Lixa.LOCAL_SESSION_HANDLER.sessionStorage;
907
+ const sessionStorage = this.sessionHandler.sessionStorage || this.localSessionHandler.sessionStorage;
751
908
  const existingSession = await sessionStorage.getSession(sessionId);
752
909
  if (!existingSession) {
753
- throw new Error("Invalid session ID. User must be authenticated to link an account.");
910
+ throw new SessionNotFoundError("Invalid session ID. User must be authenticated to link an account.", { sessionId });
911
+ }
912
+ if (!code || code.trim() === "") {
913
+ throw new InvalidOAuthCallbackError("Invalid or missing code in linkAccount");
754
914
  }
755
915
  const providerType = String(provider).toLowerCase();
756
916
  const providerConfig = this.findProviderByType(providerType);
757
917
  if (!providerConfig) {
758
- throw new Error(`Provider '${String(provider)}' is not configured`);
918
+ throw new ProviderNotConfiguredError(String(provider));
759
919
  }
760
920
  const providerImpl = this.getProvider(providerType, providerConfig);
761
- let codeVerifier = randomBytes2(32).toString("hex");
921
+ let codeVerifier;
762
922
  if (state) {
763
- const stateStorage = this.stateHandler.stateStorage || _Lixa.LOCAL_STATE_HANDLER.stateStorage;
923
+ const stateStorage = this.stateHandler.stateStorage || this.localStateHandler.stateStorage;
764
924
  const cachedState = await stateStorage.getState(state);
765
- if (cachedState) {
766
- codeVerifier = cachedState.codeVerifier;
767
- await stateStorage.deleteState(state);
925
+ if (!cachedState) {
926
+ throw new InvalidStateError("Invalid or expired state during account linking", { state });
768
927
  }
928
+ codeVerifier = cachedState.codeVerifier;
929
+ await stateStorage.deleteState(state);
769
930
  }
770
- const tokens = await this.exchangeCodeForToken(providerType, providerConfig, providerImpl, codeVerifier);
931
+ const tokens = await this.exchangeCodeForToken(code, providerConfig, providerImpl, codeVerifier || "");
771
932
  const providerMetadata = {
772
933
  name: providerType,
773
934
  endpoints: {
@@ -805,14 +966,17 @@ var Lixa = class _Lixa {
805
966
  * @returns Promise resolving to true on successful unlink
806
967
  */
807
968
  async unlinkAccount(sessionId, providerToUnlink) {
808
- const sessionStorage = this.sessionHandler.sessionStorage || _Lixa.LOCAL_SESSION_HANDLER.sessionStorage;
969
+ const sessionStorage = this.sessionHandler.sessionStorage || this.localSessionHandler.sessionStorage;
809
970
  const session = await sessionStorage.getSession(sessionId);
810
971
  if (!session || !session.accounts) {
811
- throw new Error("Session not found or has no linked accounts.");
972
+ throw new AccountUnlinkError("Session not found or has no linked accounts.", { sessionId });
812
973
  }
813
974
  const linkedProviders = Object.keys(session.accounts);
814
975
  if (linkedProviders.length <= 1) {
815
- throw new Error("Cannot unlink the only authentication provider for this account.");
976
+ throw new AccountUnlinkError("Cannot unlink the only authentication provider for this account.", {
977
+ sessionId,
978
+ provider: providerToUnlink
979
+ });
816
980
  }
817
981
  delete session.accounts[providerToUnlink.toLowerCase()];
818
982
  await sessionStorage.saveSession(sessionId, session, 86400);
@@ -831,20 +995,20 @@ var Lixa = class _Lixa {
831
995
  */
832
996
  async getResourceAuthUrl(params) {
833
997
  const { sessionId, provider, scopes, state, prompt, extraConfig } = params;
834
- const sessionStorage = this.sessionHandler.sessionStorage || _Lixa.LOCAL_SESSION_HANDLER.sessionStorage;
998
+ const sessionStorage = this.sessionHandler.sessionStorage || this.localSessionHandler.sessionStorage;
835
999
  const activeSession = await sessionStorage.getSession(sessionId);
836
1000
  if (!activeSession) {
837
- throw new Error("Authentication required. Active session must exist to connect resource providers.");
1001
+ throw new SessionNotFoundError("Authentication required. Active session must exist to connect resource providers.", { sessionId });
838
1002
  }
839
1003
  const providerType = String(provider).toLowerCase();
840
1004
  const providerConfig = this.findProviderByType(providerType);
841
1005
  if (!providerConfig) {
842
- throw new Error(`Provider '${String(provider)}' is not configured`);
1006
+ throw new ProviderNotConfiguredError(String(provider));
843
1007
  }
844
1008
  const providerImpl = this.getProvider(providerType, providerConfig);
845
1009
  const stateValue = state || randomBytes2(16).toString("hex");
846
1010
  const codeVerifier = randomBytes2(32).toString("hex");
847
- const storage = this.stateHandler.stateStorage || _Lixa.LOCAL_STATE_HANDLER.stateStorage;
1011
+ const storage = this.stateHandler.stateStorage || this.localStateHandler.stateStorage;
848
1012
  await storage.saveState(
849
1013
  stateValue,
850
1014
  {
@@ -869,45 +1033,6 @@ var Lixa = class _Lixa {
869
1033
  });
870
1034
  return `${providerImpl.authorizationEndpoint}?${searchParams.toString()}`;
871
1035
  }
872
- /**
873
- * Handles the OAuth callback for a connected resource provider and stores resource tokens on the session.
874
- *
875
- * @param params - Object containing sessionId, provider, code, state, and requested scopes
876
- * @returns Updated Session containing stored resource tokens under session.resources[provider]
877
- */
878
- static userResourceStore = /* @__PURE__ */ new Map();
879
- static LOCAL_RESOURCE_HANDLER = {
880
- resourceStorage: {
881
- saveResource: async (userId, provider, resource) => {
882
- let userMap = _Lixa.userResourceStore.get(userId);
883
- if (!userMap) {
884
- userMap = /* @__PURE__ */ new Map();
885
- _Lixa.userResourceStore.set(userId, userMap);
886
- }
887
- userMap.set(provider.toLowerCase(), resource);
888
- },
889
- getResource: async (userId, provider) => {
890
- const userMap = _Lixa.userResourceStore.get(userId);
891
- return userMap?.get(provider.toLowerCase()) || null;
892
- },
893
- getUserResources: async (userId) => {
894
- const userMap = _Lixa.userResourceStore.get(userId);
895
- const result = {};
896
- if (userMap) {
897
- for (const [p, r] of userMap.entries()) {
898
- result[p] = r;
899
- }
900
- }
901
- return result;
902
- },
903
- deleteResource: async (userId, provider) => {
904
- const userMap = _Lixa.userResourceStore.get(userId);
905
- if (userMap) {
906
- userMap.delete(provider.toLowerCase());
907
- }
908
- }
909
- }
910
- };
911
1036
  getUserKeyFromSession(session) {
912
1037
  return session.userId || session.email || session.id || "anonymous";
913
1038
  }
@@ -916,25 +1041,26 @@ var Lixa = class _Lixa {
916
1041
  */
917
1042
  async handleResourceCallback(params) {
918
1043
  const { sessionId, provider, code, state, scopes } = params;
919
- const sessionStorage = this.sessionHandler.sessionStorage || _Lixa.LOCAL_SESSION_HANDLER.sessionStorage;
1044
+ const sessionStorage = this.sessionHandler.sessionStorage || this.localSessionHandler.sessionStorage;
920
1045
  const activeSession = await sessionStorage.getSession(sessionId);
921
1046
  if (!activeSession) {
922
- throw new Error("Authentication required. Active session not found for resource connection.");
1047
+ throw new SessionNotFoundError("Authentication required. Active session not found for resource connection.", { sessionId });
923
1048
  }
924
1049
  const providerType = String(provider).toLowerCase();
925
1050
  const providerConfig = this.findProviderByType(providerType);
926
1051
  if (!providerConfig) {
927
- throw new Error(`Provider '${String(provider)}' is not configured`);
1052
+ throw new ProviderNotConfiguredError(String(provider));
928
1053
  }
929
1054
  const providerImpl = this.getProvider(providerType, providerConfig);
930
1055
  let codeVerifier = randomBytes2(32).toString("hex");
931
1056
  if (state) {
932
- const stateStorage = this.stateHandler.stateStorage || _Lixa.LOCAL_STATE_HANDLER.stateStorage;
1057
+ const stateStorage = this.stateHandler.stateStorage || this.localStateHandler.stateStorage;
933
1058
  const cachedState = await stateStorage.getState(state);
934
- if (cachedState) {
935
- codeVerifier = cachedState.codeVerifier;
936
- await stateStorage.deleteState(state);
1059
+ if (!cachedState) {
1060
+ throw new InvalidStateError("Invalid or expired state during resource connection callback", { state });
937
1061
  }
1062
+ codeVerifier = cachedState.codeVerifier;
1063
+ await stateStorage.deleteState(state);
938
1064
  }
939
1065
  const tokens = await this.exchangeCodeForToken(code, providerConfig, providerImpl, codeVerifier);
940
1066
  const expiresAt = tokens.expires_in ? Date.now() + tokens.expires_in * 1e3 : void 0;
@@ -948,7 +1074,7 @@ var Lixa = class _Lixa {
948
1074
  connectedAt: Date.now()
949
1075
  };
950
1076
  const userKey = this.getUserKeyFromSession(activeSession);
951
- const resourceStorage = this.resourceHandler.resourceStorage || _Lixa.LOCAL_RESOURCE_HANDLER.resourceStorage;
1077
+ const resourceStorage = this.resourceHandler.resourceStorage || this.localResourceHandler.resourceStorage;
952
1078
  await resourceStorage.saveResource(userKey, providerType, connectedResource);
953
1079
  activeSession.resources = activeSession.resources || {};
954
1080
  activeSession.resources[providerType] = connectedResource;
@@ -963,7 +1089,7 @@ var Lixa = class _Lixa {
963
1089
  * @param provider - Resource provider identifier (e.g. 'github', 'google')
964
1090
  */
965
1091
  async getUserResource(userIdOrEmail, provider) {
966
- const resourceStorage = this.resourceHandler.resourceStorage || _Lixa.LOCAL_RESOURCE_HANDLER.resourceStorage;
1092
+ const resourceStorage = this.resourceHandler.resourceStorage || this.localResourceHandler.resourceStorage;
967
1093
  const providerType = provider.toLowerCase();
968
1094
  const resource = await resourceStorage.getResource(userIdOrEmail, providerType);
969
1095
  if (!resource) return null;
@@ -981,7 +1107,7 @@ var Lixa = class _Lixa {
981
1107
  * Retrieves all connected resources for a specific User ID / Email.
982
1108
  */
983
1109
  async getUserResources(userIdOrEmail) {
984
- const resourceStorage = this.resourceHandler.resourceStorage || _Lixa.LOCAL_RESOURCE_HANDLER.resourceStorage;
1110
+ const resourceStorage = this.resourceHandler.resourceStorage || this.localResourceHandler.resourceStorage;
985
1111
  return await resourceStorage.getUserResources(userIdOrEmail);
986
1112
  }
987
1113
  /**
@@ -991,7 +1117,7 @@ var Lixa = class _Lixa {
991
1117
  * @param provider - Provider identifier (e.g. 'github', 'google')
992
1118
  */
993
1119
  async getConnectedResource(sessionId, provider) {
994
- const sessionStorage = this.sessionHandler.sessionStorage || _Lixa.LOCAL_SESSION_HANDLER.sessionStorage;
1120
+ const sessionStorage = this.sessionHandler.sessionStorage || this.localSessionHandler.sessionStorage;
995
1121
  const activeSession = await sessionStorage.getSession(sessionId);
996
1122
  if (!activeSession) return null;
997
1123
  const providerType = provider.toLowerCase();
@@ -1016,20 +1142,40 @@ var Lixa = class _Lixa {
1016
1142
  }
1017
1143
  /**
1018
1144
  * Refreshes a user's resource access token using its refresh token.
1145
+ * Deduplicates concurrent refresh requests via an in-flight promise mutex.
1019
1146
  *
1020
1147
  * @param userIdOrEmail - User identifier or email
1021
1148
  * @param provider - Provider identifier (e.g. 'google', 'github')
1022
1149
  */
1023
1150
  async refreshUserResourceToken(userIdOrEmail, provider, existingResource) {
1024
- const resourceStorage = this.resourceHandler.resourceStorage || _Lixa.LOCAL_RESOURCE_HANDLER.resourceStorage;
1151
+ const mutexKey = `${userIdOrEmail.toLowerCase()}:${provider.toLowerCase()}`;
1152
+ const existingPromise = this.refreshMutexes.get(mutexKey);
1153
+ if (existingPromise) {
1154
+ this.log("INFO", "Token", `Concurrent refresh request detected for '${mutexKey}'. Reusing in-flight promise.`);
1155
+ return existingPromise;
1156
+ }
1157
+ const refreshPromise = this.executeRefreshUserResourceToken(userIdOrEmail, provider, existingResource).finally(() => {
1158
+ this.refreshMutexes.delete(mutexKey);
1159
+ });
1160
+ this.refreshMutexes.set(mutexKey, refreshPromise);
1161
+ return refreshPromise;
1162
+ }
1163
+ /**
1164
+ * Internal execution of refresh token exchange.
1165
+ */
1166
+ async executeRefreshUserResourceToken(userIdOrEmail, provider, existingResource) {
1167
+ const resourceStorage = this.resourceHandler.resourceStorage || this.localResourceHandler.resourceStorage;
1025
1168
  const providerType = provider.toLowerCase();
1026
1169
  let resource = existingResource || await resourceStorage.getResource(userIdOrEmail, providerType);
1027
1170
  if (!resource || !resource.refreshToken) {
1028
- throw new Error(`No refresh token available for user '${userIdOrEmail}' on connected resource '${provider}'`);
1171
+ throw new RefreshTokenError(
1172
+ `No refresh token available for user '${userIdOrEmail}' on connected resource '${provider}'`,
1173
+ { userId: userIdOrEmail, provider }
1174
+ );
1029
1175
  }
1030
1176
  const providerConfig = this.findProviderByType(providerType);
1031
1177
  if (!providerConfig) {
1032
- throw new Error(`Provider '${provider}' is not configured`);
1178
+ throw new ProviderNotConfiguredError(provider);
1033
1179
  }
1034
1180
  const providerImpl = this.getProvider(providerType, providerConfig);
1035
1181
  const body = {
@@ -1048,7 +1194,10 @@ var Lixa = class _Lixa {
1048
1194
  });
1049
1195
  if (!response.ok) {
1050
1196
  const errorText = await response.text();
1051
- throw new Error(`Failed to refresh resource token for user '${userIdOrEmail}' on '${provider}': ${response.status} - ${errorText}`);
1197
+ throw new RefreshTokenError(
1198
+ `Failed to refresh resource token for user '${userIdOrEmail}' on '${provider}': ${response.status} - ${errorText}`,
1199
+ { userId: userIdOrEmail, provider, status: response.status }
1200
+ );
1052
1201
  }
1053
1202
  const tokens = await response.json();
1054
1203
  const expiresAt = tokens.expires_in ? Date.now() + tokens.expires_in * 1e3 : void 0;
@@ -1068,10 +1217,10 @@ var Lixa = class _Lixa {
1068
1217
  * Refreshes a connected resource access token for an active session.
1069
1218
  */
1070
1219
  async refreshResourceToken(sessionId, provider) {
1071
- const sessionStorage = this.sessionHandler.sessionStorage || _Lixa.LOCAL_SESSION_HANDLER.sessionStorage;
1220
+ const sessionStorage = this.sessionHandler.sessionStorage || this.localSessionHandler.sessionStorage;
1072
1221
  const activeSession = await sessionStorage.getSession(sessionId);
1073
1222
  if (!activeSession) {
1074
- throw new Error("Active session not found.");
1223
+ throw new SessionNotFoundError("Active session not found.", { sessionId });
1075
1224
  }
1076
1225
  const providerType = provider.toLowerCase();
1077
1226
  const userKey = this.getUserKeyFromSession(activeSession);
@@ -1086,7 +1235,7 @@ var Lixa = class _Lixa {
1086
1235
  * Disconnects a resource provider for a specific User ID / Email.
1087
1236
  */
1088
1237
  async disconnectUserResource(userIdOrEmail, provider) {
1089
- const resourceStorage = this.resourceHandler.resourceStorage || _Lixa.LOCAL_RESOURCE_HANDLER.resourceStorage;
1238
+ const resourceStorage = this.resourceHandler.resourceStorage || this.localResourceHandler.resourceStorage;
1090
1239
  await resourceStorage.deleteResource(userIdOrEmail, provider.toLowerCase());
1091
1240
  return true;
1092
1241
  }
@@ -1094,7 +1243,7 @@ var Lixa = class _Lixa {
1094
1243
  * Disconnects a resource provider from an active session and user account.
1095
1244
  */
1096
1245
  async disconnectResource(sessionId, provider) {
1097
- const sessionStorage = this.sessionHandler.sessionStorage || _Lixa.LOCAL_SESSION_HANDLER.sessionStorage;
1246
+ const sessionStorage = this.sessionHandler.sessionStorage || this.localSessionHandler.sessionStorage;
1098
1247
  const activeSession = await sessionStorage.getSession(sessionId);
1099
1248
  if (activeSession) {
1100
1249
  const userKey = this.getUserKeyFromSession(activeSession);
@@ -1107,10 +1256,22 @@ var Lixa = class _Lixa {
1107
1256
  }
1108
1257
  return false;
1109
1258
  }
1259
+ /**
1260
+ * Retrieves active session details from session storage.
1261
+ */
1110
1262
  async fetchSessionInfo(sessionId) {
1111
- const sessionStorage = this.sessionHandler.sessionStorage || _Lixa.LOCAL_SESSION_HANDLER.sessionStorage;
1263
+ const sessionStorage = this.sessionHandler.sessionStorage || this.localSessionHandler.sessionStorage;
1112
1264
  return await sessionStorage.getSession(sessionId);
1113
1265
  }
1266
+ /**
1267
+ * Deletes a session from session storage (e.g. on logout).
1268
+ *
1269
+ * @param sessionId - Active session identifier
1270
+ */
1271
+ async deleteSession(sessionId) {
1272
+ const sessionStorage = this.sessionHandler.sessionStorage || this.localSessionHandler.sessionStorage;
1273
+ await sessionStorage.deleteSession(sessionId);
1274
+ }
1114
1275
  async exchangeCodeForToken(code, providerConfig, providerImpl, codeVerifier) {
1115
1276
  const body = {
1116
1277
  client_id: providerConfig.clientId,
@@ -1141,8 +1302,10 @@ var Lixa = class _Lixa {
1141
1302
  statusText: response.statusText,
1142
1303
  error: errorBody
1143
1304
  });
1144
- throw new Error(
1145
- `Token exchange failed: ${response.status} ${response.statusText} - ${errorBody}`
1305
+ throw new TokenExchangeError(
1306
+ `Token exchange failed: ${response.status} ${response.statusText} - ${errorBody}`,
1307
+ response.status,
1308
+ { statusText: response.statusText, errorBody }
1146
1309
  );
1147
1310
  }
1148
1311
  this.log("INFO", "Token", "Token exchange response received successfully");
@@ -1157,12 +1320,204 @@ var Lixa = class _Lixa {
1157
1320
  return void 0;
1158
1321
  }
1159
1322
  };
1323
+
1324
+ // src/utils/cookies.ts
1325
+ var DEFAULT_SESSION_COOKIE_NAME = "lixa_session";
1326
+ var DEFAULT_STATE_COOKIE_NAME = "lixa_oauth_state";
1327
+ var DEFAULT_SESSION_MAX_AGE_SECONDS = 24 * 60 * 60;
1328
+ var DEFAULT_STATE_MAX_AGE_SECONDS = 5 * 60;
1329
+ function isProductionEnvironment() {
1330
+ return typeof process !== "undefined" && process.env?.NODE_ENV === "production";
1331
+ }
1332
+ function serializeCookie(name, value, options) {
1333
+ const isProd = isProductionEnvironment();
1334
+ const path = options?.path ?? "/";
1335
+ const httpOnly = options?.httpOnly ?? true;
1336
+ const secure = options?.secure ?? isProd;
1337
+ const sameSite = options?.sameSite ?? "lax";
1338
+ const parts = [`${encodeURIComponent(name)}=${encodeURIComponent(value)}`];
1339
+ if (path) {
1340
+ parts.push(`Path=${path}`);
1341
+ }
1342
+ if (typeof options?.maxAge === "number") {
1343
+ parts.push(`Max-Age=${Math.floor(options.maxAge)}`);
1344
+ const expires = new Date(Date.now() + options.maxAge * 1e3).toUTCString();
1345
+ parts.push(`Expires=${expires}`);
1346
+ }
1347
+ if (options?.domain) {
1348
+ parts.push(`Domain=${options.domain}`);
1349
+ }
1350
+ if (httpOnly) {
1351
+ parts.push("HttpOnly");
1352
+ }
1353
+ if (secure) {
1354
+ parts.push("Secure");
1355
+ }
1356
+ if (sameSite) {
1357
+ const capitalized = sameSite.charAt(0).toUpperCase() + sameSite.slice(1).toLowerCase();
1358
+ parts.push(`SameSite=${capitalized}`);
1359
+ }
1360
+ return parts.join("; ");
1361
+ }
1362
+ function createSessionCookie(sessionId, options) {
1363
+ const isProd = isProductionEnvironment();
1364
+ const resolvedOptions = {
1365
+ name: options?.name || DEFAULT_SESSION_COOKIE_NAME,
1366
+ path: options?.path ?? "/",
1367
+ maxAge: options?.maxAge ?? DEFAULT_SESSION_MAX_AGE_SECONDS,
1368
+ httpOnly: options?.httpOnly ?? true,
1369
+ secure: options?.secure ?? isProd,
1370
+ sameSite: options?.sameSite ?? "lax",
1371
+ domain: options?.domain
1372
+ };
1373
+ const name = resolvedOptions.name;
1374
+ const header = serializeCookie(name, sessionId, resolvedOptions);
1375
+ return {
1376
+ name,
1377
+ value: sessionId,
1378
+ options: resolvedOptions,
1379
+ header
1380
+ };
1381
+ }
1382
+ function clearSessionCookie(options) {
1383
+ const isProd = isProductionEnvironment();
1384
+ const resolvedOptions = {
1385
+ name: options?.name || DEFAULT_SESSION_COOKIE_NAME,
1386
+ path: options?.path ?? "/",
1387
+ maxAge: 0,
1388
+ httpOnly: options?.httpOnly ?? true,
1389
+ secure: options?.secure ?? isProd,
1390
+ sameSite: options?.sameSite ?? "lax",
1391
+ domain: options?.domain
1392
+ };
1393
+ const name = resolvedOptions.name;
1394
+ const header = serializeCookie(name, "", resolvedOptions);
1395
+ return {
1396
+ name,
1397
+ value: "",
1398
+ options: resolvedOptions,
1399
+ header
1400
+ };
1401
+ }
1402
+ function createStateCookie(state, options) {
1403
+ const isProd = isProductionEnvironment();
1404
+ const resolvedOptions = {
1405
+ name: options?.name || DEFAULT_STATE_COOKIE_NAME,
1406
+ path: options?.path ?? "/",
1407
+ maxAge: options?.maxAge ?? DEFAULT_STATE_MAX_AGE_SECONDS,
1408
+ httpOnly: options?.httpOnly ?? true,
1409
+ secure: options?.secure ?? isProd,
1410
+ sameSite: options?.sameSite ?? "lax",
1411
+ domain: options?.domain
1412
+ };
1413
+ const name = resolvedOptions.name;
1414
+ const header = serializeCookie(name, state, resolvedOptions);
1415
+ return {
1416
+ name,
1417
+ value: state,
1418
+ options: resolvedOptions,
1419
+ header
1420
+ };
1421
+ }
1422
+ function clearStateCookie(options) {
1423
+ const isProd = isProductionEnvironment();
1424
+ const resolvedOptions = {
1425
+ name: options?.name || DEFAULT_STATE_COOKIE_NAME,
1426
+ path: options?.path ?? "/",
1427
+ maxAge: 0,
1428
+ httpOnly: options?.httpOnly ?? true,
1429
+ secure: options?.secure ?? isProd,
1430
+ sameSite: options?.sameSite ?? "lax",
1431
+ domain: options?.domain
1432
+ };
1433
+ const name = resolvedOptions.name;
1434
+ const header = serializeCookie(name, "", resolvedOptions);
1435
+ return {
1436
+ name,
1437
+ value: "",
1438
+ options: resolvedOptions,
1439
+ header
1440
+ };
1441
+ }
1442
+
1443
+ // src/express.ts
1444
+ function setSessionCookieOnResponse(res, sessionId, options) {
1445
+ const cookie = createSessionCookie(sessionId, options);
1446
+ res.cookie(cookie.name, cookie.value, cookie.options);
1447
+ }
1448
+ function clearSessionCookieOnResponse(res, options) {
1449
+ const cookie = clearSessionCookie(options);
1450
+ res.cookie(cookie.name, cookie.value, cookie.options);
1451
+ }
1452
+ function setStateCookieOnResponse(res, state, options) {
1453
+ const cookie = createStateCookie(state, options);
1454
+ res.cookie(cookie.name, cookie.value, cookie.options);
1455
+ }
1456
+ function clearStateCookieOnResponse(res, options) {
1457
+ const cookie = clearStateCookie(options);
1458
+ res.cookie(cookie.name, cookie.value, cookie.options);
1459
+ }
1460
+ function createRequireAuthMiddleware(lixa, options) {
1461
+ const cookieName = options?.sessionCookieName || DEFAULT_SESSION_COOKIE_NAME;
1462
+ return async (req, res, next) => {
1463
+ try {
1464
+ const sessionId = req.cookies?.[cookieName];
1465
+ if (!sessionId) {
1466
+ if (options?.unauthorizedHandler) {
1467
+ options.unauthorizedHandler(req, res);
1468
+ return;
1469
+ }
1470
+ res.status(401).json({ error: "Unauthorized: Missing session cookie" });
1471
+ return;
1472
+ }
1473
+ const session = await lixa.fetchSessionInfo(sessionId);
1474
+ if (!session) {
1475
+ if (options?.unauthorizedHandler) {
1476
+ options.unauthorizedHandler(req, res);
1477
+ return;
1478
+ }
1479
+ res.status(401).json({ error: "Unauthorized: Invalid or expired session" });
1480
+ return;
1481
+ }
1482
+ req.sessionInfo = session;
1483
+ req.sessionId = sessionId;
1484
+ next();
1485
+ } catch (error) {
1486
+ next(error);
1487
+ }
1488
+ };
1489
+ }
1160
1490
  export {
1161
1491
  AccountLinkingStrategy,
1492
+ AccountUnlinkError,
1493
+ DEFAULT_SESSION_COOKIE_NAME,
1494
+ DEFAULT_SESSION_MAX_AGE_SECONDS,
1495
+ DEFAULT_STATE_COOKIE_NAME,
1496
+ DEFAULT_STATE_MAX_AGE_SECONDS,
1497
+ EmailNotVerifiedError,
1498
+ InvalidOAuthCallbackError,
1499
+ InvalidProviderConfigError,
1500
+ InvalidStateError,
1162
1501
  Lixa,
1502
+ LixaError,
1503
+ ProviderNotConfiguredError,
1504
+ RefreshTokenError,
1505
+ SessionNotFoundError,
1506
+ TokenExchangeError,
1507
+ clearSessionCookie,
1508
+ clearSessionCookieOnResponse,
1509
+ clearStateCookie,
1510
+ clearStateCookieOnResponse,
1511
+ createRequireAuthMiddleware,
1512
+ createSessionCookie,
1513
+ createStateCookie,
1163
1514
  decodeIdToken,
1164
1515
  determineProviderFromIssuer,
1165
1516
  extractUserInfo,
1166
- fetchUserInfo
1517
+ fetchUserInfo,
1518
+ isProductionEnvironment,
1519
+ serializeCookie,
1520
+ setSessionCookieOnResponse,
1521
+ setStateCookieOnResponse
1167
1522
  };
1168
1523
  //# sourceMappingURL=index.js.map