auth0.js: Invalid token - `state` does not match

So for some reason I can’t seem to authenticate users on certain computers/laptops that has the same browser versions.

auth.js

export var webAuth = new auth0.WebAuth({
    domain: 'xxx.auth0.com',
    clientID: 'xxx',
    responseType: 'token id_token',
    audience: 'https://xxx.auth0.com/userinfo',
    redirectUri: 'http://localhost:3000'
  })

Login.vue

if (window.location.hash) {
        webAuth.parseHash({ hash: window.location.hash }, (err, authResult) => {
          if (err) {
            return console.log('parseHash error', err)
          }
          if (authResult) {
            webAuth.client.userInfo(authResult.accessToken, function(err, user) {
              if (err) {
                console.log('err accessToken', err)
              }
              localStorage.setItem('profile', JSON.stringify(user))
              localStorage.setItem('id_token', authResult.idToken)
              window.location = '/state'
            })
          }
        })
      }

Picture:

error

Other details:

Auth0 version: NPM - 8.12.2 ScriptJS - 8.12.2

Browser: Chrome Version 64.0.3282.140 (Official Build) (64-bit) O.S: Windows 10

The issue is not happening on my laptop (which is running on the the Browser version mentioned above), but it is happening on other laptops (same browser version).

Not too sure what else to try here. Been looking at the forums, nothing is working out.

Would love some insights on this. Thank you.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 6
  • Comments: 88 (33 by maintainers)

Most upvoted comments

I’ve seen this happening sometimes if the authorize request is made from a different origin than the callback URL. E.g. you navigate to “http://myapp.com”, and instead of redirecting first to “https://myapp.com”, it goes directly to “https://yourtenant.auth0.com/authorize?...&redirect_uri=https://myapp.com” (notice the difference between “http://” and “https://”). Since Auth0.js stores the state in local storage before redirecting to Auth0 for later verification, you need to ensure that the origin where the authorize request originates is the same as the callback URL.

@luisrudge for easier troubleshooting, I might be a good idea to log in the console a little more data, like the state that came in the callback, and what was there in localStorage (no match?). Even a list of states present in LocalStorage might help.

Or maybe just handle one possible state storage slot instead (i.e. not including the state value as part of the key for local storage)?

In all sincerity, this `state` does not match. message is not at all helpful. The above comments mention some “possible causes”, but it’s still not clear. It’d be nice if there was a clear reason (in the error output) stating what the specific problem is.

I want to summarize the two common causes I see in customer support related to this state does not match error (apologies for repeating the content of my previous post, but I’m adding a second cause here):

  • Callback URL set to a different domain. E.g. your app started at the http://myapp.com and the callback is set to https://myapp.com (note the different http vs https scheme). Auth0.js/Lock store the state in local storage, which is not shared across different domains. In the http/https case, the correct approach is to redirect to the https scheme first and then initiate the login.
  • A flow in the app is causing parseHash to be called twice. The first time it’s run, the slot in local storage used for the specified state is cleared, so the second time you will always get this error. Make sure that your app only calls this once. Note that, by default, Lock calls it automatically upon initialization if it finds a result in the location of the hosting window.

CRAAAAAP.

So I’m using lock.resumeAuth, but I did not set auth0-lock Lock option autoParseHash to false, so this caused parseHash to be called twice. I solved that issue by setting autoParseHash to false.

Note, in the autoParseHash or resumeAuth documentation, there is not a single mention of this cryptic error!!!

However, now that I’ve solved that problem, and I can verify that parseHash is not being called twice, now something else is causing the same error. I have a feeling now I’m encountering this problem (double whammy):

you need to ensure that the origin where the authorize request originates is the same as the callback URL


It’d be very nice for the Auth0 team to take this problem seriously and make it more clear, both in the documentation, and by providing contextual error messages rather than `state` does not match..

Now I’ll continue to step through auth0 code in Chrome devtools until I find the second source of the error, which as paying customer wish I didn’t have to do.

If anything, a prorated refund of the wasted time would be very welcome, and would make all frustrations go away, because I need to be working on the business product where I work, instead of wasting resources.

I get this error in Private Browsing Firefox v63.0.3 with all extensions and Content Blocking disabled using the provided React sample app. To reproduce, login and then refresh the page, auth0-js v9.8.2. I do not get the error in Chrome or Safari.

@nicosabena mention of HTTP vs HTTPS made the difference for me.

Fix: Now forcing all traffic to HTTPS and all requests work.

Previously, a user would enter on HTTP and try to authenticate. The callback was set to send them back to the domain but on HTTPS, hence the mixed/non-matching state. As the callback was set to return to HTTPS, the second and all subsequently requests worked as expected. It was no longer mixed or not matching. It was HTTPS from there on out.

I get this error in Private Browsing Firefox v63.0.3 with all extensions and Content Blocking disabled using the provided React sample app. To reproduce, login and then refresh the page, auth0-js v9.8.2. I do not get the error in Chrome or Safari.

We are hitting the same thing - refreshing the page shows invalid token - state does not match for Firefox only.

Ah ok thanks, that did the trick.

Now that my credibility has been destroyed by not being able to read the documentation properly, is redirecting to the login page straight from the logout endpoint a common use case or am I an outlier? If it’s common, it would be really nice for logout/buildAuthorizeUrl to handle setting state the same way authorize does.