microsoft-authentication-library-for-js: AuthError: Unexpected error in authentication.: Hash does not contain state.

I’m submitting a…

[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report  
[ ] Performance issue
[ ] Feature request
[ ] Documentation issue or request
[ ] Other... Please describe:


  • Chrome version XX
  • Firefox version XX
  • IE version XX
  • Edge version XX
  • Safari version XX

Library version


Current behavior

Steps to reproduce.

  1. Attempt a B2C login flow using loginRedirect
  2. When asked to log in, click “reset password” (This will redirect back to the SPA)
  3. Catch the AuthError (AADB2C90118) and redirect the user to the password reset flow
  4. Click “cancel” on the password reset flow. (This redirects back to the SPA)

now calling new UserAgentApplication(config) will error with the message:

AuthError: Unexpected error in authentication.: Hash does not contain state.

At this point you can’t recover. Even if you catch the error, clear session storage, and try to call new UserAgentApplication(config) it will still error again.

Expected behavior

After redirecting back to the SPA after the user clicks “cancel” msal should trigger your errorReceivedCallback and give it an error that can be recovered from.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 12
  • Comments: 24 (4 by maintainers)

Most upvoted comments

Please re-open this issue. Getting the same problem, setting storeAuthStateInCookie to true does not resolve the problem.

Same issue here with Google Chrome (build 80.0.3987.122). Regular login works, but when using a custom Sign Up policy we receive the AuthError: Unexpected error in authentication.: Hash does not contain state. error.

I have the same problem in my case the browser is Edge Chromium and I can’t get the password reset flow to work with Ad B2C, if the user cancels or completes the flow I get the error.

note: I have storeAuthStateInCookie in true

With msal 1.3.1 error still present.

Same as @jeverduzco. I am having the issue in Edge Chromium when using the password reset flow in AD B2C. I also have storeAuthStateInCookie set to true

I see a lot of people have this problem.

Reason - aad for some reason loses state on reset password flow. What is state? Msal records string on your page before redirect to aad, and compares it to response that you got after redirecting from aad, to insure that request to aad was issued by user`s browser.

How to fix it?

  1. You can wait for msal (or aad) team to fix it.
  2. You can rewrite function that checks state, make it so it would not check it for reset password case. If you have more questions - you can contact me.

And, if you like me, experienced a number of other issues, I would recommend rewriting msal altogether.

I am seeing the same error when redirecting from Sign Up v2

I am facing same issue when authorization flow is not triggered from msal, I am implementing user invitation flow using custom policy, flow works fine, after completion it redirects to the app, but msal raise above error, how to handle this scenario?

In the beta (1.3.0-beta.1) version work fine for me.

I am also getting this issue in the latest version of Firefox (74.0.1) and Chrome (81.0.4044.92). I have included storeAuthStateInCookie: true in my msal config.

My steps to reproduce are as follows:

  1. Go to the login page of my signin user flow. A script on that page changes the forgot password link href so it points to my forgotpassword flow landing page.
  2. Click forgot password link. navigate to the forgot password page.
  3. Go through the entire flow, changing my password successfully.
  4. Get redirected back to my application where it shows this error:

Unhandled Rejection (AuthError): Unexpected error in authentication.: Hash does not contain state.

in my stack trace, the source of the error is when I initialize in my code:

new msal.UserAgentApplication(environment.msalConfig);

From there the stack trace is as follows (NOTE that this is in calling order, not reverse order like a stack track):


  238 |  * @param {@link AuthenticationParameters}
  239 |  *
  240 |  * To renew idToken, please pass clientId as the only scope in the Authentication Parameters
> 241 |  * @returns {Promise.<AuthResponse>} - a promise that is fulfilled when this function has completed, or rejected if an error was raised. Returns the {@link AuthResponse} object
      | ^  242 |  */
  243 | UserAgentApplication.prototype.acquireTokenPopup = function (userRequest) {
  244 |     var _this = this;

  1043 | var aState = this.getAccountState(serverAuthenticationRequest.state);
  1044 | var response = {
  1045 |     uniqueId: "",
> 1046 |     tenantId: "",
       | ^  1047 |     tokenType: (accessTokenCacheItem.value.idToken === accessTokenCacheItem.value.accessToken) ? ServerHashParamKeys.ID_TOKEN : ServerHashParamKeys.ACCESS_TOKEN,
  1048 |     idToken: idTokenObj,
  1049 |     idTokenClaims:,

  1109 | this.logger.verbose("Renew token Expected state: " + serverAuthenticationRequest.state);
  1110 | // Build urlNavigate with "prompt=none" and navigate to URL in hidden iFrame
  1111 | var urlNavigate = UrlUtils.urlRemoveQueryStringParameter(UrlUtils.createNavigateUrl(serverAuthenticationRequest), Constants.prompt) + Constants.prompt_none + Constants.response_mode_fragment;
> 1112 | window.renewStates.push(serverAuthenticationRequest.state);
       | ^  1113 | window.requestType = Constants.renewToken;
  1114 | this.registerCallback(serverAuthenticationRequest.state, scope, resolve, reject);
  1115 | this.logger.infoPii("Navigate to:" + urlNavigate);

  32 |     AuthError.createNoWindowObjectError = function (errDesc) {
  33 |         return new AuthError(AuthErrorMessage.noWindowObjectError.code, AuthErrorMessage.noWindowObjectError.desc + " " + errDesc);
  34 |     };
> 35 |     return AuthError;
  36 | }(Error));
  37 | export { AuthError };
  38 | //#

  22 |     var _this =, errorMessage) || this;
  23 |     Object.setPrototypeOf(_this, AuthError.prototype);
  24 |     _this.errorCode = errorCode;
> 25 |     _this.errorMessage = errorMessage;
     | ^  26 | = "AuthError";
  27 |     return _this;
  28 | }