Skip to content

BrowserAuthError and user cancelled the flow for SSO MSAL-angular. #7725

@sneti-rpost

Description

@sneti-rpost

Core Library

MSAL.js (@azure/msal-browser)

Core Library Version

2.22.1

Wrapper Library

MSAL Angular (@azure/msal-angular)

Wrapper Library Version

2.1.2

Public or Confidential Client?

Confidential

Description

Hi Team,
we're facing below issue while logging from SSO Microsoft.

  1. when user is logging from SSO from our website using Microsoft login pop-up first time he's able to login. after some time(idle time/multiple login and logout) when he tried to login via SSO, he's unable to login and pop-up is disappearing.

ssocode.txt

Error Message

User Account: null Error Json: {"eventType":"msal:loginFailure","interactionType":"popup","payload":null,"error":{},"timestamp":1745852447496}
User Account: null Error:{"errorCode":"user_cancelled","errorMessage":"User cancelled the flow.","subError":"","name":"BrowserAuthError","correlationId":"0baa75c7-ec09-4f5f-b512-cc0d9285413f"}
Error; [Mon, 28 Apr 2025 15:00:47 GMT] : [0baa75c7-ec09-4f5f-b512-cc0d9285413f] : msal.js.browser@2.39.0 : Error - PopupHandler.monitorPopupForHash - window closed
User Account: null user_cancelled: User cancelled the flow.
User Account: null RetryCount: 0 Error:user_cancelled: User cancelled the flow.

MSAL Logs

Error; [Tue, 29 Apr 2025 04:04:03 GMT] : [ffc4ccec-33df-41eb-99b3-de453c6e37b5] : msal.js.browser@2.39.0 : Error - PopupHandler.monitorPopupForHash - window closed

Network Trace (Preferrably Fiddler)

  • Sent
    Pending

MSAL Configuration

import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { ActivatedRoute, ParamMap, Router } from '@angular/router';
import { MatButtonModule } from '@angular/material/button';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatListModule } from '@angular/material/list';
import { MatMenuModule } from '@angular/material/menu';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { ProfileComponent } from './profile/profile.component';

import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
import { IPublicClientApplication, PublicClientApplication, InteractionType, BrowserCacheLocation, LogLevel } from '@azure/msal-browser';
import { MsalGuard, MsalInterceptor, MsalBroadcastService, MsalInterceptorConfiguration, MsalModule, MsalService, MSAL_GUARD_CONFIG, MSAL_INSTANCE, MSAL_INTERCEPTOR_CONFIG, MsalGuardConfiguration, MsalRedirectComponent } from '@azure/msal-angular';
import { FailedComponent } from './failed/failed.component';
import { SSOAuthenticationComponent } from './sso-authentication/sso-authentication.component';
import { ssoAuthenticationLogoutComponent } from './sso-authentication-logout/sso-authentication-logout.component';
import { environment } from 'src/environments/environment';
import { HeaderComponent } from './header/header.component';
import { FooterComponent } from './footer/footer.component';
import { SocialLoginModule, SocialAuthServiceConfig, GoogleInitOptions } from '@abacritt/angularx-social-login';
import {
  GoogleLoginProvider,
  FacebookLoginProvider
} from '@abacritt/angularx-social-login';
import { EmailAutenticationComponent } from './email-autentication/email-autentication.component';
// import ngx-translate and the http loader
import {TranslateLoader, TranslateModule} from '@ngx-translate/core';
import {TranslateHttpLoader} from '@ngx-translate/http-loader';
import {HttpClient} from '@angular/common/http';
import { ResetPasswordReminderComponent } from './reset-password-reminder/reset-password-reminder.component';
import { ResetPasswordComponent } from './reset-password/reset-password.component';
import { PasswordExpiredComponent } from './password-expired/password-expired.component';
import { ErrorpageComponent } from './errorpage/errorpage.component';
//import { ErrorInterceptor } from './_helpers/error.interceptor';
import { ReactiveFormsModule } from '@angular/forms';
import { PasswordResetComponent } from './password-reset/password-reset.component';
import { ResetPasswordSuccessComponent } from './reset-password-success/reset-password-success.component';
import { ResetPasswordErrorComponent } from './reset-password-error/reset-password-error.component';
import { ConversionUtils } from 'turbocommons-ts/utils/ConversionUtils';
import { ssoSsoLogoutComponent } from './sso-sso-logout/sso-sso-logout.component';



const isIE = window.navigator.userAgent.indexOf("MSIE ") > -1 || window.navigator.userAgent.indexOf("Trident/") > -1; // Remove this line to use Angular Universal
let clientIdPv='';
let postLogoutRedirectUri='';
export function HttpLoaderFactory(http: HttpClient) {
  return new TranslateHttpLoader(http, '../../assets/i18n/', '.json');
}
export function loggerCallback(logLevel: LogLevel, message: string) {
  console.log(message);
}

