0

I have a NodeJS/Express application where I am using PassportJS for authentication.

I have the following routes:

router.get("/profile", isUser, (req, res) => { 
  res.render("profile");
});

router.post("/post-something", isUser, (req, res) => {
  db.post(...);
  res.json({ success: true });
});

router.get("/login", (req, res) => {
  res.redner("login");
});

router.post("/login", (req, res) => {
  req.logIn(...);
  res.redirect("profile");
});

router.delete("/logout", (req, res) => {
  req.logout(...);
  res.redirect("login");
});

where isUser is a middleware function which checks that the user is logged in:

  • if the user is logged in, continue.
  • if the authInfo is set, it means there was an error (e.g. the user is still logged in despite the user document having been deleted causing passportJS to fail when trying to find the user), in which case I wish to log the user out.
  • if the user is not logged in, the user should be taken to the log in page.
function isUser(req, res, next) {
  if (req.user) {
    return next();
  }
  else if (req.authInfo.message === "user not found") {
    return res.redirect("/logout");
  }
  else {
    return res.redirect("/login");
  }

Firstly, in the scenario where the user is not logged in and I wish to redirect to the login page, how do I distinguish between the login GET route and the login POST route? If a user for example sends the post request to /post-something will the redirect also assume that the method to be used is still the POST method causing me to attempt to log in directly instead of opening the log in page?

Secondly, in the scenario where an error has occurred and I wish to log out, how does my app know that I am switching from a GET or POST request to now redirect to a DELETE route before redirecting back to a GET route after logging out?

sorry if this is a dumb question but I do not understand how these redirects work when it comes to the HTTP methods ):

1 Answer 1

2

Your code as it is now will respond with a 302 status code, which just tells the browser to go somewhere else. Historically, that ended up being a GET request, even if you are redirecting from a POST call.

There are other status codes, namely 307 & 308, which work similarly to 302 & 301, that state that the client use the same method again. But that's not what you want, so just stick with 302 and your POST will be followed by a GET of your login page.

However, is that what you want? If you are making an XHR call, then the POST which returns JSON will be redirected to a GET which returns HTML (your login page). You'll probably just end up with a parsing error at the next JSON.parse().

If someone accesses a resource that they must be logged in for, but they aren't logged in, don't redirect an XHR. Respond with a 401 instead, and then your library can understand that it means the user isn't logged in, and can then just load the login page.

5
  • I suppose I can check the "accept" request header to know if I should send a 401 json response or do a redirect. So currently the way my code is now my redirects will always look for GET routes if I understood correctly. How do I redirect to the logout route which is a delete route then?
    – Oscar R
    Commented Jul 9 at 19:23
  • I'm not sure what you mean by redirecting to /logout. It's a DELETE request, which means it must be XHR. If you have a "Log out" button somewhere, and clicking it calls the DELETE route, then when that call completes you'd want to tell the window to navigate to /login. You wouldn't do a redirect there either.
    – mherzig
    Commented Jul 9 at 19:37
  • I don't know what you are using in the front end, so that's a different question. For example, once the DELETE request is successful, you might run navigate('/login'); if you are using React Router or window.location = '/login' for vanilla JS
    – mherzig
    Commented Jul 9 at 19:39
  • Currently I dont really use XHR, when the logout button is clicked, I just navigate to the log in page using res.redirect() after the log out is complete. However, the scenario I mentioned was rather about logging the user out when passportjs fails to deserialize the user, by redirecting whatever request the middleware is used in to the logout route. But I understand if this is not possible, it would just be convenient if it was.
    – Oscar R
    Commented Jul 9 at 19:52
  • 1
    Ah yes, sorry, I do understand now. Unfortunately, the browser won't do a DELETE request unless its XHR, so you would have to have the middleware do whatever the logout would have done anyway, and then redirect to the login page.
    – mherzig
    Commented Jul 9 at 22:01

Not the answer you're looking for? Browse other questions tagged or ask your own question.