I noticed a pretty interesting edge case of using auth0. I use "auth0-js": "9.11.3".
The case:
A user is on our login page that uses auth0-js for login. While the user is on login page, we push an update - basically, build a new version of our SPA. If the user will try to login using “old” version of page, they won’t be authorized, and parseHash method will fail with a following error:
{
error: invalid_token,
errorDescription: `state` does not match.,
message: `state` does not match.
}
Part of the issue, that it only happens on an app re-builds. That’s the reason why I can’t provide any repro.
Hey @voronin
The state is a random string, generated by Auth0.js right before redirecting the user to the authorization endpoint (/authorize), included in that request, and stored locally (in a cookie, in the latest versions of Auth0.js). When Auth0 (the service) redirects the browser back to the app with the authorization response, it includes that state that Auth0.js compares with what was stored in the cookie (if it doesn’t match, you get the state does not match error).
IIRC the cookie where the state is stored has a duration of 30 minutes, so if the user stays on the login page (or other interactive parts of the authorization process) longer than that, this error could appear. A new version deploy shouldn’t cause this (unless you are changing domains!), but hopefully understanding how this works will help you with the troubleshooting.
Hi @nicolas_sabena! Thanks for reply. Can you clarify a little bit more?
Am I right that state is being generated on the moment of login method call?
Eg
// This code invoked on a page load
const webAuth = new auth0.WebAuth({
domain,
clientID,
responseType: 'id_token',
redirectUri
});
// This code is invoked per user clicks "login" somewhere on a form
// Does state being generated here?
webAuth.login(... some credentials);
This is where the state received in the authorization response is compared with the state generated right before starting the flow:
The “Transaction manager” class is used to store and then retrieve the state (auth0.js/transaction-manager.js at master · auth0/auth0.js · GitHub). As I said before, by default it uses cookies as a way of storing the state (because the value needs to survive between page reloads), but it can also use localStorage if configured to do so.
If you can reproduce the issue (like manually forcing a deploy), you can try putting breakpoints in the places where the state is stored and then retrieved, to find where the difference comes. Referencing the non-minified version of Auth0.js will make it easier to work with source files.