export function MSALInstanceFactory(): IPublicClientApplication {
  clientIdPv= localStorage.getItem('clienIdLS')!;
  postLogoutRedirectUri = localStorage.getItem("postLogoutRedirectUri")!;

  return new PublicClientApplication({
    
    auth: {
      clientId: environment.azureSSOClientId, 
      authority: 'https://login.microsoftonline.com/common', // PPE testing environment.
      redirectUri: '/',
      postLogoutRedirectUri: '/'
    },
    cache: {
      cacheLocation: BrowserCacheLocation.LocalStorage,
      storeAuthStateInCookie: true, // Helps with KMSI scenarios
      // storeAuthStateInCookie: isIE, // set to true for IE 11. Remove this line to use Angular Universal
    },
    system: {
      loggerOptions: {
        //loggerCallback,
        // added for verbose logging
        loggerCallback: (level: LogLevel, message: string | Error | any, containsPii: boolean) => {
          try {
                if (containsPii) {
                  return;  // skip logging sensitive info
                }
    // Check if message is a string, because only strings have includes method
                if (typeof message === 'string') {
                  if (
                    message.includes('Silent token acquisition failed') ||
                    message.includes('Token renewal operation failed due to timeout') ||
                    message.includes('login_required') ||
                    message.includes('interaction_in_progress') ||
                    message.includes('token_renewal_error') ||
                    message.includes('timeout')
                  ) {
                    console.warn('loggerCallback:Token/Session Warning', message);
                  }
                } else if (message instanceof Error) {
                  console.warn('loggerCallback:ErrorMessage:', message.message); // Handle the case when message is an instance of Error
                  console.warn('loggerCallback:ErrorStackTrace:', message.stack); // Log stack trace if available
                }
                else if (typeof message === 'object' && message !== null) { // Handle message when it's a generic object (not string or Error)
                    console.warn('loggerCallback.ObjectMessage:', message);
                    console.warn('loggerCallback.SerializedObject:', JSON.stringify(message));
                }
                // log everything if environment is not prod
                if ( !environment.production || 
                   message.includes('timeout') ||
                  (environment.production && level === LogLevel.Error)
                )
                {
                      if (typeof message !== 'string') {
                          message = JSON.stringify(message);
                      }

                      var logTextBase64Str=ConversionUtils.stringToBase64(LogLevel[level] + "; " + message);
                        // 2. Call Custom API
                        const logEntry = {
                          ClientId:clientIdPv
                          ,LogText:logTextBase64Str
                          ,Type: 'MSAL.js'
                        };

                      fetch(environment.baseAPIUrl+'/api/v1/log', {
                        method: 'POST',
                        headers: {
                          'Content-Type': 'application/json',
                        },
                        body: JSON.stringify(logEntry),
                      })
                      .then(response => {
                        if (!response.ok) {
                          console.error('Failed to send MSAL log to API:', response.status, response.statusText);
                        }
                      })
                      .catch(error => {
                        console.error('Error sending MSAL log to API:', error);
                      });
                }

                switch (level) {
                  case LogLevel.Error:
                    console.error(message);
                    break;
                  case LogLevel.Info:
                    console.info(message);
                    break;
                  case LogLevel.Verbose:
                    console.debug(message);
                    break;
                  case LogLevel.Warning:
                    console.warn(message);
                    break;
            }
        } catch (err) {
          console.error("MSAL Logger internal error:", err);
        }
          
      },
      
        //logLevel: LogLevel.Info,
        logLevel: LogLevel.Verbose,
        piiLoggingEnabled: false
      }
      ,tokenRenewalOffsetSeconds: 600 //MSAL will try to renew tokens 10 minutes before they expire
      ,windowHashTimeout: 120000 // 120 seconds/2 minutes
      ,navigateFrameWait: 60000 // 60 seconds
      //,asyncPopups: false, // default value is false

      /* Defaults
        windowHashTimeout	:	9000ms	//timeout period for processing the hash fragment (#) in the URL after a redirect during an authentication flow
        navigateFrameWait	:	500ms	//while acquiring token in background, is the maximum amount of time (in milliseconds) that MSAL will wait for the browser to successfully navigate the hidden iframe to the Microsoft authorization endpoint.
        tokenRenewalOffsetSeconds	:	300s	//early renewal buffer for tokens i.e. 5 minutes before expiry
        loadFrameTimeout : 0 timeout //for loading iframes, how long the library will wait for the hidden iframe to complete its task before considering the renewal attempt a failure
      */
    }
  });
}
// required for AOT compilation
// export function HttpLoaderFactory(http: HttpClient): TranslateHttpLoader {
//   return new TranslateHttpLoader(http);
// }
export function MSALInterceptorConfigFactory(): MsalInterceptorConfiguration {
  const protectedResourceMap = new Map<string, Array<string>>();
   protectedResourceMap.set('https://graph.microsoft.com/v1.0/me', ['user.read']); // Prod environment. Uncomment to use.
  //protectedResourceMap.set('https://graph.microsoft-ppe.com/v1.0/me', ['user.read']);

  return {
    interactionType: InteractionType.Popup,
    protectedResourceMap
  };
}

export function MSALGuardConfigFactory(): MsalGuardConfiguration {
  return { 
    interactionType: InteractionType.Popup,
    authRequest: {
      
      scopes: ["api://"+environment.scopeId+"/.default"], // client ID of the API
      prompt: 'select_account', // Forces account selection, may reduce KMSI prompts
    },
    loginFailedRoute: '/login-failed'
  };
}
const googleLoginOptions: GoogleInitOptions = {
  oneTapEnabled: false, // default is true
  scopes: 'https://www.googleapis.com/auth/calendar.readonly'
}; // https://developers.google.com/identity/oauth2/web/guides/use-token-model#initialize_a_token_client

@NgModule({
  declarations: [
    AppComponent,
    HomeComponent,
    ProfileComponent,
    FailedComponent,
    ssoAuthenticationComponent,
    ssoAuthenticationLogoutComponent,
    HeaderComponent,
    FooterComponent,
    EmailAutenticationComponent,
    ResetPasswordReminderComponent,
    ResetPasswordComponent,
    PasswordExpiredComponent,
    ErrorpageComponent,
    PasswordResetComponent,
    ResetPasswordSuccessComponent,
    ResetPasswordErrorComponent,
    ssoSsoLogoutComponent
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    AppRoutingModule,
    MatButtonModule,
    MatToolbarModule,
    MatListModule,
    MatMenuModule,
    HttpClientModule,
    MsalModule,
    SocialLoginModule,
    // ngx-translate and the loader module
    HttpClientModule,
    ReactiveFormsModule,
    TranslateModule.forRoot({
        loader: {
            provide: TranslateLoader,
            useFactory: HttpLoaderFactory,
            deps: [HttpClient]
        }
    })
  ],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: MsalInterceptor,
      multi: true
    },
    //{ provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true },
    //{ provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true },

    {
      provide: MSAL_INSTANCE,
      useFactory: MSALInstanceFactory
    },
    {
      provide: MSAL_GUARD_CONFIG,
      useFactory: MSALGuardConfigFactory
    },
    {
      provide: MSAL_INTERCEPTOR_CONFIG,
      useFactory: MSALInterceptorConfigFactory
    },
    {
      provide: 'SocialAuthServiceConfig',
      useValue: {
        autoLogin: false,
        providers: [
          {
            id: GoogleLoginProvider.PROVIDER_ID,
            provider: new GoogleLoginProvider(
              environment.googleSSOClientId,googleLoginOptions
            )
          }
          /* ,
          {
            id: FacebookLoginProvider.PROVIDER_ID,
            provider: new FacebookLoginProvider('clientId')
          } */
        ],
        onError: (err) => {
          console.error(err);
        }
      } as SocialAuthServiceConfig,
    },
    MsalService,
    MsalGuard,
    MsalBroadcastService
  ],
  bootstrap: [AppComponent, MsalRedirectComponent]
})
export class AppModule { 

  constructor(private route: ActivatedRoute) {
    //alert(this.route.snapshot.queryParamMap.get('clientId'));
    //this.route.params.subscribe( params => clientIdPv =(params['clientId']));
    //clientIdPv=localStorage.getItem('clienIdLS')!;
    //alert(clientIdPv);
    //alert(this.clientId);
    //localStorage.setItem("clienIdLS",this.clientId); */
   }

   ngOnInit(): void {
    /* let clientIdPv=0;
    this.route.paramMap.subscribe((params: ParamMap) => {
      clientIdPv= +params.get('clientId')!
    })
    alert(clientIdPv); */
  }
}

Relevant Code Snippets

