1

We have a NodeJS express server with express-session and express-mysql-session enabled. We've connected the session database and can verify there are sessions being created. Our app redirects users without a token cookie to Auth0 for authentication, and they are redirected back to our app at /callback. It does successfully set our ID token that allows our user to be logged in. However, the passport auth0 strategy complains that it cannot verify the authentication state.

'Unable to verify authorization request state.'

The server code is below, with some other parts commented out. Connecting to the session database is successful since we can see our sessions get created with each request.

const options = {
  database: process.env.SESSION_DB_NAME || "sessions",
  host: process.env.SESSION_DB_HOST! as string,
  password: process.env.SESSION_DB_PASSWORD! as string,
  port: parseInt(process.env.SESSION_DB_PASSWORD || "3306", 10),
  user: process.env.SESSION_DB_USER! as string,
};
const sessionStore = new MySQLStore(options);

app.use(
  session({
    cookie: {
      httpOnly: true,
      maxAge: 24 * 3600 * 1000, // 1 day
      secure: true,
    },
    resave: false,
    saveUninitialized: true,
    secret: process.env.SESSION_SECRET!,
    store: sessionStore,
  })
);

app.get("/login", (request, response, next) => {
  // if there is no session, it's a server error
  if (!request.session) {
    console.error(new Error("No session in /login"));
    return response.status(500).send("Server error: No Session");
  }

  return passport.authenticate("auth0", {
    scope: "openid email profile",
  })(request, response, next);
});

console.log("router: Auth0 Callback");
app.get("/callback", (request, response, next) => {
  const domain = request.hostname;
  console.log(request.session);

  passport.authenticate("auth0", (auth0Error, token, info) => {
    // if there was a problem authenticating
    if (auth0Error) {
      console.error(auth0Error);
      return response.status(500).send();
    }

    // ensure we have a session. The middleware should be giving us one.
    if (!request.session) {
      console.error("No session in /callback.");
      return response.status(500).send();
    }

    // if we couldn't log in
    if (!token) {
      if (info) {
        console.log(info);
        return response.status(500).send(info.message);
      }

      // redirect to the login page
      return response.status(401).send("Cannot log you in.");
    }

    // parse the token we get
    const user = jwt.decode(token);

    // if there is no valid user token, we've got bigger problems
    if (!user) {
      console.error("Token is falsey after authenticating.");
      return response.status(500).send();
    } else if (typeof user === "string") {
      console.error("Cannot decode JWT after authenticating");
      return response.status(500).send();
    }

    request.logIn(user, (logInError) => {
      // redirect to desired route
      // ...
    });
  })(request, response, next);
});

router.get("/*", (request, response, next) => {
  passport.authenticate("jwt", (authenticationError, isAuthenticated, info) => {
    // Log in successful via existing JWT
    if (isAuthenticated) {
      return next();
    }

    // handle unauthenticated situations
    // ...
  })(request, response, next);
});

I've tried the following suggestions at https://github.com/auth0/passport-auth0/issues/70:

  • app.set("trust proxy", 1")
  • session cookie already set to secure
  • serving only on https
  • using mysql session store and default in-memory store

We are running the server in a kubernetes cluster using ClusterIP for our ingress. Env variables are being set correctly, I'm pretty sure. When I run this locally I do not have any issues.

What could cause the session to not be restored but instead recreated with each request?

whiterook6
  • 3,270
  • 3
  • 34
  • 77
  • How did you fix the problem? I'm running into the same issue. I'm running nodejs on heroku – Chris Hansen Feb 18 '22 at 12:54
  • @ChrisHansen I'm not sure whether we ever did resolve it. Looking back through our commits, I think it was more of a mitigation. If we caught that exception log, we tried another login attempt automatically. – whiterook6 Feb 18 '22 at 18:14

1 Answers1

1

Your question was posted over a year ago so I figure you've already fixed it, but I thought I'd post my solution to help others. I very recently ran into the same issue, although I was using an Apache reverse proxy instead of a Kubernetes cluster.

I've posted my solution in another SO question: https://stackoverflow.com/a/67891167/8221175

In short, my Apache configuration was missing these lines:

RequestHeader set X-Forwarded-Proto expr=%{REQUEST_SCHEME}
RequestHeader set X-Forwarded-SSL expr=%{HTTPS}

ProxyPass / http://localhost:8001/
ProxyPassReverse / http://localhost:8001/

This, along with other session/cookie configuration for express (see the SO link) fixed it. My sessions now persist and I no longer have the issue.

For those interested in why the 'Unable to verify authorization request state.' message is issued, check out my answer in this GitHub issue: https://github.com/auth0/passport-auth0/issues/89#issuecomment-856971807

Victor
  • 578
  • 7
  • 12
  • I'm running into the same issue on heroku with a nodejs setup. Can you answer my question here https://stackoverflow.com/questions/71145818/unable-to-verify-authorization-state-on-heroku? – Chris Hansen Feb 16 '22 at 18:46