BrowserAuthError: interaction_in_progress: Interaction is currently in progress.

Iheb Jandoubi 25 Reputation points
2023-10-26T10:23:37.7666667+00:00

for my SPA , i 'am using msal for authentification. i got this error :

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.
    at BrowserAuthError.AuthError [as constructor] (AuthError.ts:77:1)
    at new BrowserAuthError (BrowserAuthError.ts:227:1)
    at BrowserAuthError.createInteractionInProgressError (BrowserAuthError.ts:303:1)
    at BrowserCacheManager.setInteractionInProgress (BrowserCacheManager.ts:1026:1)
    at ClientApplication.preflightInteractiveRequest (ClientApplication.ts:861:1)
    at ClientApplication.preflightBrowserEnvironmentCheck (ClientApplication.ts:845:1)
    at PublicClientApplication.<anonymous> (ClientApplication.ts:301:1)
    at step (gradeVideoWithMsal.jsx:77:1)
    at Object.next (gradeVideoWithMsal.jsx:77:1)
    at gradeVideoWithMsal.jsx:77:1

this is my index.jsx : User's image

and this is is my app.jsx :

  const { instance } = useMsal();
  useEffect(() => {
    const callbackId = instance.addEventCallback((event) => {
      if (
        (event.eventType === EventType.LOGIN_SUCCESS ||
          event.eventType === EventType.ACQUIRE_TOKEN_SUCCESS) &&
        event.payload.account
      ) {
     
        if (
          compareIssuingPolicy(
            event.payload.idTokenClaims,
            b2cPolicies.names.editProfile
          )
        ) {
          // retrieve the account from initial sing-in to the app
          const originalSignInAccount = instance
            .getAllAccounts()
            .find(
              (account) =>
                account.idTokenClaims.oid === event.payload.idTokenClaims.oid &&
                account.idTokenClaims.sub === event.payload.idTokenClaims.sub &&
                compareIssuingPolicy(
                  account.idTokenClaims,
                  b2cPolicies.names.signUpSignIn
                )
            );

          let signUpSignInFlowRequest = {
            authority: b2cPolicies.authorities.signUpSignIn.authority,
            account: instance.getActiveAccount(),
          };

          // silently login again with the signUpSignIn policy
          instance.ssoSilent(signUpSignInFlowRequest);
        }

        if (
          compareIssuingPolicy(
            event.payload.idTokenClaims,
            b2cPolicies.names.forgotPassword
          )
        ) {
          let signUpSignInFlowRequest = {
            authority: b2cPolicies.authorities.signUpSignIn.authority,
            scopes: [
              ...protectedResources.apiVideo.scopes.read,
              ...protectedResources.apiVideo.scopes.write,
              ...protectedResources.apiSpeech.scopes.read,
              ...protectedResources.apiSpeech.scopes.write,
              ...protectedResources.apiAdminVideo.scopes.read,
              ...protectedResources.apiAdminVideo.scopes.write,
            ],
          };
          instance.loginRedirect(signUpSignInFlowRequest);
        }
      }

      if (event.eventType === EventType.LOGIN_FAILURE) {
        console.log("we are here")
        // Check for forgot password error
        // Learn more about AAD error codes at https://docs.microsoft.com/en-us/azure/active-directory/develop/reference-aadsts-error-codes
        if (event.error && event.error.errorMessage.includes("AADB2C90118")) {
          const resetPasswordRequest = {
            authority: b2cPolicies.authorities.forgotPassword.authority,
            scopes: [],
          };
          instance.loginRedirect(resetPasswordRequest);
        }
      }
    });

    return () => {
      if (callbackId) {
        instance.removeEventCallback(callbackId);
      }
    };
    // eslint-disable-next-line
  }, [instance]);


and this is my navigation bar : in where i handle sign in , navigation bar is a component of home page , which url is http://localhost:3000 which is a correct redirect uri :