declare var $: any;
@Component({
  selector: 'app-sso-authentication',
  templateUrl: './sso-authentication.component.html',
  styleUrls: ['./sso-authentication.component.css'],
  providers: [DataSharingService]
})
export class SSOAuthenticationComponent implements OnInit {
  title = 'SSOAuthUI';
  private readonly _destroying$ = new Subject<void>();
  isIframe = false;
  loginDisplay = false;
  providerAccessToken = '';
  refreshTokenFromRCAPAPI = '';
  accessTokenFromRCAPAPI = '';
  azureTokenResponseGv = '';
  public resultContentObj = new ResultContent();
  safeSrc: SafeResourceUrl;
  clientAppLoginUrl = '';
  callBackUrlFromQueryString = '';
  clientIdFromQueryString = '';
  loginUrlFromQueryString = '';
  isUnAuthorized = '';
  showLoginPopup = '';
  googleRefreshToken = '';
  googleSSOClientId = environment.googleSSOClientId;
  langQS = '';
  appLang: any;
  currentLoggedInUserEmail: any;
  loginFailureCounter:number=0;
  constructor(@Inject(MSAL_GUARD_CONFIG) private msalGuardConfig: MsalGuardConfiguration
    , private ssoAuthService: SSOAuthenticationService
    , private authService: MsalService
    , private msalBroadcastService: MsalBroadcastService
    , private dataShareService: DataSharingService
    , private auzureTokenRespService: AzureTokenResponseService
    , private sanitizer: DomSanitizer
    , private route: ActivatedRoute
    , private googleAutheService: GoogleAuthenticationService
    , private socialAuthService: SocialAuthService
    , private user: UserSessionService
    , private langLoaderSvc: TranslationLoaderService
    , private langSvc: TranslateService
    , private commonUtilSvc: CommonUtilService) {
    let clientId = localStorage.getItem("clienIdLS")!;
    let callbackUrl = localStorage.getItem("callbackUrl_" + clientId)!;
    this.clientAppLoginUrl = localStorage.getItem("loginUrl_" + clientId)!;
    this.LogError("Log.constructor", "clientAppLoginUrl from local storage :" + this.clientAppLoginUrl, clientId);
    this.safeSrc = this.sanitizer.bypassSecurityTrustResourceUrl(callbackUrl);
    //this.route.params.subscribe( params => this.clientAppLoginUrl=params['LoginUrl']);
    this.route.queryParams.subscribe(params => {
      this.callBackUrlFromQueryString = params['CallBackUrl'];
      this.clientIdFromQueryString = params['SSOClientId'];
      this.loginUrlFromQueryString = params['LoginUrl'];
      this.LogError("Log.this.route.queryParams.subscribe", "loginUrlFromQueryString :" + this.loginUrlFromQueryString, this.clientIdFromQueryString);
      this.isUnAuthorized = params['IsUnAuthorized'];
      this.showLoginPopup = params['ShowLoginPopup'];
      this.clientAppLoginUrl = (this.clientAppLoginUrl == null && this.loginUrlFromQueryString != null)
        ? this.loginUrlFromQueryString : this.clientAppLoginUrl;
      this.LogError("Log.this.route.queryParams.subscribe", "clientAppLoginUrl :" + this.clientAppLoginUrl, this.clientIdFromQueryString);
      clientId = (clientId == null && this.clientIdFromQueryString != null) ? this.clientIdFromQueryString : clientId;
      if(params['LN']!=null && params['LN']!= undefined && params['LN'].length>0) //check if request url has params['LN'] multiple times
      {
          if(params['LN'].toString().indexOf(',')!=-1)  //check if request url has params['LN'] multiple times means (ex: en-us,en-us,en-us), then split by comma and get 1st value
            this.langQS= params['LN'].toString().split(',')[0]; 
          else
            this.langQS = params['LN'].toString();
      }
      else
          this.langQS='en-us'; //default lang
      
    });
  }

  InitLang() {
    const lang = this.user.getAppLanguage();
    const browserLang = navigator.language.toLowerCase();
    if (lang === browserLang) {
      this.langLoaderSvc.use(lang);
      this.appLang = lang;
    } else {
      this.langLoaderSvc.use(lang);
      this.appLang = browserLang;
    }
  }
  disableGoogleButton(callbackUrl: string) {
    if (callbackUrl != null && callbackUrl.indexOf("rmail.") != -1)
      $("#pnlGoogleBtn").addClass("disabledbutton");

  }
  displaySpinner() {

    $('#pnlSpinner').css("display", "block");
  }

  hideSpinner() {
    $('#pnlSpinner').css("display", "none");
  }
  displaySSOButtons() {
    
    $('#pnlSSOButtons').css("display", "block");
  }
  hideSSOButtons() {
    
    $('#pnlSSOButtons').attr('style', 'display: none !important');
  }
  

  googleBtnOnMouseOver() {
    alert('hi');
    $("#googleBtn").attr('title', 'Sign in with Google');
    //document.getElementById('googleBtn')?.setAttribute('title', 'Sign in with Google');
  }

  logRequestUrlAllQueryStringValues() {
    var currentReqUrl = window.location.href;
    this.LogError("Log.ngOnInit.logRequestUrlAllQueryStringValues", "Current Request Url: " + currentReqUrl + " ", this.clientIdFromQueryString);
    const urlString = window.location.search; // Get the query string part of the URL
    const searchParams = new URLSearchParams(urlString);

    // Loop using forEach
    searchParams.forEach((value, key) => {
      console.log(`Key: ${key}, Value: ${value}`);
      this.LogError("Log.ngOnInit.logRequestUrlAllQueryStringValues", "key:" + key + " " + "value:" + value, this.clientIdFromQueryString);
    });


  }

  getLoginUrlFragment(): string {
    let loginUrl: any = this.loginUrlFromQueryString;
    var currentReqUrl = window.location.href;
    const urlString = window.location.search; // Get the query string part of the URL
    const searchParams = new URLSearchParams(urlString);

    let loginUrlFragment = '';
    let i: number = 0;
    // Loop using forEach
    searchParams.forEach((value, key) => {
      if (key.toLowerCase() != "SSOClientId".toLowerCase()
        && key.toLowerCase() != "CallBackUrl".toLowerCase()
        && key.toLowerCase() != "LoginUrl".toLowerCase()
        && key.toLowerCase() != "ShowLoginPopup".toLowerCase()
        && key.toLowerCase() != "errorReason".toLowerCase()
      ) {
        if (i == 0)
          loginUrlFragment += key + "=" + value;
        else
          loginUrlFragment += "&" + key + "=" + value;

        i++;
      }

    });

    return loginUrlFragment;
  }
  ngOnInit(): void {

    this.logRequestUrlAllQueryStringValues();

    if (this.langQS != null && this.langQS != '')
      this.appLang = this.langQS;
    else
      this.appLang = 'en-us';
    this.langSvc.setDefaultLang(this.appLang);
    localStorage.setItem('appLang', this.appLang);
    this.InitLang();
    $('#divProcessingCommon').css("display", "none");
    //this.disableGoogleButton(this.callBackUrlFromQueryString); //this is temp fix only
    this.displaySSOButtons();
    this.getGoogleTokenResponseAndRedirectToClientApplication();
    this.addHandleRedirectPromise();
    this.addMsalEventListeners();

  }

