Skip to content

Updating to msal-browser 4.9.0 login doesn't work anymore #7663

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
2 tasks
StantonCoffey89 opened this issue Mar 26, 2025 · 19 comments
Closed
2 tasks

Updating to msal-browser 4.9.0 login doesn't work anymore #7663

StantonCoffey89 opened this issue Mar 26, 2025 · 19 comments
Labels
bug-unconfirmed A reported bug that needs to be investigated and confirmed msal-angular Related to @azure/msal-angular package msal-browser Related to msal-browser package public-client Issues regarding PublicClientApplications question Customer is asking for a clarification, use case or information.

Comments

@StantonCoffey89
Copy link

Core Library

MSAL.js (@azure/msal-browser)

Core Library Version

4.9.0

Wrapper Library

MSAL Angular (@azure/msal-angular)

Wrapper Library Version

4.0.7

Public or Confidential Client?

Public

Description

(please go easy on me, this is my first time submitting a bug report)

Before updating my NPM packages I was able to have my angular application log a user in. After updating, the login processing doesn't work anymore. If I revert my msal-angular and msal-browser packages back to 4.0.7 and 4.8.0, respectively, then the application logs in fine.

Error Message

No response

MSAL Logs

After updating my npm packages, the login process after a redirect seems to get stuck after the "initializeEnd". It doesn't seem to handle the redirect portion and finish logging the user in.

MsalBroadcastService inProgress$ startup
MsalBroadcastService msalSubject$ msal:initializeStart {eventType: 'msal:initializeStart', interactionType: null, payload: null, error: null, timestamp: 1743002095450}
[Wed, 26 Mar 2025 15:14:55 GMT] : [] : @azure/[email protected] : Info - CacheManager:getIdToken - Returning ID token
[Wed, 26 Mar 2025 15:14:55 GMT] : [] : @azure/[email protected] : Info - CacheManager:getIdToken - Returning ID token
Angular is running in development mode.
[Wed, 26 Mar 2025 15:14:55 GMT] : [] : @azure/[email protected] : Info - CacheManager:getIdToken - Returning ID token
MsalBroadcastService msalSubject$ msal:initializeEnd {eventType: 'msal:initializeEnd', interactionType: null, payload: null, error: null, timestamp: 1743002095482}
[Wed, 26 Mar 2025 15:14:55 GMT] : [] : @azure/[email protected] : Info - handleRedirectPromise called but there is no interaction in progress, returning null.

Network Trace (Preferrably Fiddler)

  • Sent
  • Pending

MSAL Configuration

export function loggerCallback(logLevel: LogLevel, message: string) {
    console.log(message);
}

export function MSALInstanceFactory(): IPublicClientApplication {
    return new PublicClientApplication({
        auth: {
            clientId: '<client-id>',
            authority: "https://login.microsoftonline.com/<tenent-id>",
            redirectUri: document.location.origin,
            postLogoutRedirectUri: '/',
        },
        cache: {
            cacheLocation: BrowserCacheLocation.SessionStorage,
        },
        system: {
            allowPlatformBroker: false,
            loggerOptions: {
                loggerCallback,
                logLevel: LogLevel.Info,
                piiLoggingEnabled: true,
            },
        },
    });
}

export function MSALInterceptorConfigFactory(): MsalInterceptorConfiguration {
    const protectedResourceMap = new Map<string, Array<string>>();
    protectedResourceMap.set('<url>', ['<scope>']);
    return {
        interactionType: InteractionType.Redirect,
        protectedResourceMap,
    };
}

export const appConfig: ApplicationConfig = {
    providers: [
        provideZoneChangeDetection({ eventCoalescing: true }),
        provideRouter(routes, withHashLocation()),
        provideHttpClient(withInterceptorsFromDi(), withFetch()),
        {
            provide: HTTP_INTERCEPTORS,
            useClass: MsalInterceptor,
            multi: true,
        },
        {
            provide: MSAL_INSTANCE,
            useFactory: MSALInstanceFactory,
        },
        {
            provide: MSAL_INTERCEPTOR_CONFIG,
            useFactory: MSALInterceptorConfigFactory,
        },
        MsalService,
        MsalGuard,
        MsalBroadcastService
    ]
};

