AzureAD / microsoft-authentication-library-for-js

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

Continuous looping from MSAL handleRedirectStart - Returning access token #7195

Closed billgirten closed 3 months ago

billgirten commented 4 months ago

Core Library

MSAL.js (@azure/msal-browser)

Core Library Version

3.6.0

Wrapper Library

MSAL React (@azure/msal-react)

Wrapper Library Version

2.0.8

Public or Confidential Client?

Public

Description

Intermittently, users to the www.buysportscards.com are witnessing what appears to be a looping web page. After careful examination of the MSAL logs, it appears that MSAL is infinitely firing an event to handle an access token returned by Microsoft.

This causes our web application to react to the handler, causing the state to change, forcing the page to re-render.

Error Message

No errors are encountered.

MSAL Logs

[Wed, 10 Jul 2024 22:06:02 GMT] : [] : @azure/msal-browser@3.11.1 : Info - Emitting event: msal:initializeStart main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:02 GMT] : [] : @azure/msal-browser@3.11.1 : Info - Emitting event: msal:initializeEnd main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:02 GMT] : [] : @azure/msal-browser@3.11.1 : Info - initialize has already been called, exiting early. main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:02 GMT] : [] : @azure/msal-browser@3.11.1 : Info - Emitting event: msal:handleRedirectStart main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:02 GMT] : [01909eae-9fbe-7e2b-a9a3-e2760d35c891] : msal.js.browser@3.11.1 : Info - handleRedirectPromise called but there is no interaction in progress, returning null. main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:02 GMT] : [] : @azure/msal-browser@3.11.1 : Info - Emitting event: msal:handleRedirectEnd main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:02 GMT] : [] : @azure/msal-react@2.0.14 : Info - MsalProvider - msal:handleRedirectStart results in setting inProgress from startup to handleRedirect main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:02 GMT] : [] : @azure/msal-react@2.0.14 : Info - MsalProvider - msal:handleRedirectEnd results in setting inProgress from handleRedirect to none main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:12 GMT] : [] : @azure/msal-browser@3.11.1 : Info - Emitting event: msal:initializeStart main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:12 GMT] : [] : @azure/msal-browser@3.11.1 : Info - Emitting event: msal:initializeEnd main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:12 GMT] : [] : @azure/msal-browser@3.11.1 : Info - initialize has already been called, exiting early. main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:12 GMT] : [] : @azure/msal-browser@3.11.1 : Info - Emitting event: msal:handleRedirectStart main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-react@2.0.14 : Info - MsalProvider - msal:handleRedirectStart results in setting inProgress from startup to handleRedirect main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-browser@3.11.1 : Info - BrowserCacheManager: addTokenKey - idToken added to map main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-browser@3.11.1 : Info - BrowserCacheManager: addTokenKey - accessToken added to map main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-browser@3.11.1 : Info - BrowserCacheManager: addTokenKey - refreshToken added to map main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-browser@3.11.1 : Info - Emitting event: msal:loginSuccess main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-browser@3.11.1 : Info - Emitting event: msal:handleRedirectEnd main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-react@2.0.14 : Info - MsalProvider - msal:handleRedirectEnd results in setting inProgress from handleRedirect to none 2main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-browser@3.11.1 : Info - Emitting event: msal:acquireTokenStart main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getAccessToken - Returning access token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-browser@3.11.1 : Info - Emitting event: msal:acquireTokenSuccess 2main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-browser@3.11.1 : Info - Emitting event: msal:acquireTokenStart main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getAccessToken - Returning access token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-browser@3.11.1 : Info - Emitting event: msal:acquireTokenSuccess 2main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:13 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:20 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:20 GMT] : [] : @azure/msal-browser@3.11.1 : Info - Emitting event: msal:acquireTokenStart main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:20 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getAccessToken - Returning access token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:20 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:20 GMT] : [] : @azure/msal-browser@3.11.1 : Info - Emitting event: msal:acquireTokenSuccess main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:20 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token 2main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:21 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:22 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:23 GMT] : [] : @azure/msal-browser@3.11.1 : Info - Emitting event: msal:acquireTokenStart main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:23 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getAccessToken - Returning access token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:23 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:23 GMT] : [] : @azure/msal-browser@3.11.1 : Info - Emitting event: msal:acquireTokenSuccess 2main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:23 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:23 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:23 GMT] : [] : @azure/msal-browser@3.11.1 : Info - Emitting event: msal:acquireTokenStart main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:23 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getAccessToken - Returning access token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:23 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:23 GMT] : [] : @azure/msal-browser@3.11.1 : Info - Emitting event: msal:acquireTokenSuccess 2main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:23 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:32 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:32 GMT] : [] : @azure/msal-browser@3.11.1 : Info - Emitting event: msal:acquireTokenStart main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:33 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:33 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:33 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getAccessToken - Returning access token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:33 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:33 GMT] : [] : @azure/msal-browser@3.11.1 : Info - Emitting event: msal:acquireTokenSuccess main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:33 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:33 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:33 GMT] : [] : @azure/msal-browser@3.11.1 : Info - Emitting event: msal:acquireTokenStart main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:33 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getAccessToken - Returning access token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:33 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:33 GMT] : [] : @azure/msal-browser@3.11.1 : Info - Emitting event: msal:acquireTokenSuccess 2main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:33 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:33 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:33 GMT] : [] : @azure/msal-browser@3.11.1 : Info - Emitting event: msal:acquireTokenStart main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:33 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getAccessToken - Returning access token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:33 GMT] : [] : @azure/msal-common@14.8.1 : Info - CacheManager:getIdToken - Returning ID token main.5a9f4e0e.js:2 [Wed, 10 Jul 2024 22:06:33 GMT] : [] : @azure/msal-browser@3.11.1 : Info - Emitting event: msal:acquireTokenSuccess