  private addHandleRedirectPromise() : void{
    this.authService.instance.handleRedirectPromise()
    .then((response) => {
       if (response && response.account) {
          this.authService.instance.setActiveAccount(response.account);
      }
      this.currentLoggedInUserEmail = this.authService.instance.getActiveAccount();
      console.log('Initial Account:', this.currentLoggedInUserEmail);
      this.LogError("Log.addHandleRedirectPromise.handleRedirectPromise", "User Account: " + this.currentLoggedInUserEmail, this.clientIdFromQueryString)
    })
      .catch((error: string) => {
        console.error('Error handling redirect promise:', error);
        this.LogError("Log.addHandleRedirectPromise.handleRedirectPromise.Error", error, this.clientIdFromQueryString)
      });
  }

//Region Microsoft login popup code
//Code addded for login success, login failure , inprogress event types to call in ngOnInit method
  private addMsalEventListeners(): void {
    
    this.msalBroadcastService.msalSubject$
      .pipe(filter((msg: EventMessage) => msg.eventType === EventType.LOGIN_SUCCESS))
      .subscribe((msg: EventMessage) => {
        const payload = msg.payload as AuthenticationResult;
        this.authService.instance.setActiveAccount(payload.account);
        
        const loginAccount = payload.account;
        this.currentLoggedInUserEmail = loginAccount?.username;
        this.LogError("Log.addMsalEventListeners.Result", "User Account: " + loginAccount?.username + " " + this.convertObjToJsonString(msg), this.clientIdFromQueryString);
        

      },

      error => {
        var errorDesc = error.toString();
        let errorReason = '';
        this.displayActualErrorInConsole(errorDesc, "addMsalEventListeners.LOGIN_SUCCESS");
        if (typeof errorDesc == "string" && errorDesc.indexOf(ErrorReason.CONSENT_REQUIRED) > -1) {
          errorReason = ErrorReason.CONSENT_REQUIRED;
          this.redirectToClientAppLoginWhenErrorOccured(errorReason);
        }
        else {
          errorReason = ErrorReason.UNKNOWN_ERROR_OCCURED;
          this.redirectToClientAppLoginWhenErrorOccured(errorReason);
        }
      }
    );
    
    
   
   
    this.msalBroadcastService.msalSubject$
      .pipe(filter((msg: EventMessage) => msg.eventType === EventType.LOGIN_FAILURE || msg.eventType === EventType.ACQUIRE_TOKEN_FAILURE))
      .subscribe((msg: EventMessage) => {
        console.error('MSAL Popup Login Failure:', msg);
        const errorJson = JSON.stringify(msg, Object.getOwnPropertyNames(msg));
        const errorObjJson=JSON.stringify(msg?.error);
        this.LogError("Log.addMsalEventListeners.FailureEvent", "User Account: " + this.currentLoggedInUserEmail + " Error Json: " + errorJson , this.clientIdFromQueryString)
        this.LogError("Log.addMsalEventListeners.FailureEvent1", "User Account: " + this.currentLoggedInUserEmail + " Error:" + errorObjJson, this.clientIdFromQueryString);
        
        
      });


    this.msalBroadcastService.inProgress$
      .pipe(filter((status: InteractionStatus) => status === InteractionStatus.None)
            ,takeUntil(this._destroying$)
            )
      .subscribe(() => {
        this.setLoginDisplay();
        this.checkAndSetActiveAccount();
      });
    }

    
//End region Microsoft login popup code
  generateIframeHtmlElement() {
    this.hidePnlComingSoon();
    let clientId = this.getSSOClientId();

    let callbackUrl = this.getCallBackUrl();
    this.clearLocalStorageTokenResponse();
    this.generateDataShareIframeHtmlElement(callbackUrl, clientId);
  }

  convertObjToJsonString(obj: any) {
    let response;
    response = JSON.stringify(obj);
    return response;
  }


  //#endregion

  CancelCurrentRequest() {
    window.location.href = this.loginUrlFromQueryString; //+'?errorReason='+ErrorReason.USER_CANCELLED_CURRENT_REQUEST;

  }

  ngOnDestroy(): void {
    this._destroying$.next(undefined);
    this._destroying$.complete();
  }
  
  async AzureSignIn() {
    
    this.generateIframeHtmlElement();
    
    if (!this.isUserAlreadyLoggedin()) {
      console.log("first time login");
      this.LogError("Log.AzureSignIn", "first time login", this.clientIdFromQueryString);
      await this.firstTimeLoginAndDisplayLoginPopup();

    }
    else if (this.isUserAlreadyLoggedin() &&
      (this.isUnAuthorized != null && this.isUnAuthorized == 'Y')
      || (this.showLoginPopup != null && this.showLoginPopup == 'Y')
    ) {
      console.log('Already logged in, unauthorized request/unable to login due to some reason case, show loginpopup');
      this.LogError("Log.AzureSignIn", "Already logged in.Unauthorized request/unable to login due to some reason case,show loginpopup", this.clientIdFromQueryString);
      //this.promptForPasswordForUnAuthroizedRequest();
      this.chooseAccountToLoginForAlreadyLoggedIn(true);
    }
    else if (this.isUserAlreadyLoggedin()) {
      console.log("AlreadyLoggedIn");
      this.LogError("Log.AzureSignIn", "AlreadyLoggedIn", this.clientIdFromQueryString);

      this.chooseAccountToLoginForAlreadyLoggedIn(false);
    }
  }

  async firstTimeLoginAndDisplayLoginPopup() {
    
    this.LogError("Log.firstTimeLoginAndDisplayLoginPopup", "Begining of the method", this.clientIdFromQueryString);
    await this.loginPopup();
    this.hideSSOButtons();
    

    /* Moved below block to ngoninit */
    
    
    this.LogError("Log.firstTimeLoginAndDisplayLoginPopup", "End of the method", this.clientIdFromQueryString);  
    
      
    
  }