Relevant Code Snippets

async loginAzureAd() {
        return new Promise<boolean>(async (resolve) => {
            this.msalBroadcastService.msalSubject$.subscribe(event => {
                console.log('MsalBroadcastService', 'msalSubject$', event.eventType, (event.error?.cause ?? '') + (event.error?.message ?? ''), event)
            })
            this.msalBroadcastService.inProgress$.subscribe(status => {
                console.log('MsalBroadcastService', 'inProgress$', status)
                if (status == InteractionStatus.None) {
                    let activeAccount = this.msalService.instance.getActiveAccount();
                    if (activeAccount) {
                        console.log('already an active account', activeAccount)
                        resolve(true)
                    } else {
                        let allAccounts = this.msalService.instance.getAllAccounts()
                        if (allAccounts.length == 0) {
                            console.log('no msal accounts')
                            this.msalService.instance.loginRedirect()
                        } else {
                            console.log('activating first account', allAccounts)
                            this.msalService.instance.setActiveAccount(allAccounts[0]);
                            resolve(true)
                        }
                    }
                }
            });
            this.msalService.handleRedirectObservable().subscribe();
        })
    }

Reproduction Steps

  1. update npm packages so msal-angular is 4.0.8 and msal-browser is 4.9.0
  2. running the application the login process gets stuck after a redirect and never gets to an inProgress$ status of "none"
  3. revert npm packages to msal-angular is 4.0.7 and msal-browser is 4.8.0
  4. running the application the login process doesn't get stick after redirect. The progress status gets "none"

Expected Behavior

The following log outputs are what login normally looks like after a redirect back to my page. You can see all the steps happen and the MsalBroadcastService.inProgress$ gets to a state of "none", which I'm expecting.

MsalBroadcastService inProgress$ startup
MsalBroadcastService msalSubject$ msal:initializeStart {eventType: 'msal:initializeStart', interactionType: null, payload: null, error: null, timestamp: 1742999991666}
[Wed, 26 Mar 2025 14:39:51 GMT] : [] : @azure/[email protected] : Info - CacheManager:getIdToken - Returning ID token
[Wed, 26 Mar 2025 14:39:51 GMT] : [] : @azure/[email protected] : Info - CacheManager:getIdToken - Returning ID token
Angular is running in development mode.
[Wed, 26 Mar 2025 14:39:51 GMT] : [] : @azure/[email protected] : Info - CacheManager:getIdToken - Returning ID token
MsalBroadcastService msalSubject$ msal:initializeEnd {eventType: 'msal:initializeEnd', interactionType: null, payload: null, error: null, timestamp: 1742999991692}
[Wed, 26 Mar 2025 14:39:51 GMT] : [] : @azure/[email protected] : Info - CacheManager:getIdToken - Returning ID token
MsalBroadcastService msalSubject$ msal:handleRedirectStart {eventType: 'msal:handleRedirectStart', interactionType: 'redirect', payload: null, error: null, timestamp: 1742999991694}
MsalBroadcastService inProgress$ handleRedirect
[Wed, 26 Mar 2025 14:39:51 GMT] : [0195d2e5-358e-7f58-9785-bc2f05dd8d23] : [email protected] : Info - handleRedirectPromise called but there is no interaction in progress, returning null.
MsalBroadcastService msalSubject$ msal:handleRedirectEnd {eventType: 'msal:handleRedirectEnd', interactionType: 'redirect', payload: null, error: null, timestamp: 1742999991695}
MsalBroadcastService inProgress$ none
[Wed, 26 Mar 2025 14:39:51 GMT] : [] : @azure/[email protected] : Info - CacheManager:getIdToken - Returning ID token
already an active account

Identity Provider

Entra ID (formerly Azure AD) / MSA

Browsers Affected (Select all that apply)

Chrome

Regression

