AzureAD / microsoft-authentication-library-for-js

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

BrowserAuthError: interaction_in_progress: Error while logging in everytime #3063

Closed spavithra5 closed 3 years ago

spavithra5 commented 3 years ago

Library

Framework

Description

I am following the sample in https://github.com/Azure-Samples/ms-identity-b2c-javascript-spa Everytime i login, i get this error message. When i refresh the page it's working as expected.

Error Message

 BrowserAuthError: interaction_in_progress: Interaction is currently in progress. Please ensure that this interaction has been completed before calling an interactive API.
    at BrowserAuthError.AuthError [as constructor] (http://localhost:44305/assets/main.js:759:24)
    at new BrowserAuthError (http://localhost:44305/assets/main.js:7301:28)
    at Function../node_modules/@azure/msal-browser/dist/index.es.js.BrowserAuthError.createInteractionInProgressError (http://localhost:44305/assets/main.js:7362:16)
    at PublicClientApplication../node_modules/@azure/msal-browser/dist/index.es.js.ClientApplication.preflightInteractiveRequest (http://localhost:44305/assets/main.js:10778:36)
    at PublicClientApplication.<anonymous> (http://localhost:44305/assets/main.js:10148:45)
    at step (http://localhost:44305/assets/main.js:310:23)
    at Object.next (http://localhost:44305/assets/main.js:291:53)
    at http://localhost:44305/assets/main.js:284:71
    at new Promise (<anonymous>)
    at __awaiter (http://localhost:44305/assets/main.js:280:12)

MSAL Configuration

const msalConfig = {
    auth: {
        clientId: "----", 
        authority:  "https://{tenant}/b2clogin.com/{tenant}.onmicrosoft.com/{signinpolicy}", 
        knownAuthorities: ["{tenant}.b2clogin.com"], 
        redirectUri: "http://localhost:44305/index.html", 

    },
    cache: {
        cacheLocation: "sessionStorage",
        storeAuthStateInCookie: false, 
    },
};

const loginRequest = {
    scopes: ["openid", "https://{tenant}.onmicrosoft.com/{tenantid}/api/User.Read"],
};

const tokenRequest = {
    scopes: ["https://{tenant}.onmicrosoft.com/{tenantid}/api/User.Read"], 
    forceRefresh: false, 
};

Reproduction steps

1) Login to ADB2C 2) Error occurs in console 3) 3) Refresh the page, works as expected

const msalInstance = new msal.PublicClientApplication(msalConfig);
msalInstance.handleRedirectPromise()
    .then(handleResponse)
    .catch(error => {
        console.log(error);
    });

function handleResponse(response) {
    if (response !== null) {
        accountId = response.account.homeAccountId;
        username = response.account.username;
        sessionStorage.setItem("idToken", response.idToken);
    } else {
        selectAccount();
    }
}
function login() {
        msalInstance.loginRedirect(loginRequest);
}
function logOut() {
    const logoutRequest = {
        account: msalInstance.getAccountByHomeId(accountId),
    };   
    msalInstance.logout(logoutRequest);
}
function getTokenRedirect(request) {
    request.account = msalInstance.getAccountByHomeId(accountId);    
    return msalInstance.acquireTokenSilent(request)
        .then((response) => {
           /* if (!response.accessToken || response.accessToken === "") {
                    throw new msal.InteractionRequiredAuthError;
            } */
            return handleResponse(response);
        })
        .catch(error => {
            console.log(error);
            if (error instanceof msal.InteractionRequiredAuthError) {
                return msalInstance.acquireTokenRedirect(request);
            } else {
                console.log(error);   
            }
    });
}

Expected behavior

Identity Provider

Browsers/Environment

Regression

Security

Source

patrick-jones commented 3 years ago

I experienced a similar issue: #2403

You may find that the various redirect methods return null with the expectation that the response doesn't matter because the page is redirecting anyway. However, there is usually a slight delay while the redirect happens and your script will continue to execute with MSAL in an unexpected state. Long story short, try something like this:

            log('Authenticating via redirect...');
            return _authApp.loginRedirect(request).then(
                // loginRedirect sometimes returns too quickly and you see erroneous state on the page before the browser
                // redirects. This is to guard against that spurious condition
                () => new Promise((resolve) => setTimeout(resolve, 60000))
            );
pkanher617 commented 3 years ago

@spavithra5 Are you calling login() or getTokenRedirect() when the page loads, or as a result of some user interaction? I think what may be happening here is that one of these APIs is being called before the handleRedirectPromise() has a chance to finish, which is causing the app to throw this error. If you can wait until handleRedirectPromise() has resolved you should not have these errors anymore.

spavithra5 commented 3 years ago

@patrick-jones and @pkanher617 Thank you for your response. I went through the code, once again, and there was a place where login is called again before the handleRedirectPromise is resolved. For now, i have commented it out. So this error is not occuring. But ideally for our application, during the login itself, API is called, I am not sure how to handle that scenario because in React within the Componentwillmount and componentdidmount, API is called, so ideally it's being called before the token is obtained through login, so i get the "Interaction in progress error" . Any suggestions on how to handle it?

pkanher617 commented 3 years ago

It depends on how you are calling the API, but ideally you could do

handleRedirectPromise().then(resp => {
   if (resp) {
      // use resp.accessToken to make the API call
  } else {
     // use getAccount APIs to check if your account is there
     // if you have an account, call acquireTokenSilent() to get the token and renew it if it is expired, then use the token in the API call
     // if you do not have an account, you are not signed in and should present a login screen or kick off login automatically
  }
});

I highly recommend taking a look at the msal-react library as it takes care of a lot of this for you. Reading through the docs for msal-browser and msal-react may also help.

spavithra5 commented 3 years ago

Thank you for your kind response. I will try this. But in the npm website it's mentioned that msal-react is under development. We do not recommend using this in a production environment yet. So is it fine to use it?

github-actions[bot] commented 3 years ago

This issue has not seen activity in 14 days. If your issue has not been resolved please leave a comment to keep this open. It will be closed in 7 days if it remains stale.

github-actions[bot] commented 3 years ago

This issue has been closed due to inactivity. If this has not been resolved please open a new issue. Thanks!