  chooseAccountToLoginForAlreadyLoggedIn(IsUnAuthorized: boolean) {
    this.hideSSOButtons();
    if (IsUnAuthorized) {
      console.log("already logged in, but unauthorized, autologin");
      this.LogError("Log.chooseAccountToLoginForAlreadyLoggedIn", "already logged in, but unauthorized", this.clientIdFromQueryString);
    }
    else {
      console.log("already logged in");
      this.LogError("Log.chooseAccountToLoginForAlreadyLoggedIn", "already logged in", this.clientIdFromQueryString);
    }


    let scopeId = environment.scopeId

    var request = {
      scopes: ["api://" + scopeId + "/.default"],
      prompt: 'select_account'
    };

    this.authService.loginPopup(request)
      .subscribe((result: AuthenticationResult) => {
        console.log(result);


        const payload = result as AuthenticationResult;
        const loginAccount = payload.account;
        this.currentLoggedInUserEmail = loginAccount?.username;
        this.LogError("Log.chooseAccountToLoginForAlreadyLoggedIn.loginPopup.Result", "User Account: " + loginAccount?.username + " " + this.convertObjToJsonString(result), this.clientIdFromQueryString);
        this.LogError("Log.chooseAccountToLoginForAlreadyLoggedIn.loginPopup.AuthenticationResult", "User Account: " + loginAccount?.username, this.clientIdFromQueryString);
        this.authService.instance.setActiveAccount(payload.account);
        this.LogError("Log.chooseAccountToLoginForAlreadyLoggedIn.loginPopup.Response", this.convertObjToJsonString(payload), this.clientIdFromQueryString);
        let azureTokenRespObj = this.getAzureTokenResponseObjectForAquireTokenSilent(payload);//this.getAzureTokenResponseObject(payload);
        let azuretokenresp = this.getAzureTokenJsonResponseAsString(azureTokenRespObj);

        //this.azureTokenResponseGv=azuretokenresp;

        if (azuretokenresp != null && azuretokenresp != undefined && azuretokenresp.length>0)
        {
            this.LogError("Log.chooseAccountToLoginForAlreadyLoggedIn.loginPopup.If", "User Account: " + loginAccount?.username + " " , this.clientIdFromQueryString);
            this.redirectToClientApplication(azuretokenresp);
        }
        else {
          let errorReason = ErrorReason.AZURE_TOKEN_EMPTY_RESPONSE_ACQUIRE_TOKEN_POPUP;//"Azure token response is empty from acquireTokenPopup method";
          this.LogError("Log.chooseAccountToLoginForAlreadyLoggedIn.loginPopup.Else", "User Account: " + loginAccount?.username + " " + "ErrorReason:"+ errorReason, this.clientIdFromQueryString);
          this.redirectToClientAppLoginWhenErrorOccured(errorReason);
        }
        //this.redirectToClientApplication();
      },
        error => {

          //if(IsUnAuthorized)
          //{
          var errorDesc = error.toString();
          let errorReason = ''
          this.LogError("Log.chooseAccountToLoginForAlreadyLoggedIn.loginPopup.Error", "User Account: " + this.currentLoggedInUserEmail + this.convertObjToJsonString(errorDesc), this.clientIdFromQueryString);
          //alert(typeof errorDesc);
          if (typeof errorDesc == "string" && errorDesc.indexOf(ErrorReason.USER_CANCELLED) > -1) {
            errorReason = ErrorReason.USER_CANCELLED_FROM_UNAUTHORIZED_AT_LOGIN_POPUP;
            this.redirectToClientAppLoginWhenErrorOccured(errorReason);
            //this.acquireTokenSilientImpl(request);
          }
          else {
            this.displayActualErrorInConsole(errorDesc, "chooseAccountToLoginForAlreadyLoggedIn.loginPopup.Request.Error");
            errorReason = ErrorReason.UNKNOWN_ERROR_OCCURED;
            this.redirectToClientAppLoginWhenErrorOccured(errorReason);
          }

          //}
          

        },
      );

  }


  getAzureTokenResponseObject(payload: AuthenticationResult) {
    let refreshtokenObj = <RefreshTokenResponseModel>this.auzureTokenRespService.getRefreshTokenJsonFromLocalStorage();
    this.currentLoggedInUserEmail = payload.account?.username;
    this.LogError("Log.getAzureTokenResponseObject.refreshtokenObj", "User Account : " + payload.account?.username! + " " + this.convertObjToJsonString(refreshtokenObj), this.clientIdFromQueryString);
    let azureTokenRespObj = new AzureTokenResponseModel();
    azureTokenRespObj.accesstoken = payload.accessToken;//payload.idToken;
    azureTokenRespObj.useremail = payload.account?.username!;
    azureTokenRespObj.username = payload.account?.name!;
    azureTokenRespObj.idtoken = payload.idToken;
    azureTokenRespObj.refreshtoken = refreshtokenObj.secret;
    azureTokenRespObj.ssotype = environment.azureADProvider;
    this.LogError("Log.getAzureTokenResponseObject.azureTokenRespObj", "User Account : " + azureTokenRespObj.useremail + " " + this.convertObjToJsonString(azureTokenRespObj), this.clientIdFromQueryString);
    return azureTokenRespObj;
  }

  getAzureTokenResponseObjectForAquireTokenSilent(payload: AuthenticationResult) {
    /* let refreshtokenObj=<RefreshTokenResponseModel>this.auzureTokenRespService.getRefreshTokenJsonFromLocalStorage()
    let azureTokenRespObj=new AzureTokenResponseModel();
    azureTokenRespObj.accesstoken= payload.accessToken;
    azureTokenRespObj.useremail=payload.account?.username!;
    azureTokenRespObj.username=payload.account?.name!;
    azureTokenRespObj.idtoken=payload.idToken;
    azureTokenRespObj.refreshtoken=refreshtokenObj.secret; 
    azureTokenRespObj.ssotype=environment.azureADProvider;
    return azureTokenRespObj; */
    return this.getAzureTokenResponseObject(payload);
  }

  setLoginDisplay() {
    this.loginDisplay = this.authService.instance.getAllAccounts().length > 0;
    if (this.loginDisplay)
      $('#btnLogout').css('display', 'block');

  }

  checkAndSetActiveAccount() {
    /**
     * If no active account set but there are accounts signed in, sets first account to active account
     * To use active account set here, subscribe to inProgress$ first in your component
     * Note: Basic usage demonstrated. Your app may require more complicated account selection logic
     */
    let activeAccount = this.authService.instance.getActiveAccount();

    if (!activeAccount && this.authService.instance.getAllAccounts().length > 0) {
      let accounts = this.authService.instance.getAllAccounts();
      this.authService.instance.setActiveAccount(accounts[0]);

      this.LogError("Log.checkAndSetActiveAccount", "Multiple accounts, setting active account to: " + accounts[0], this.clientIdFromQueryString);
    }
  }

  //If it is coming back after a failure we can prompt for username/password
  async loginPopupPromptForUserNamAndPwd() {
    
    if(this.loginFailureCounter<2)
    {
          this.loginFailureCounter= this.loginFailureCounter+1;
          let scopeId = environment.scopeId;
        var request = {
          scopes: ["api://" + scopeId + "/.default"],
          prompt: 'login'
        };

        if (this.msalGuardConfig.authRequest) {
          try {
                const response: AuthenticationResult = await firstValueFrom(
                this.authService.loginPopup(request)
              );
              const loginAccount = response.account;
              this.currentLoggedInUserEmail = loginAccount?.username;
              this.LogError("Log.loginPopupPromptForUserNamAndPwd.msalGuardConfig.authRequest", "User Account: " + loginAccount?.username, this.clientIdFromQueryString);
              this.authService.instance.setActiveAccount(response.account); 
          } catch (error: any) {
              const errorDesc = error?.message || error.toString();
              this.displayActualErrorInConsole(errorDesc, "loginPopupForUserNamAndPwd.Request.Error");
          }
            
          
        } else {
              try {
                const response: AuthenticationResult = await firstValueFrom(
                this.authService.loginPopup(request)
              );
              const loginAccount = response.account;
              this.currentLoggedInUserEmail = loginAccount?.username;
              this.LogError("Log.loginPopupPromptForUserNamAndPwd.msalGuardConfig.authRequest.Else", "User Account: " + loginAccount?.username, this.clientIdFromQueryString);
              this.authService.instance.setActiveAccount(response.account); 
            } catch (error: any) {
                const errorDesc = error?.message || error.toString();
                this.displayActualErrorInConsole(errorDesc, "loginPopupForUserNamAndPwd.msalGuardConfig.authRequest.Else.Error");
                let errorReason = ErrorReason.LOGIN_POPUP_FAILURE;
                this.redirectToClientAppLoginWhenErrorOccured(errorReason);
            }
          

        }
    }
    else
    {
      this.LogError("Log.loginPopupPromptForUserNamAndPwd.Else", "User Account: " + this.currentLoggedInUserEmail +"Login Attempts exceeded more than 1 time, Login attempts tried: "+ this.loginFailureCounter, this.clientIdFromQueryString);
      let errorReason = ErrorReason.AZURE_TOKEN_EMPTY_RESPONSE_FIRST_TIME_LOGIN;
      this.redirectToClientAppLoginWhenErrorOccured(errorReason);
    }
    

  }

