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

Viewed 202

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.

1 Answers
Related