@azure/msal-angular 4.0.7

@StantonCoffey89 StantonCoffey89 added bug-unconfirmed A reported bug that needs to be investigated and confirmed question Customer is asking for a clarification, use case or information. labels Mar 26, 2025
@microsoft-github-policy-service microsoft-github-policy-service bot added the Needs: Attention 👋 Awaiting response from the MSAL.js team label Mar 26, 2025
@github-actions github-actions bot added msal-angular Related to @azure/msal-angular package msal-browser Related to msal-browser package public-client Issues regarding PublicClientApplications labels Mar 26, 2025
@gcrockenberg
Copy link

gcrockenberg commented Mar 26, 2025

I had to roll back to:

"@azure/msal-angular": "4.0.7",
"@azure/msal-browser": "4.8.0",

4.9.0 redirect caching changes caused wiped out accounts on browser refresh. Doesn't happen with 4.8.0.

@klandell
Copy link

I am also unable to login after upgrading to 4.9.0. Same issue of handleRedirectPromise response being null. I am using just @azure/msal-browser with no wrapper lib. Downgrading to 4.8.0 fixes it.

@StantonCoffey89
Copy link
Author

@azure/msal-browser v4.9.1 was released yesterday. I tried that version, but it seems to have the same issue.

@neilzuk
Copy link

neilzuk commented Mar 27, 2025

I'm having the same problem, tried out v4.9.1 and the problem remained. Rolled back to @azure/msal-browser v4.8.0 and @azure/msal-angular v4.0.7 and logins worked as expected with redirect flow. With the new versions the InteractionStatus appears to get stuck in "startup" state.

@yitigerliu
Copy link

I'm having a slightly different issue, but potentially related. After logging out and redirecting, I get stuck in the handleRedirect state. After trying it with the samples and older versions, it appears that the problematic area was introduced in the handleRedirectPromiseInternal function as part of Redirect flow temporary cache refactor (#7648).

@plamber
Copy link

plamber commented Mar 31, 2025

I'm having the same problem, tried out v4.9.1 and the problem remained. Rolled back to @azure/msal-browser v4.8.0 and @azure/msal-angular v4.0.7 and logins worked as expected with redirect flow. With the new versions the InteractionStatus appears to get stuck in "startup" state.

We had to rollback to @azure/msal-browser v4.8.0. We are also using the redirect flow.

@kimpham301
Copy link

I'm also having the issue for my react app where redirecting results in a loop, neither v4.9.0 and v4.8.0 work, I have to revert back to v4.7.0

@pascual-cano-allhuman
Copy link

I'm also having the same issue with msal-react and msal-browser 4.9.1, I had to revert back to 4.8.0

@wgebczyk
Copy link

wgebczyk commented Apr 1, 2025

aaaaaand... they silently killed 4.9.x - no word in this issue :D LOL!

@sameerag
Copy link
Member

sameerag commented Apr 1, 2025

We are working on reproducing on our end, we are not seeing it in our samples. If someone can share steps to repro this for msal-browser (msal-angular is shared in the issue desc), including msal configuration, is the migration done with reloading the page and the APIs used, it will be helpful to sort this early.

The deprecation announcement is made in response to the issues reported here to ensure other folks are not impacted.

@microsoft-github-policy-service microsoft-github-policy-service bot added Needs: Author Feedback Awaiting response from issue author and removed Needs: Attention 👋 Awaiting response from the MSAL.js team labels Apr 1, 2025
@lalimasharda
Copy link
Contributor

Hey @StantonCoffey89 I am able to reproduce an issue with the interaction status not clearing out properly after user logs out (logoutRedirect) and then logs back in using the acquireTokenRedirect for msal-browser. Is this the same scenario you are facing or anyone else here is? If you can provide a full MSAL trace logs from the console, that would be helpful in confirming this use case.

@klandell
Copy link

klandell commented Apr 2, 2025

I have a pretty simple use case. I hope this can help with debugging.