  handleLoginResponse(response:AuthenticationResult)
  {
      const loginAccount = response.account;
      this.currentLoggedInUserEmail = loginAccount?.username;
      this.LogError("Log.handleLoginResponse", "User Account: " + loginAccount?.username, this.clientIdFromQueryString);
      this.authService.instance.setActiveAccount(response.account); 

      let azureTokenRespObj = this.getAzureTokenResponseObject(response);
      let azuretokenresp = this.getAzureTokenJsonResponseAsString(azureTokenRespObj);
      if (azuretokenresp != null && azuretokenresp != undefined && azuretokenresp.length > 0) {
        localStorage.setItem("azureTokenRespLocalStorage", azuretokenresp);
        this.LogError("Log.handleLoginResponse.LOGIN_SUCCESS", "RedirectToClient. User Account: " + loginAccount?.username, this.clientIdFromQueryString);
        this.redirectToClientApplication(azuretokenresp); // This posts the message.
      }
      else //LOGIN_SUCCESS fallback scenario
      {
        let errorReason = ErrorReason.AZURE_TOKEN_EMPTY_RESPONSE_FIRST_TIME_LOGIN; //"Azure token response is empty for First time azure login";
        this.LogError("Log.handleLoginResponse.LOGIN_SUCCESS.Else", "User Account: " + loginAccount?.username, this.clientIdFromQueryString);          
        this.redirectToClientAppLoginWhenErrorOccured(errorReason);
        //this.loginPopupPromptForUserNamAndPwd();
        //this.invokeAcquireTokenSilent();
      }
  }
   async loginPopup() {

    let scopeId = environment.scopeId;
    var request = {
      scopes: ["api://" + scopeId + "/.default"],
      prompt: 'select_account'
    };
    var requestWithPwd = {
      scopes: ["api://" + scopeId + "/.default"],
      prompt: 'login'
    };
    const maxAzureLoginRetries : number= environment.maxAzureLoginRetries; //3 configured in environment.ts file
    const maxAzureLoginDelay : number = environment.maxAzureLoginDelay;
    const maxAzureLoginWithSelectRetries : number = environment.maxAzureLoginWithSelectRetries;

    if (this.msalGuardConfig.authRequest) {
      for (let i = 0; i < maxAzureLoginRetries; i++) 
      {  
           
          try { 
                this.LogError("Log.loginPopup.For.Try","User Account: " + this.currentLoggedInUserEmail + " RetryCount: "+ i.toString(),this.clientIdFromQueryString);
                const currentRequest = (i < maxAzureLoginWithSelectRetries) ? request : requestWithPwd;
                const response: AuthenticationResult = await firstValueFrom(
                    this.authService.loginPopup(currentRequest)
                );
                this.handleLoginResponse(response);
                this.LogError("Log.loginPopup.For.Try","User Account: " + this.currentLoggedInUserEmail + " successful login in RetryCount: "+ i.toString() ,this.clientIdFromQueryString);
                break;
          } catch (error: any) {
              const errorDesc = error?.message || error.toString();
              this.LogError("Log.loginPopup.For.catch","User Account: " + this.currentLoggedInUserEmail + " RetryCount: "+ i.toString() + " Error:"+ errorDesc,this.clientIdFromQueryString);
              this.displayActualErrorInConsole(errorDesc, "loginPopup.For.catch");
             
                    
                    //this.LogError("Log.loginPopup.LOGIN_FAILURE.Else", "User Account: " + this.currentLoggedInUserEmail + " " + errorDesc.error?.message, this.clientIdFromQueryString);
              if (errorDesc?.includes('popups are blocked in the browser'))
              {
                this.redirectToClientAppLoginWhenErrorOccured(ErrorReason.POPUP_BLOCKED_IN_BROWSER);
                break;
              }
                            
              if (i==maxAzureLoginRetries-1) //3-1=2
              {
                this.redirectToClientAppLoginWhenErrorOccured(ErrorReason.GENERIC_LOGIN_FAILURE);
              }
              else
                await delayLoop(maxAzureLoginDelay); //2sec
          }
        }
        

      
    } else {
          try {
            const response: AuthenticationResult = await firstValueFrom(
            this.authService.loginPopup(request)
          );
          const loginAccount = response.account;
          this.currentLoggedInUserEmail = loginAccount?.username;
          this.LogError("Log.msalGuardConfig.authRequest.Else", "User Account: " + loginAccount?.username, this.clientIdFromQueryString);
          this.authService.instance.setActiveAccount(response.account); 
        } catch (error: any) {
            const errorDesc = error?.message || error.toString();
            this.displayActualErrorInConsole(errorDesc, "loginPopup.msalGuardConfig.authRequest.Else.Error");
            let errorReason = ErrorReason.LOGIN_POPUP_FAILURE;
            this.redirectToClientAppLoginWhenErrorOccured(errorReason);
        }
       

    }

  }

  displayPnlComingSoon() {
    $('#pnlComingSoon').css("display", "block");
    setTimeout(function () {
      $('#pnlComingSoon').css("display", "none");
    }, 2000);

  }

  hidePnlComingSoon() {
    $('#pnlComingSoon').css("display", "none");
  }
  
  redirectToClientAppLoginWhenErrorOccured(errorDesc: string) {
    console.log("redirectToClientAppLoginWhenErrorOccured error is  " + errorDesc);
    this.LogError("Log.redirectToClientAppLoginWhenErrorOccured", "User Account: " + this.currentLoggedInUserEmail + " error is :" + errorDesc, this.clientIdFromQueryString);
    this.clearLocalStorage();
    this.LogError("Log.redirectToClientAppLoginWhenErrorOccured.Request", "User Account: " + this.currentLoggedInUserEmail + " Client App Login Url: " + this.clientAppLoginUrl + "?errorReason=" + errorDesc, this.clientIdFromQueryString);
    let loginUrlFragment = this.getLoginUrlFragment();
    if (loginUrlFragment.length > 0) {
      let loginUrl = this.clientAppLoginUrl.indexOf('?') > 0 ? this.clientAppLoginUrl + '&' + loginUrlFragment + "&errorReason=" + errorDesc
        : this.clientAppLoginUrl + "?" + loginUrlFragment + "&errorReason=" + errorDesc;
      this.LogError("Log.redirectToClientAppLoginWhenErrorOccured.ModifiedLoginUrl", "User Account: " + this.currentLoggedInUserEmail + " Client App Login Url: " + loginUrl, this.clientIdFromQueryString);
      window.location.href = loginUrl;
    }
    else
      window.location.href = this.clientAppLoginUrl + "?errorReason=" + errorDesc;
  }

