0

I'm trying to get a basic Auth0 app running. I followed the Node example on the Auth0 dashboard but I ran into an infinite redirect loop between /login and /callback. I tried to simplify the code using the getting started example of this repo's readme, right now my routing code looks like this:

app.get('/login',
      passport.authenticate('auth0', {scope: 'openid email profile'}),
      (req, res) => res.redirect("/")
    )

    app.get("/callback", 
      passport.authenticate('auth0', {failureRedirect: '/login'}),
      (req, res) => {
        if(!req.user) throw new Error("user null")
        res.redirect("/")
      }
    )

Everything about my setup follows the instructions I got on my Auth0 dashboard.

I did some digging and found out that /login is called twice, then /callback is called twice, then /login twice and so on and so on. I also found out that if I give the /callback's passport.authenticate a callback, it receives these arguments: null, false, {message: "Invalid authorization request state."}

Google didn't find anything meaningful when I searched for the phrase "Invalid authorization request state." and I did everything according to the docs. Any idea what I'm doing wrong?

ThanhPhanLe
  • 1,315
  • 3
  • 14
  • 25
M. Farnik
  • 235
  • 1
  • 3
  • 9

3 Answers3

1

I have had the same issue with these error and was caused due to session loss on Kubernetes landing my calls to different instances each time (sort of like load balancing), what we did was to lower from 3 instances to 1 and that fixed it. Also you could set in your Auth0Strategy config the value of state: false to double check if this lets you move on.

isalmeron
  • 11
  • 1
0

It turns out I didn't have the /callback route set up properly. This is the proper setup:

router.get("/callback", (req, res, next) => {
  passport.authenticate('auth0', (err, user, info) => {
    if(err) return next(err)
    if(!user) return res.redirect("/failure?info=" + JSON.stringify(info))

    req.logIn(user, err => {
      if(err) return next(err)

      const returnTo = req.session.returnTo
      delete req.session.returnTo
      res.redirect(returnTo || '/secret')
    })
  })(req, res, next)
})

res.redirect should lead somewhere else and req.logIn needs to be called with the proper arguments

M. Farnik
  • 235
  • 1
  • 3
  • 9
0

For those who are still having issues, the problem might lie elsewhere. When I ran into this it turned out to be caused by session cookies that weren't persisting! It turned out my reverse proxy (running on Apache) wasn't configured properly. I've described my solution here: https://stackoverflow.com/a/67891167/8221175

As for why this might happen for those interested, I've posted an explanation on one of the GitHub issues here: https://github.com/auth0/passport-auth0/issues/89#issuecomment-856971807

In short: The state query parameter in the response of a login call is saved in the session. If sessions don't persist, passport can't get that state data and it'll think someone is hijacking your session. That causes the “Invalid authorization request state.” message, as well as the user to be falsy in the passport.authenticate callback. If your code then redirects to '/login', the whole thing repeats, causing an infinite loop.

The fix is to make sure your cookies are saved properly and your sessions therefore persist. You can use the examples I've provided in the links.

Victor
  • 578
  • 7
  • 12