Home > OS >  JWT authentication working in postman but authentication token not being set to cookies in browser
JWT authentication working in postman but authentication token not being set to cookies in browser

Time:08-08

I am using JWT to set a token for user authentication on specific routes. The authentication works perfectly with the Postman routes, but when I log in using the browser and the app sends the GET requests to my Heroku backend, I get a 401 Unauthorized error. I am using the same Heroku URL when sending a postman request, so I am sure that my Heroku hosting is not the issue.

The flow of the app is as follows:

Once a user tries to log in, we check credentials with the DB and if the credentials are correct, we then assign a jwt token to the cookie. This occurs on the server side using the encode function below.

export const encode = async (req, res, next) => {
  try {
    const { username, password } = req.params;
    const verifiedLogin = await User.onUserLogin(username, password);
    if (verifiedLogin.success === false) {
      return res.status(401).json({ success: false, message: "Invalid login credentials" });
    }
    const token = jwt.sign({ userid: verifiedLogin.user._id, userType: verifiedLogin.user.type }, SECRET_KEY);
    res.cookie("Authorization", token, { httpOnly: false, secure: false });
    console.log("cookie", res.cookie);
    return res.status(200).json({ success: true, userId: verifiedLogin.user._id });
  } catch (error) {
    return res.status(400).json({
      success: false,
      message: "Problem while trying to authenticate ",
      error: error,
    });
  }
};

Once the user is logged in, we then run a series of GET requests from the client side to retrieve some data from our DB. None of the GET requests are authorized after login so I will only provide one of them here.

export const fetchUserGroups = async () => {
  let roomsFromResponse = [];

  // Request to get the groups the user is part of for the groups panel
  await axios
    .get(`http://saldanaj97-chattyio.herokuapp.com/room/user-messages/`, CONFIG)
    .then((response) => {
      response.data.roomIds.map((room) => {
        const newRoom = { id: room._id, groupName: room.groupName, lastMessageReceived: { user: "", contents: "" } };
        return (roomsFromResponse = [newRoom, ...roomsFromResponse]);
      });
    })
    .catch((error) => {
      console.log("Auth error when retrieving users groups", error);
    });
  return roomsFromResponse;
};

Lastly, when a user is trying to access a route that requires authentication(such as the one above), the decode middleware below is used to decode the jwt token.

export const decode = (req, res, next) => {
  if (req.cookies === "") {
    return res.status(400).json({ success: false, error: "No access token provided " });
  }
  const accessToken = req.cookies["Authorization"];
  try {
    const decoded = jwt.verify(accessToken, SECRET_KEY);
    req.userId = decoded.userid;
    req.userType = decoded.userType;
    return next();
  } catch (error) {
    return res.status(401).json({
      success: false,
      message: "Could not decode authorization token",
    });
  }
};

Below are my cors settings from the backend.

// Cors
const corsOptions = {
  origin: ["http://localhost:3000"],
  exposedHeaders: ["Authorization"],
};

app.use(cors(corsOptions));
app.use((req, res, next) => {
  res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content, Accept, Content-Type, Authorization");
  res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH, OPTIONS");
  res.setHeader("Access-Control-Allow-Credentials", true);
  next();
});

When a user logs in, an error is caught and the error is posted in the console with a 401 code along with the 'could not decode authorization token' from the decode function catch block from above. When I go to check the application settings in chrome, there is no Authorization token being set after login, but when I run the same GET request in postman, the cookies ARE being set.

I have tried different things such as settings 'httpOnly' to true as well as setting 'secure' to true but neither has worked. This is my first app that I have tried hosting and every feature was working fine while developing in localhost but once I put it on Heroku I have not been able to get the authorization to work in the browser even though all my requests from postman continue working.

I am not sure if this is a cors issue, an issue with the decode function, or a different issue altogether. Any help would be appreciated.

CodePudding user response:

If you're not on the same domain, you can't set cookie for the client from server, it works in postman since you're hitting the endpoint from the same domain.

https://stackoverflow.com/a/44516536/12490386

  • Related