Page refresh breaks MSAL React instance

217 Views Asked by At

I'm building a React app that uses MSAL to redirect the user to a login page, then redirect back to the app after successful authentication. When HomePage.tsx loads, an API call is triggered to a 3rd party API. The response is used to render content. This call requires an access token generated by MSAL. This all works perfectly.

The problem occurs if the page is refreshed in the browser any time after successful login. After the refresh, the method msalInstance.acquireTokenSilent() fails with the following error:

uninitialized_public_client_application You must call and await the initialize function before attempting to call any other MSAL API. For more visit: aka.ms/msaljs/browser-errors

Going back to the initial login, after authentication and redirection back to the HomePage, I can inspect msalInstance and it is initialized, resulting in a successful request for access token.

enter image description here

But after a page refresh I can inspect it again and it is indeed not initialized.

enter image description here

This is not happening with another React app I maintain that also uses the same MSAL redirect login process. The only difference I can see between the two apps is the version of msal-react and msal-browser. The working app uses:

"@azure/msal-browser": "^2.32.2",
"@azure/msal-react": "^1.5.2",

But as you see further down, this new app is running newer versions of both.

Do I need to handle this differently in msal-react v2?

Is there a step I am missing that would prevent the MSAL instance from de-initializing after a page refresh?

Relevant code:

main.tsx

const msalConfig: Configuration = {
  auth: {
    clientId: config.clientId,
    authority: config.authority
  }
}

const pca = new PublicClientApplication(msalConfig);

const authRequest = {
  scopes: ["openid", "profile"]
};

root.render(
    <MsalProvider instance={pca}>

      <MsalAuthenticationTemplate interactionType={InteractionType.Redirect} authenticationRequest={authRequest}>

        <App msalInstance={pca} msalConfig={config}/>

      </MsalAuthenticationTemplate>
      <UnauthenticatedTemplate>
        <p>No users are signed in!</p>
      </UnauthenticatedTemplate>

    </MsalProvider>
)

App.tsx

function App(props: any) {
    const { instance, accounts, inProgress } = useMsal();

    const [bookmarkedApps, setBookmarkedApps] = useState<UserApp[]>();

    const getAccessToken = async () => {
        try{
            const msalResponse = await props.msalInstance.acquireTokenSilent({
                scopes: [props.msalConfig.scopes],
                account: accounts[0]
            });
            return msalResponse.accessToken;
        } catch (error) {
            console.log(error!.errorCode);
            console.log(error!.errorMessage);
        }
        
    }

        
    const getBookmarkedApps = async () => {
        const resp = await fetch('/api/apps/bookmarked', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + await getAccessToken()
            },
            body: JSON.stringify({
                environmentConfigId: 1
            })
        });

        if(resp.ok) {
            const data = await resp.json();
            setBookmarkedApps(data);
        }
    }

    const router = createBrowserRouter([
        {
            path: '/',
            element: <RootLayout />,
            children: [
                { path: '/', element: <HomePage getAccessToken={getAccessToken} bookmarkedApps={bookmarkedApps}/> },
                {
                    path: '/apps', element: <Outlet />, children: [
                        { path: '/apps/manage', element: <ManageApps /> },
                    ]
                }
            ]
        },
    ]);

    useEffect(() => {
        getBookmarkedApps();
    }, []);

    return (
        <RouterProvider router={router} />
    );
}

export default App;

From package.json:

"dependencies": {
    "@azure/msal-browser": "^3.5.0",
    "@azure/msal-react": "^2.0.7",
    "@emotion/react": "^11.11.1",
    "@emotion/styled": "^11.11.0",
    "@mui/icons-material": "^5.14.18",
    "@mui/material": "^5.14.18",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router": "^6.20.0",
    "react-router-dom": "^6.20.0"
  }
0

There are 0 best solutions below