Network Trace (Preferrably Fiddler)

MSAL Configuration

export const msalConfig: Configuration = {
    auth: {
        clientId: process.env.REACT_APP_CLIENT_ID || '', // This is the ONLY mandatory field that you need to supply.
        authority: b2cPolicies.authorities.signUpSignIn.authority, // Choose SUSI as your default authority.
        knownAuthorities: [b2cPolicies.authorityDomain || ''], // Mark your B2C tenant's domain as trusted.
        redirectUri: process.env.REACT_APP_REDIRECT_URI, // You must register this URI on Azure Portal/App Registration. Defaults to window.location.origin
        postLogoutRedirectUri: process.env.REACT_APP_POST_LOGOUT_REDIRECT_URI, // Indicates the page to navigate after logout.
        navigateToLoginRequestUrl: true, // If "true", will navigate back to the original request location before processing the auth code response.
    },
    cache: {
        cacheLocation: 'localStorage', // Configures cache location. "sessionStorage" is more secure, but "localStorage" gives you SSO between tabs.
        storeAuthStateInCookie: false, // Set this to "true" if you are having issues on IE11 or Edge
    },
    system: {},
};

Relevant Code Snippets

useEffect(() => {
        const account = instance.getActiveAccount();
        if (account !== null) {
            const tokenRequest: SilentRequest = {
                account: account as AccountInfo | undefined,
                scopes: AUTH_REQUESTS.LOGIN.scopes,
            };
            instance
                .acquireTokenSilent(tokenRequest)
                .then(async response => {
                    if (response.accessToken) {
                        const apiConfig: Configuration = {...apiAuthConfig, accessToken: response.accessToken};
                        sellersLockerSearchApi = new SellersLockerSearchApi(apiConfig);
                    }
                })
                // eslint-disable-next-line @typescript-eslint/no-unused-vars
                .catch(error => {
                    addToast({
                        severity: 'error',
                        message: 'User must be Signed In.',
                        contextKey: 'Authentication',
                    });
                    setTimeout(() => {
                        authFunc.logout();
                    }, 5000);
                });
        }
    }, [instance]);

Reproduction Steps

  1. User Sign-In to www.buysportscards.com
  2. User navigates to Inventory page
  3. Snippet above executes and periodically goes into an endless loop - every second MS returns access token.

Expected Behavior

Access token should be returned upon request.

Identity Provider

Azure B2C Custom Policy

Browsers Affected (Select all that apply)

Chrome, Firefox, Edge, Safari

Regression

No response

Source

External (Customer)

Tijmene commented 4 months ago

I am experiencing a similar issue!

tnorling commented 3 months ago

This causes our web application to react to the handler, causing the state to change, forcing the page to re-render.

This sounds like this is the cause of your loop rather than the result. If your whole page is re-rendering that will cause your useEffect hook to run again which will invoke acquireTokenSilent again and that will emit the event again.

Can you provide more context around what your event handler is doing and why? You likely should not be re-rendering the entire page based on a token call succeeding.

@Tijmene I would suggest opening your own issue with more details so we can focus on your specific usage

billgirten commented 3 months ago

tnorling,

The problem is that this effect is intermittent - not consistent.

Here is the useEffect hook that is inside of the AuthContext:

` useEffect(() => { const eventCallbackId = instance.addEventCallback(async event => { if (event.eventType === EventType.LOGIN_START) { console.log('msal helper >>> LOGIN_START'); dispatch({type: reducerActions.SET_LOGIN_INPROGRESS}); } if (event.eventType === EventType.LOGIN_SUCCESS && event.payload) { console.log('msal helper >>> LOGIN_SUCCESS'); const payload = event.payload as AuthenticationResult; const accessToken = payload.accessToken; const account = payload.account; instance.setActiveAccount(account); dispatch({ type: reducerActions.SET_ACCESS_TOKEN_AND_ACCOUNT, payload: {accessToken, account}, }); } if (event.eventType === EventType.LOGIN_FAILURE) { console.log('msal helper >>> LOGIN_FAILURE'); }

        if (event.eventType === EventType.ACQUIRE_TOKEN_SUCCESS) {
            console.log('msal helper >>> ACQUIRE_TOKEN_SUCCESS');
            const payload = event.payload as AuthenticationResult;
            const accessToken = payload.accessToken;
            if (localStorage.getItem('accessToken') !== accessToken) {
                localStorage.setItem('accessToken', accessToken);
                dispatch({
                    type: reducerActions.SET_ACCESS_TOKEN,
                    payload: {accessToken},
                });
            }
        }

        if (event.eventType === EventType.ACQUIRE_TOKEN_FAILURE) {
            console.log('msal helper >>> ACQUIRE_TOKEN_FAILURE');
        }
    });

    return () => {
        if (eventCallbackId) {
            instance.removeEventCallback(eventCallbackId);
        }
    };
}, [instance]);`
tnorling commented 3 months ago

You do not need to and should not store the access token yourself in localstorage. MSAL.js handles caching tokens for you and you should invoke acquireTokenSilent each time you need to use the token, if it's cached and valid it will be returned from the cache.

billgirten commented 3 months ago

Thank you, Thomas.