On location change, if the there is an account, the content renders, otherwise the login function of my AuthProvider is called. This worked very well in 4.8, and as mentioned, const res = await c.handleRedirectPromise(); is always null in 4.9.

e.g.

useEffect(() => {
  if (!account && !isLoggingIn) {
    startLogin(async () => {
      await login(location);
    });
  }
}, [account, isLoggingIn, login, location]);

file: "~/lib/auth/msal-client";

import { BrowserCacheLocation, createStandardPublicClientApplication } from "@azure/msal-browser";

import { getConfig } from "~/lib/app-config";

const baseURL = window.location.origin;

export default (() => {
  const config = getConfig();
  return createStandardPublicClientApplication({
    auth: {
      clientId: config.AZURE_CLIENT_ID,
      authority: `https://login.microsoftonline.com/${config.AZURE_TENANT_ID}`,
      redirectUri: `${baseURL}/auth/redirect`,
      postLogoutRedirectUri: `${baseURL}/auth/logout-success`,
      navigateToLoginRequestUrl: false,
    },
    cache: { cacheLocation: BrowserCacheLocation.SessionStorage },
  });
})();

export const getApiScopes = () => {
  const config = getConfig();
  return [`api://${config.AZURE_CLIENT_ID}/default`];
};

export const getMsScopes = () => ["User.Read"];

export const getScopes = () => [...getApiScopes(), ...getMsScopes()];

file: "~/components/ux/authentication/Authentication/AuthenticationProvider"

import { ReactNode, use, useCallback, useEffect, useState } from "react";

import { EventType } from "@azure/msal-browser";
import { Location, NavigateFunction } from "react-router";

import { AuthenticationContext } from "~/components/ux/authentication/AuthenticationContext";
import msalClient, { getScopes } from "~/lib/auth/msal-client";
import HttpError, { HttpStatus } from "~/lib/error/http-error";

type State = { to: string };

export default function AuthenticationProvider(props: { children?: ReactNode }) {
  const c = use(msalClient);

  const [account, setAccount] = useState(() => {
    let active = c.getActiveAccount();
    if (!active) {
      const all = c.getAllAccounts();
      if (all.length === 1) {
        active = all[0];
        c.setActiveAccount(active);
      }
    }
    return active;
  });

  useEffect(() => {
    const cid = c.addEventCallback((ev) => {
      if (ev.eventType === EventType.LOGOUT_SUCCESS) {
        c.setActiveAccount(null);
      }
    });
    return () => {
      if (cid) c.removeEventCallback(cid);
    };
  }, [c]);

  const login = useCallback(
    async (location: Location) => {
      if (!account) {
        await c.clearCache();
        await c.loginRedirect({
          state: encodeState({ to: location.pathname + location.search + location.hash }),
          scopes: getScopes(),
        });
      }
    },
    [account, c],
  );

  const logout = useCallback(async () => {
    if (account) {
      await c.logoutRedirect({ account });
    }
  }, [account, c]);

  const handleRedirect = useCallback(
    async (navigate: NavigateFunction) => {
      try {
        const res = await c.handleRedirectPromise();
        if (res) {
          const { account, state } = res;

          c.setActiveAccount(account);
          setAccount(account);
          if (state) {
            const to = decodeState(state)?.to;
            navigate(to ?? "/");
          }
        } else {
          throw new HttpError(HttpStatus.Unauthorized);
        }
      } catch (err) {
        console.error(err);
        throw new HttpError(HttpStatus.Unauthorized, undefined, { cause: err });
      }
    },
    [c],
  );

  const value = {
    account,
    login,
    logout,
    handleRedirect,
  };

  return <AuthenticationContext.Provider value={value} {...props} />;
}

function encodeState(state: State) {
  return window.btoa(JSON.stringify(state));
}

function decodeState(str: string) {
  return JSON.parse(window.atob(str)) as State;
}

file: "~/components/ux/authentication/AuthenticationContext"

import { createContext } from "react";

import { AccountInfo } from "@azure/msal-browser";
import { Location, NavigateFunction } from "react-router";