export const NavigationBar = () => {
    const { instance, inProgress } = useMsal();
     let activeAccount;
     console.log(inProgress)

     if (instance) {
        console.log(instance)
         activeAccount = instance.getActiveAccount();
         
     }
    

  const userEmail = activeAccount?.idTokenClaims?.emails?.[0]; // Adjust this depending on the actual structure of your idTokenClaims
  const emailDomain = userEmail?.split('@')[1];

 

    const handleLoginRedirect = () => {
        console.log(inProgress)
        instance.loginRedirect(loginRequest).catch((error) => console.log(error));
    };

    const handleLogoutRedirect = () => {
        instance.logoutRedirect();
    };

    
    return (
        <>
            <Navbar style={{ backgroundColor: '#039d90' }} variant="dark" className="navbarStyle">
                <a className="navbar-brand" href="/">
                   XGOL
                </a>
                <AuthenticatedTemplate>
    {emailDomain === 'xgol.pro' ? (
        <>
            <Nav.Link className="navbarButton" href="/records/processed">
                processed speeches
            </Nav.Link>
            <Nav.Link className="navbarButton" href="/records/unprocessed">
                unprocessed speeches
            </Nav.Link>
            <div className="collapse navbar-collapse justify-content-end">
              
                <DropdownButton
                    variant="warning"
                    drop="start"
                    title={activeAccount && activeAccount.name ? activeAccount.name : 'Unknown'}
                >
                    
                    <Dropdown.Item as="button" onClick={handleLogoutRedirect}>
                        Sign out using Redirect
                    </Dropdown.Item>
                </DropdownButton>
            </div>
        </>
    ) : (
        <>
            <Nav.Link className="navbarButton" href="/recordSpeech">
                Record Video
            </Nav.Link>
            <Nav.Link className="navbarButton" href="/records">
                My videos
            </Nav.Link>
            <Nav.Link className="navbarButton" href="/addSpeech">
                Add Speech
            </Nav.Link>
            <div className="collapse navbar-collapse justify-content-end">
               
                <DropdownButton
                    variant="warning"
                    drop="start"
                    title={activeAccount && activeAccount.name ? activeAccount.name : 'Unknown'}
                >
                  
                    <Dropdown.Item as="button" onClick={handleLogoutRedirect}>
                        Sign out using Redirect
                    </Dropdown.Item>
                </DropdownButton>
            </div>
        </>
    )}
</AuthenticatedTemplate>

                <UnauthenticatedTemplate>
                    <div className="collapse navbar-collapse justify-content-end">
                        <DropdownButton variant="secondary" className="ml-auto" drop="start" title="Sign In">
                          
                            <Dropdown.Item as="button" onClick={handleLoginRedirect}>
                                Sign in using Redirect
                            </Dropdown.Item>
                        </DropdownButton>
                    </div>
                </UnauthenticatedTemplate>
            </Navbar>
        </>

to fetch some data for my api i have the following hook :

/**
 * Custom hook to call a web API using bearer token obtained from MSAL
 * @param {PopupRequest} msalRequest 
 * @returns 
 */
const useFetchWithMsal = (msalRequest) => {
    const { instance, inProgress } = useMsal();
    console.log(inProgress)
    const dispatch = useDispatch()
    const error = "Unexpected error has occured! Try Later again"
    const { result, error: msalError } = useMsalAuthentication(InteractionType.Popup, {
        ...msalRequest,
        account: instance.getActiveAccount(),
        redirectUri: '/redirect'
    });
   

    /**
     * Execute a fetch request with the given options
     * @param {string} method: GET, POST, PUT, DELETE
     * @param {String} endpoint: The endpoint to call
     * @param {Object} data: The data to send to the endpoint, if any 
     * @returns JSON response
     */
    const execute = async (method, endpoint, data = null) => {
        if (msalError) {
        
            dispatch(gradeVideoFail(error))
            return;
        }
        if (result) {
            try {
                let response = null;
                dispatch(gradeVideoRequest())
                const headers = new Headers();
                const bearer = `Bearer ${result.accessToken}`;            
                headers.append("Authorization", bearer);
            
               
            
                if (data) headers.append('Content-Type', 'application/json');

                let options = {
                    method: method,
                    headers: headers,
                    body: data ? JSON.stringify(data) : null,
                };

                response = await (await fetch(endpoint, options)).json();
                     
                dispatch(gradeVideoSuccess(response))

                if (response.error) {
                    
                    dispatch(gradeVideoFail(response.error));
                  } else {
                    dispatch(gradeVideoSuccess(response))
                  }
            } catch (e) {
                dispatch(gradeVideoFail(error))
                throw e;
            }
        }
    };

    return {
   
        execute: useCallback(execute, [result, msalError,dispatch]), // to avoid infinite calls when inside a `useEffect`
    };
};

export default useFetchWithMsal;
Microsoft Entra ID
Microsoft Entra ID
A Microsoft Entra identity service that provides identity management and access control capabilities. Replaces Azure Active Directory.
21,656 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Christian Uden 0 Reputation points
    2023-10-26T10:31:35.34+00:00

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.