microsoft-authentication-library-for-js: Hash value cannot be processed because it is empty
Core Library
MSAL.js v2 (@azure/msal-browser)
Core Library Version
2.22.0
Wrapper Library
MSAL React (@azure/msal-react)
Wrapper Library Version
1.3.0
Description
The user cannot log in after entering email & password. The login popup gets closed and nothing happens.
After getting the error, that does not happen all times, it’s possible to login after clicking the login button again (sometimes, it is needed to click it several times). This intermittence makes it difficult to debug.
I basically followed this tutorial: https://docs.microsoft.com/en-us/azure/active-directory/develop/tutorial-v2-react
The Azure AD app in portal.azure.com (Microsoft_AAD_RegisteredApps) was configured with Single Page Application redirect URIs having the URI set matching the one configured in the msal configuration (auth.redirectUri
property)
Error Message
error BrowserAuthError: hash_empty_error: Hash value cannot be processed because it is empty. Please verify that your redirectUri is not clearing the hash. Given Url: https://myUrl.com/
Msal Logs
No response
MSAL Configuration
const msalConfig = {
auth: {
clientId: '930b1k1b-...',
authority: 'https://login.microsoftonline.com/l2cba3e8-...',
redirectUri: 'https://myUrl.com/'
},
cache: {
cacheLocation: 'sessionStorage',
storeAuthStateInCookie: false,
},
}
Relevant Code Snippets
ClientApp instantiation:
---------------------------------------------------------------------
import { PublicClientApplication } from '@azure/msal-browser';
import { MsalProvider } from '@azure/msal-react';
import { msalConfig } from './config';
const msaInstance = new PublicClientApplication(msalConfig);
ReactDOM.render(
<React.StrictMode>
<MsalProvider instance={msaInstance}>
<App />
</MsalProvider>
</React.StrictMode>,
document.getElementById('root')
);
---------------------------------------------------------------------
Signing in:
const { instance } = useMsal();
const navigate = useNavigate();
let signin = () => {
return instance
.loginPopup({
scopes: ['User.Read'],
})
.then((response) => {
setUserData(response);
navigate('welcomPagePath');
})
.catch((e) => {
console.log('error', e);
});
};
Reproduction Steps
- Enter Microsoft email
- Enter password
Expected Behavior
The user can log in
Identity Provider
Azure AD / MSA
Browsers Affected (Select all that apply)
Chrome
Regression
No response
Source
External (Customer)
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 42 (7 by maintainers)
For me, when the login popup is opened in a popup window, then it succeeds. However, if the login popup is opened in a tab - then it fails with the same error as above (
hash_empty_error
). I find Chrome, running in fullscreen mode on a Mac (rather than just expanded to the display) will open the popup as a tab, rather than a new window - triggering the error.We use the popup login methods. The popup first directs the user to Microsoft, they sign in (or are already signed in) and are then redirected to our
redirectUri
that we’ve set in both thePublicClientApplication
config and Azure portal. The URL they’re redirected to has a hash appended (http://your.redirect.url#some-hash-from-microsoft
). The parent window (the one where you created the popup from) reads the hash from the popup’s URL, and then closes the popup.We had our redirect URL set to our application’s homepage (i.e.
/
). This meant that, when the popup loaded the page after being redirected back from Microsoft, our application was loaded - including the code that checks if the user is logged in. If the parent window didn’t read the hash in time before the application in the popup checked the user’s login status, then the hash would be cleared - and our parent application would error, as it couldn’t read the hash from the popup. So we had a race between the parent window reading the URL and our application loading - not good!The solution, as given in docs and issue comments, was to redirect the popup to a blank page.
Not very much, ideally. 😄 It’s literally just a page to redirect the popup to; it just needs to be on the same domain as your application, so the parent window can read from it. Here’s a (slightly redacted) version of ours:
This page should never be seen by your users. It will flash up quickly just before the popup closes, so having it as minimal as possible will help with performance. It doesn’t need to be styled - if anything, having content will confuse users who’ll see a momentary flash of content in the popup before its closed for them.
If you’re using the popup login, then it never redirects back to your application landing page. You have MSAL in your main application window that a user sees (we’ll call this the “parent”). The parent creates the popup, the popup goes to Microsoft, Microsoft redirects back to your blank page, and the parent reads from the popup URL before closing the popup. Your parent window never redirects to Microsoft - but when you’re logged in the
AuthenticatedTemplate
will show rather thanUnauthenticatedTemplate
.We’ve resolved this in our application. For us, we had our redirect URL as the home page of our application. This caused an issue where our router (in Next.js) took over the routing in the popup, stripping the hash and redirecting it to the login page - before the window that launched the popup had time to extract it. Redirecting to a blank page allowed consistent logins.
These comments and documentation helped: https://github.com/AzureAD/microsoft-authentication-library-for-js/issues/4550#issuecomment-1058519256 https://github.com/AzureAD/microsoft-authentication-library-for-js/issues/4456#issuecomment-1046328877 https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/login-user.md#redirecturi-considerations
Seems like its working now… Still under testing though… Thanks for your help and valuable feedback !!
This part I did understand. Thanks for giving a detailed info.
React being a SPA, is it even possible to have a url to open up a static html page ? My application entire routes + App components are bound by
According to msft docs, this blank route should be outside of the
<MsalProvider />
. Is my understanding correct ? If so, how do we now open a blank.html outside of the SPA 🤔Again appreciate you providing this explanation regarding how MSAL is enabling authentication !! 👍
🎉This issue was addressed in #4793, which has now been successfully released as
@azure/msal-browser@v2.25.0
.🎉Handy links:
@atkinchris’s answer above should resolve this issue - thank you for your input. We will update our docs to be more clear that you must either allow MSAL to complete processing before the router, or follow the docs listed and redirect to a blank page.
Thank you for your help @atkinchris!
Great - then you can set that as your redirect URL in your
PublicClientApplication
config and Azure portal. 🙂