type AuthenticationState = {
  account: AccountInfo | null;
  login: (location: Location) => Promise<void>;
  logout: () => Promise<void>;
  handleRedirect: (navigate: NavigateFunction) => Promise<void>;
};

export const AuthenticationContext = createContext<AuthenticationState | null>(null);

file: "~/components/ux/authentication/CompleteAuthentication"

This is the page for the route that matches the authentication redirect URI. It calls the handler to complete authentication in the auth provider.

import { useEffect, useTransition } from "react";

import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router";

import AbsoluteFill from "~/components/ux/AbsoluteFill";
import FillLoader from "~/components/ux/FillLoader";
import useAuthentication from "~/hooks/use-authentication";

export default function CompleteAuthentication() {
  const { account, handleRedirect } = useAuthentication();
  const [isHandlingRedirect, startHandleRedirect] = useTransition();

  const navigate = useNavigate();
  const { t: uxt } = useTranslation("ux");

  useEffect(() => {
    if (!account && !isHandlingRedirect) {
      startHandleRedirect(async () => {
        await handleRedirect(navigate);
      });
    }
  }, [account, isHandlingRedirect, handleRedirect, navigate]);

  return (
    <AbsoluteFill>
      <FillLoader label={uxt("authentication.loadingLabel")} />
    </AbsoluteFill>
  );
}

@StantonCoffey89
Copy link
Author

Here are 2 trace outputs. One where I'm able to login successfully, the other where login fails.

Both scenarios start with a browser with no users logged in.

The failure scenario (v4.9.1) gets stuck after the MsalService initialization steps end. If you look at my "loginAzureAd()" function above you'll see that I'm waiting for the "inProgress$" status to change to "None" for me to call the "loginRedirect()" function. But the status never changes.

The success scenario (v4.8.0) is successful because the MsalService initialization steps end AND the "inProgress$" status changes to a value of "None" meaning I can now call the "loginRedirect()" function.

successful-login-sequence-v4.0.7-v4.8.0-1743603538226.log
failure-login-sequence-v4.0.8-v4.9.1-1743604266578.log

@microsoft-github-policy-service microsoft-github-policy-service bot added Needs: Attention 👋 Awaiting response from the MSAL.js team and removed Needs: Author Feedback Awaiting response from issue author labels Apr 2, 2025
@maaaNu
Copy link

maaaNu commented Apr 8, 2025

Hi all,
We're running into the same issue described here: #7663 (comment).

Is there any update or workaround available at this point? We'd really appreciate any insights or guidance.

Thanks in advance!

@lalimasharda
Copy link
Contributor

Can folks try out the latest builds from today and let us know if this issue is fixed? Thank you!

@microsoft-github-policy-service microsoft-github-policy-service bot added Needs: Author Feedback Awaiting response from issue author and removed Needs: Attention 👋 Awaiting response from the MSAL.js team labels Apr 8, 2025
@Tweentyy
Copy link

Tweentyy commented Apr 9, 2025

Hello,
For me all is working good!
Thanks

@neilzuk
Copy link

neilzuk commented Apr 9, 2025

I've updated this morning and can confirm my Angular app is working as expected again, thank you!

@klandell
Copy link

klandell commented Apr 9, 2025

4.10.0 works for me. Thanks.

@StantonCoffey89
Copy link
Author

I've updated to 4.10.0 and all is working now. Thanks!

@microsoft-github-policy-service microsoft-github-policy-service bot added Needs: Attention 👋 Awaiting response from the MSAL.js team and removed Needs: Author Feedback Awaiting response from issue author labels Apr 10, 2025
@microsoft-github-policy-service microsoft-github-policy-service bot removed the Needs: Attention 👋 Awaiting response from the MSAL.js team label Apr 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug-unconfirmed A reported bug that needs to be investigated and confirmed msal-angular Related to @azure/msal-angular package msal-browser Related to msal-browser package public-client Issues regarding PublicClientApplications question Customer is asking for a clarification, use case or information.
Projects
None yet
Development

No branches or pull requests