I just wanted to post this here because it took me about 12 hours to solve this problem and I wanted to help others who may have run into it!
The Problem
I had an issue in using the @auth0/auth0-react package in a SPA where I was running on http://localhost:8080, it would throw a state mismatch error after correctly authorizing in the new Auth0 login redirect page. I would notice in the URL params that the state Auth0 generated for the login was different than the one it was returned/sent to the callback url. It felt like a race condition at first because it happened about 80% of the time we tried to log in.
A manual refresh reset the state and worked every time.
Honestly, searching online returned very limited results, but I tried:
- Using refresh tokens
- Using the
useCookiesForTransactionsparam forAuth0Provider - Adding a specific
/callbackurl, react-routerRoute, and component - Setting my own cookies (even though it was a SPA) as with this WordPress Invalid State Error article suggested
- Downgrading react-router to v5.3 from v6
- Downgrading React from v18.x to v17.x
- Using
httpsinstead ofhttp(yes, even forlocalhost) - etc
The error I would get back had a stack trace that included lines in webpack’s source code.
Specs
Relevant package declarations in package.json:
@auth0/auth0-react": "^1.12.0""react": "^18.1.0""react-dom": "^18.1.0""react-router-dom": "^6.4.3""webpack": "^5.72.0""webpack-cli": "^4.9.2""webpack-dev-server": "^4.9.0"
Other information:
- Mac OSX 12.4
- Google Chrome Version 107.0.5304.110
The Solution
Are you ready? It’s super dumb.
…
…
…
Disabling HMR in Webpack.
We were running with hot: true in our webpack config and it caused our app to re-render unnecessarily (even without extra saves while logging in). I’m still not sure exactly why this caused Auth0 to trip up, but it might make sense that since it re-rendered a few extra times when redirecting to the callback, that Auth0 might have thought it was a CSRF attack.
So any of the solutions would work for this problem:
- Add
hot: falseto yourwebpack.config.js
module.exports = {
...
devServer: {
hot: false
...
}
}
- Add
watch: falseto your webpack config
module.exports = {
...
watch: false
}
- Use
webpack-dev-serverwithout the--hotflag
Ok. I hope that helps someone save some time. It stumped me and my friend, who graciously decided to help me debug, for a good long while.
Would love to know exactly why this happens, but I’m also just happy with knowing the fix!