  displayActualErrorInConsole(errorDesc: string, errorOrigin: string) {
    console.log(errorOrigin+ ":" + ' Actual error is:' + errorDesc);
    //console.log(errorDesc);
    this.LogError("Log.displayActualErrorInConsole." + errorOrigin, "User Account: " + this.currentLoggedInUserEmail + " " + errorDesc, this.clientIdFromQueryString);
  }

  logout(popup?: boolean) {
    let returnUrl = window.location.href;
    let clientId = this.getSSOClientId();

    let callbackUrl = this.getCallBackUrl();

    if (popup) {
      this.authService.logoutPopup({

        mainWindowRedirectUri: returnUrl

      });
    } else {
      this.authService.logoutRedirect();
    }
  }
  

  generateDataShareIframeHtmlElement(callbackUrl: string, ssoClientId: string) {
    //removeIframeElement(ssoClientId);
    const iframe = document.createElement('IFRAME');
    iframe.id = 'receiverSOS1_' + ssoClientId;
    //iframe.id = 'receiverIframe';
    iframe.style.display = "none";
    iframe.style.width = "1px";
    //iframe.sandbox="allow-storage-access-by-user-activation allow-scripts allow-same-origin"
    (<HTMLIFrameElement>iframe).src = callbackUrl;
    document.body.appendChild(iframe);

  }

  postLocalStorageData(linkURL: any, portal: any) {

    this.dataShareService.postCrossDomainMessage(linkURL, portal);
  }

  isUserAlreadyLoggedin() {
    let isLoggedIn = this.authService.instance.getAllAccounts().length > 0;
    if (isLoggedIn) {
      let accountInfo = this.authService.instance.getAllAccounts();
      for (let item of accountInfo) {

        this.LogError("Log.isUserAlreadyLoggedin", "UserName: " + item?.username, this.clientIdFromQueryString);
      }

    }
    else {
      this.LogError("Log.isUserAlreadyLoggedin", "First time login, no user account already logged in", this.clientIdFromQueryString);
    }
    /* if(isLoggedIn)
      this.setAzureTokenResponseFromCookie(); */
    return isLoggedIn;
  }


  getssoClientId() {

    return this.clientIdFromQueryString;
  }

  getCallBackUrl() {


    return this.callBackUrlFromQueryString;
  }

  getAzureClientId() {
    return environment.azureSSOClientId;
  }
  getAzureTokenJsonResponseAsString(azureTokenRespObj: AzureTokenResponseModel) {
    let response: string = "";
    response = JSON.stringify(azureTokenRespObj);
    let userEmail = azureTokenRespObj?.useremail;
    this.currentLoggedInUserEmail = userEmail;
    this.LogError("Log.getAzureTokenJsonResponseAsString.Response", "User Account : " + userEmail + " " + response, this.clientIdFromQueryString);

    return response;
  }
  clearLocalStorageTokenResponse() {
    let clientId = this.getssoClientId();

    localStorage.removeItem("azuretokenresp_" + this.getAzureClientId());
  }

  redirectToClientApplication(azureTokenResponse: string) {

    this.onLoad(azureTokenResponse);
    //this.dataShareService.postCrossDomainMessage("test");
  }


  onLoad(azureTokenResponse: string) {
    let clientId = this.getssoClientId();
    let callbackUrl = this.getCallBackUrl();
    //alert(callbackUrl);
    let azuretokenResp = azureTokenResponse;

    const date = new Date();

    //POST MESSAGE
    console.log('is window:load');
    var iframe = document.getElementById("receiverSOS1_" + clientId);
    //const iframe = document.getElementById("receiverIframe");
    console.log(iframe);
    //alert(iframe)
    //if (iframe == null) { return; }
    if (iframe == null) {
      this.generateDataShareIframeHtmlElement(callbackUrl, clientId);
      iframe = document.getElementById("receiverSOS1_" + clientId);
    }
    const iWindow = (iframe as HTMLIFrameElement).contentWindow!;
    let msgToPost = JSON.stringify(azuretokenResp);
    let userEmail = this.currentLoggedInUserEmail;
    this.LogError("Log.onLoad", "User Account : " + userEmail + " CallbackUrl is :" + callbackUrl, clientId);
    if (msgToPost != null && msgToPost != '') {
      console.log('Azure token response exists');
      this.LogError("Log.onLoad", "User Account : " + userEmail + " Azure token response exists and msgToPost is :" + msgToPost, clientId);
    }
    else {
      console.log('Azure token response not exists');
      this.LogError("Log.onLoad", "User Account : " + userEmail + " Azure token response does not exists." + msgToPost, clientId);
    }


    //let domainUrl=getDomainUrl(callbackUrl);


    this.displaySpinner();
    /* iWindow.addEventListener("load", function() {
      console.log("Finish");
      this.alert('iframe loaded');
     });
     */
     try {
        if (iframe != null && msgToPost != null && msgToPost != '') {
          this.clearLocalStorage();
          iWindow.postMessage(msgToPost, '*');
          setTimeout(function () {
            //iWindow.postMessage(msgToPost, callbackUrl);
            //alert(callbackUrl);
            console.log('callbackUr is ' + callbackUrl);
            window.location.href = callbackUrl;
          }, 1000);
        }
        else {
          let errorDesc = '';
          if (iframe == null) {
            errorDesc = ErrorReason.COULD_NOT_ABLE_TO_SEND_MESSAGE;
            this.LogError("Log.onLoad.Post.SendMessageFail", "User Account : " + userEmail +  " Error: COULD_NOT_ABLE_TO_SEND_MESSAGE",this.clientIdFromQueryString);
            this.redirectToClientAppLoginWhenErrorOccured(errorDesc);
          }
          else if (msgToPost == null || msgToPost == '') {
            errorDesc = ErrorReason.AZURE_TOKEN_EMPTY_RESPONSE_BEFORE_SENDING_MESSAGE;
            this.LogError("Log.onLoad.Post.EmptyMsgToPost", "User Account : " + userEmail +  " Error: msgToPost is empty",this.clientIdFromQueryString);
            this.redirectToClientAppLoginWhenErrorOccured(errorDesc);
          }

        }
    } catch (error: any) {
      const errorCatchDesc = error?.message || error.toString();
      this.LogError("Log.onLoad.Post.Error", "User Account : " + userEmail +  " Error:"+ errorCatchDesc,this.clientIdFromQueryString);
      this.displayActualErrorInConsole(errorCatchDesc, "Log.onLoad.Post.Error");
      const errorReturnDesc = ErrorReason.UNEXPECTED_ERROR_DURING_TOKEN_POST_MESSAGE;
      this.redirectToClientAppLoginWhenErrorOccured(errorReturnDesc);
    }
  }

