@opensourcekd/ng-common-libs 2.0.10 → 2.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -448,6 +448,7 @@ function e(e,t){var n={};for(var o in e)Object.prototype.hasOwnProperty.call(e,o
448
448
  class AuthService {
449
449
  auth0Client = null;
450
450
  initializationPromise = null;
451
+ /** Remains false if callback processing fails, allowing the callback to be retried. */
451
452
  callbackHandled = false;
452
453
  callbackPromise = null;
453
454
  userSubject;
@@ -482,6 +483,14 @@ class AuthService {
482
483
  const existingUserInfo = this.getUserInfoFromStorage();
483
484
  this.userSubject = new rxjs.BehaviorSubject(existingUserInfo);
484
485
  this.user$ = this.userSubject.asObservable();
486
+ // Eagerly begin Auth0 client initialization so logs are visible immediately.
487
+ // The .catch() only suppresses an unhandled-rejection warning; the rejected
488
+ // promise is stored in initializationPromise and re-throws when awaited by
489
+ // ensureInitialized() or ensureAuth0Client(), surfacing the error to callers.
490
+ this.initializationPromise = this.initializeAuth0();
491
+ this.initializationPromise.catch(error => {
492
+ console.error('[AuthService] Failed to initialize Auth0 client:', error);
493
+ });
485
494
  }
486
495
  /**
487
496
  * Get the identifier of this AuthService instance
@@ -521,6 +530,25 @@ class AuthService {
521
530
  console.log('[AuthService] Auth0 client initialized successfully');
522
531
  this.emitAuthEvent('init', null);
523
532
  }
533
+ /**
534
+ * Ensure the Auth0 client instance is created, without triggering callback detection.
535
+ * Used internally by {@link handleCallback} to avoid a circular async dependency:
536
+ * `ensureInitialized` → `checkAndHandleCallback` → `handleCallback` → `ensureInitialized`.
537
+ * @throws {Error} When the Auth0 client fails to initialize
538
+ */
539
+ async ensureAuth0Client() {
540
+ if (this.auth0Client)
541
+ return;
542
+ if (this.initializationPromise) {
543
+ await this.initializationPromise;
544
+ return;
545
+ }
546
+ this.initializationPromise = this.initializeAuth0();
547
+ await this.initializationPromise;
548
+ if (!this.auth0Client) {
549
+ throw new Error('[AuthService] Auth0 client failed to initialize');
550
+ }
551
+ }
524
552
  /**
525
553
  * Ensure the Auth0 client is initialized before use
526
554
  * Lazy-initializes on the first call and auto-handles OAuth callbacks when detected
@@ -549,6 +577,10 @@ class AuthService {
549
577
  * The Auth0 SDK's `handleRedirectCallback` validates the `state` parameter
550
578
  * to prevent CSRF attacks. This method only detects presence of callback
551
579
  * params before delegating securely to the SDK.
580
+ *
581
+ * Uses an async IIFE to store the in-flight promise for concurrency deduplication
582
+ * (concurrent callers await the same promise) while still using async/await
583
+ * internally instead of `.then()/.catch()` chains.
552
584
  */
553
585
  async checkAndHandleCallback() {
554
586
  if (this.callbackHandled || typeof window === 'undefined')
@@ -558,15 +590,22 @@ class AuthService {
558
590
  return;
559
591
  }
560
592
  const urlParams = new URLSearchParams(window.location.search);
561
- if (urlParams.has('code') && urlParams.has('state')) {
562
- console.log('[AuthService] Auth0 callback detected in URL, processing...');
563
- this.emitAuthEvent('callback_detected', null);
564
- this.callbackPromise = this.handleCallback()
565
- .then(() => { this.callbackHandled = true; })
566
- .catch(error => { throw error; })
567
- .finally(() => { this.callbackPromise = null; });
593
+ if (!urlParams.has('code') || !urlParams.has('state'))
594
+ return;
595
+ console.log('[AuthService] Auth0 callback detected in URL, processing...');
596
+ this.emitAuthEvent('callback_detected', null);
597
+ // Store the promise before the first await so concurrent callers see it
598
+ // and deduplicate by awaiting the same in-flight promise.
599
+ this.callbackPromise = (async () => {
600
+ await this.handleCallback();
601
+ this.callbackHandled = true;
602
+ })();
603
+ try {
568
604
  await this.callbackPromise;
569
605
  }
606
+ finally {
607
+ this.callbackPromise = null;
608
+ }
570
609
  }
571
610
  /**
572
611
  * Redirect the user to Auth0 Universal Login
@@ -603,11 +642,15 @@ class AuthService {
603
642
  /**
604
643
  * Handle the OAuth2 redirect callback after successful authorization
605
644
  * Stores the user info and access token, then cleans up the callback URL
645
+ *
646
+ * Uses {@link ensureAuth0Client} (not {@link ensureInitialized}) to avoid a circular
647
+ * async dependency: `ensureInitialized` → `checkAndHandleCallback` → `handleCallback`
648
+ * → `ensureInitialized`. Only the Auth0 client instance is needed here.
606
649
  * @returns {@link CallbackResult} with `success` flag and optional `appState`
607
650
  */
608
651
  async handleCallback() {
609
652
  try {
610
- await this.ensureInitialized();
653
+ await this.ensureAuth0Client();
611
654
  console.log('[AuthService] Processing Auth0 redirect callback...');
612
655
  const result = await this.auth0Client.handleRedirectCallback();
613
656
  const user = await this.auth0Client.getUser();
@@ -631,6 +674,11 @@ class AuthService {
631
674
  }
632
675
  /**
633
676
  * Log the user out, clear all stored auth data, and redirect to the logout URI
677
+ *
678
+ * Uses {@link ensureAuth0Client} (not {@link ensureInitialized}) to avoid triggering
679
+ * callback detection during logout. Calling `ensureInitialized` here would invoke
680
+ * `checkAndHandleCallback`, which re-authenticates the user if callback URL params
681
+ * are present, causing them to be sent back to Auth0 instead of the logout URI.
634
682
  */
635
683
  async logout() {
636
684
  console.log('[AuthService] User logging out...');
@@ -640,7 +688,7 @@ class AuthService {
640
688
  this.userSubject.next(null);
641
689
  this.emitAuthEvent('logout', null);
642
690
  try {
643
- await this.ensureInitialized();
691
+ await this.ensureAuth0Client();
644
692
  await this.auth0Client.logout({
645
693
  logoutParams: { returnTo: this.config.logoutUri }
646
694
  });