AzureAD / microsoft-authentication-library-for-js

Microsoft Authentication Library (MSAL) for JS
http://aka.ms/aadv2
MIT License
3.6k stars 2.64k forks source link

BrowserAuthError: interaction_in_progress - Unable to fix, regardles of solutions found #3950

Closed aikobeyers closed 3 years ago

aikobeyers commented 3 years ago

Core Library

MSAL.js v2 (@azure/msal-browser)

Core Library Version

2.16.1

Wrapper Library

MSAL Angular (@azure/msal-angular)

Wrapper Library Version

2.0.2

Description

I'm implementing security for the applications at the company I'm working at right now. I followed your example found here and got it working for the first application. I went on to implement it for the next application, which is basically the same one, just talks to a different api, but the complexity is the same. After possibly doing something wrong I keep getting the error:

core.js:6157 ERROR Error: Uncaught (in promise): BrowserAuthError: interaction_in_progress: Interaction is currently in progress. Please ensure that this interaction has been completed before calling an interactive API. For more visit: aka.ms/msaljs/browser-errors. BrowserAuthError: interaction_in_progress: Interaction is currently in progress. Please ensure that this interaction has been completed before calling an interactive API. For more visit: aka.ms/msaljs/browser-errors. I found several other posts that said to clear the caches, storages etc... But none of it works. All it does is prompt me to log in again, only to fill in the sessionStorage back with the same entries, amongst them the entry that says msal.442edcf7-9e0c-469b-93fb-daa1839724bd.interaction.status interaction_in_progress. As far as I know I've tried everthing I've found. Also the solution from AzureAD themselves doesn't work.

I'm very new to this so I might have missed something simple, if so, my apologies.

I also posted it on StackOverflow But I thought I'd ask it here as well, as I am really stuck. And again, if it's a really easy solution and I overlooked something simple, my apologies then.

Update

I tried copying the LocalStorage values from the working application and I got it to work. Refreshing works and no errors appear, but when I logout and after it prompted me to login again and I do, then it's right back to the start again.

MSAL Configuration

MsalModule.forRoot(
      new PublicClientApplication({ // MSAL Configuration
        auth: {
          clientId: "442edcf7-9e0c-469b-93fb-daa1839724bd",
          authority: "https://login.microsoftonline.com/81fa766e-a349-4867-8bf4-ab35e250a08f",
          redirectUri: window.location.origin,
        },
        cache: {
          cacheLocation : BrowserCacheLocation.LocalStorage,
          storeAuthStateInCookie: false, // set to true for IE 11
        },
        system: {
          loggerOptions: {
            loggerCallback: () => {},
            piiLoggingEnabled: false
          }
        }
      }), {
        interactionType: InteractionType.Redirect, // MSAL Guard Configuration
      }, {
        protectedResourceMap: new Map([
          [ 'http://localhost:8200/', ['api://442edcf7-9e0c-469b-93fb-daa1839724bd/acces_as_user/Acces-user']],
          [ 'https://ai-display-dev-pcq-dev.bravo-apps.volvocars.biz/', ['api://442edcf7-9e0c-469b-93fb-daa1839724bd/acces_as_user/Acces-user']]
        ]),
        interactionType: InteractionType.Redirect // MSAL Interceptor Configuration
      }
    )

Relevant Code Snippets

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit, OnDestroy{
  isIframe = false;
  loginDisplay = false;

  activeUser = '';

  private readonly onDestroy$ = new Subject<void>()
   isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset)
      .pipe(
        map(result => result.matches),
        shareReplay()
      );

    constructor(
      private breakpointObserver: BreakpointObserver,
      private router: Router,
      @Inject(MSAL_GUARD_CONFIG) private msalGuardConfig: MsalGuardConfiguration,
      private authService: MsalService,
      private msalBroadcastService: MsalBroadcastService,
      private location: Location
      ) {}

  ngOnInit(): void {

    const currentPath = this.location.path();
    // Dont perform nav if in iframe or popup, other than for front-channel logout
    this.isIframe = BrowserUtils.isInIframe() && !window.opener && currentPath.indexOf("logout") < 0; // Remove this line to use Angular Universal
    this.setLoginDisplay();

    this.msalBroadcastService.msalSubject$
      .pipe(
        takeUntil(this.onDestroy$)
      ).subscribe(val => console.log('SUBJEECT', val));

    this.msalBroadcastService.inProgress$
      .pipe(
        tap((status: InteractionStatus) => console.log('MSAL STATUS', status)),
        filter((status: InteractionStatus) => status === InteractionStatus.None),
        takeUntil(this.onDestroy$)
      )
      .subscribe((val) => {
        console.log('SUBBBBBB', val)
        this.setLoginDisplay();
        this.checkAndSetActiveAccount();
      })
  }

  setLoginDisplay() {
    this.loginDisplay = this.authService.instance.getAllAccounts().length > 0;
  }

  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]);
    }

    if(activeAccount) {
      //this.userService.activeUserName = activeAccount.name;
      this.activeUser = activeAccount.name;
    }
  }

  ngOnDestroy() {
    this.onDestroy$.next();
  }

  doLogout(): void{
    this.authService.logoutRedirect();
  }
}

Identity Provider

Azure AD / MSA

Source

External (Customer)

pkanher617 commented 3 years ago

@aikobeyers Are your sessionStorage values being cleared on page load? Or are they remaining in the cache when the page is reloaded? This usually happens when the page is reloaded without a recognizable hash and the values aren't cleared correctly before calling an acquireToken API. If this is happening, we need to figure out why the values in sessionStorage aren't being cleared.

Could you try reproducing the issue with one of our samples as well? This can help us figure out where the issue is happening.

aikobeyers commented 3 years ago

Hi @pkanher617 , the sessionStorage values are not being cleared on page load. I also have no idea why they are put in there, as I configured it to be stored in the localStorage. Also, if I clear the sessionStorage and then reload, the values are put back in. (I also don't have a lot of experience with that and all of my colleagues here are backend developers with no knowlegde of that.)

I will try to reproduce it with your sample as well!

aikobeyers commented 3 years ago

I have also noticed that it automatically redirects me to login, even though I have nowhere specified to do that. I want to have it on a button, but whenever I run and open the app, if the storages and cookies are empty, it automatically prompts me to login.

Update

This is because a url from the ProtectedResourcemap is immediatly called upon opening the app

ghost commented 3 years ago

This issue requires attention from the MSAL.js team and has not seen activity in 5 days. @pkanher617 please follow up.

aikobeyers commented 3 years ago

Hi, @pkanher617 have you perhaps had any time? I don't want to be in your heels but I haven't found anything myself yet.

aikobeyers commented 3 years ago

Update: I've had a breakthrough. If I change the login type to Popup and handle it this way, it's fixed. I can login and logout without any issues. However if I then change it back to Redirect, it's broken again. So for now I'll keep it on Popup. Simple solution, but I hadn't thought of it because I assumed the issue would be occur there as well.

tnorling commented 3 years ago

@aikobeyers If you wish to use redirects please review this doc to understand how redirects work and the additional considerations around handling redirect responses. Please also review this doc for specific instructions regarding the interaction_in_progress error.

ghost commented 3 years ago

@aikobeyers This issue has been automatically marked as stale because it is marked as requiring author feedback but has not had any activity for 5 days. If your issue has been resolved please let us know by closing the issue. If your issue has not been resolved please leave a comment to keep this open. It will be closed automatically in 7 days if it remains stale.