  clearLocalStorage() {
    localStorage.clear();
  }

  setCookie(name: string, value: string, expireDays: number, path: string = '') {
    let d: Date = new Date();
    d.setTime(d.getTime() + expireDays * 24 * 60 * 60 * 1000);
    let expires: string = `expires=${d.toUTCString()}`;
    let cpath: string = path ? `; path=${path}` : '';
    document.cookie = `${name}=${value}; ${expires}${cpath}`;
  }

  LogError(type: string, logText: string, clientId: string) {
   
    this.commonUtilSvc.LogError(type, logText, clientId);
     
  }


  private getCookie(name: string) {
    let ca: Array<string> = document.cookie.split(';');
    let caLen: number = ca.length;
    let cookieName = `${name}=`;
    let c: string;

    for (let i: number = 0; i < caLen; i += 1) {
      c = ca[i].replace(/^\s+/g, '');
      if (c.indexOf(cookieName) == 0) {
        return c.substring(cookieName.length, c.length);
      }
    }
    return '';
  }

  private deleteCookie(name: string) {
    this.setCookie(name, '', -1);
  }


}

//Refernces - testPauseLoop
//https://medium.com/@chrisjr06/why-and-how-to-avoid-await-in-a-for-loop-32b86722171
function delayLoop(ms: number): Promise<void> {
  return new Promise(resolve => setTimeout(resolve, ms));
}
 

function getDomainUrl(callbackUrl: any) {
  var str = callbackUrl,
    delimiter = '/',
    start = 3,
    tokens = str.split(delimiter).slice(start),
    result = tokens.join(delimiter);

  console.log(result)

  // To get the substring BEFORE the nth occurence
  var tokens2 = str.split(delimiter).slice(0, start),
    result2 = tokens2.join(delimiter); // this

  console.log(result2)
  return result2
}

function removeIframeElement(ssoClientId: string) {
  document.getElementById('receiverSOS1_' + ssoClientId)?.remove();
}

function detectPopupBlocker() {

  var isPopupblocker = false;
  var windowUrl = 'about:blank';
  var windowId = 'TestPopup_' + new Date().getTime();
  var windowFeatures = 'left=0%,top=0%,width=0.1%,height=0.1%';
  var windowRef = window.open(windowUrl, windowId, windowFeatures);

  if (!windowRef) {
    //alert('A popup blocker was detected. Please turn it off to use this application.');
    //return false;
    $('#pnlPopupblockerMsg').css("display", "block");
    isPopupblocker = true;
  }
  else {
    // No popup blocker was detected...
    windowRef.close();
    isPopupblocker = false;
    $('#pnlPopupblockerMsg').css("display", "none");
    //document.getElementById('pageContent').style.display = 'block';
  }

  return isPopupblocker;
}

function postMessageToClientAppIfUserAlreadyLoggedin(clientId: string, callbackUrl: string, azuretokenResp: string) {
  alert('postMessageToClientApp');
  //const iframeWin = document.getElementById('h5-iframe').contentWindow;
  const iframe = document.getElementById("receiverSOS1_" + clientId);
  //const iframe = document.getElementById("receiverIframe");
  console.log(iframe);
  //let azuretokenResp= this.azureTokenResponseGv;
  var msgToPost = JSON.stringify(azuretokenResp);
  //alert(iframe)
  if (iframe == null) { return; }
  const iWindow = (iframe as HTMLIFrameElement).contentWindow!;
  window.addEventListener(
    'message',
    (e) => {
      const { data } = e;
      console.log('receive page load', data);
      if (data.pageLoaded) {
        /* iframeWin.postMessage("hello", '*'); */
        // setTimeout(function () {
        iWindow.postMessage("rrrrr", '*');

        /* if(callbackUrl.indexOf('?IsAzureSSO=Y')==-1)
            callbackUrl=callbackUrl+"?IsAzureSSO=Y"; */
        //alert('callbackUrl'+callbackUrl);
        window.location.href = callbackUrl;
        //}, 1000);

      }
      else {
        alert('iframe page is not loaded');
        setTimeout(function () {
          iWindow.postMessage('not', '*');

          /* if(callbackUrl.indexOf('?IsAzureSSO=Y')==-1)
              callbackUrl=callbackUrl+"?IsAzureSSO=Y"; */
          //alert('callbackUrl'+callbackUrl);
          window.location.href = callbackUrl;
        }, 1000);
      }
    },
    false,
  );
}

function displaySpinner() {
  throw new Error('Function not implemented.');
}

Reproduction Steps

  1. login via sso microsoft login pop-up.
  2. be idle for some time in the same tab.
  3. logout of the application.
  4. try to login, user is not logged-in directly. pop-up is disappearing.

Expected Behavior

use has to login after idle/multiple time login and logouts.

Identity Provider

Entra ID (formerly Azure AD) / MSA

Browsers Affected (Select all that apply)

Chrome, Edge

Regression

No response

Activity

added
bug-unconfirmedA reported bug that needs to be investigated and confirmed
questionCustomer is asking for a clarification, use case or information.
on Apr 29, 2025
changed the title [-]Browser auth error and user cancelled the flow for SSO MSAL-angular.[/-] [+]BrowserAuthError and user cancelled the flow for SSO MSAL-angular.[/+] on Apr 30, 2025
tnorling

tnorling commented on Jul 1, 2025

@tnorling
Collaborator

Do you have a Cross-Origin-Opener-Policy set on your site? This can cause the behavior you're describing. I'd also suggest updating to the latest version as v2 is missing > 2 years worth of updates

sneti-rpost

sneti-rpost commented on Jul 10, 2025

@sneti-rpost
Author

Hi @tnorling we did move to latest version still we're facing same issue. let us know if any steps to take care from our side.

tnorling

tnorling commented on Jul 10, 2025

@tnorling
Collaborator

Please check if you have a COOP policy set on your site.

sneti-rpost

sneti-rpost commented on Jul 14, 2025

@sneti-rpost
Author

Hi @tnorling,
We've cross verified for COOP policy, we're not adding any header from our side. below is the workflow we're following. Please suggest if any.

  1. We're having multiple client application which will redirect to one common site which has Google and Microsoft SSO implemented.
  2. when user tries to Login using SSO, then user's are facing the above said issue.

thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs: Attention 👋Awaiting response from the MSAL.js teambug-unconfirmedA reported bug that needs to be investigated and confirmedconfidential-clientIssues regarding ConfidentialClientApplicationsmsal-angularRelated to @azure/msal-angular packagemsal-browserRelated to msal-browser packageno-issue-activityIssue author has not responded in 5 daysquestionCustomer is asking for a clarification, use case or information.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @tnorling@sneti-rpost

        Issue actions

          BrowserAuthError and user cancelled the flow for SSO MSAL-angular. · Issue #7725 · AzureAD/microsoft-authentication-library-for-js