1

I am new to MERN. I was using this code below . I followed a youtube tutorial and it was working fine for me for 4 to 5 days but now suddenly it has stopped working. I didn't change anything. I am not able to login, logout or even fetch data. My postman is giving positive results using these api but it won't work on my code. I want to remind you guys again, it was working fine for 4 to 5 days.

const User = require("../model/user");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");

const signup = async (req, res, next) => {
  const { fname, lname, email, password, role, phone } = req.body;
  let existingUser;
  try {
    existingUser = await User.findOne({ email: email });
  } catch (err) {
    console.log(err);
  }
  if (existingUser) {
    return res.status(400).json({ message: "user already exists" });
  }
  const hashedPassword = bcrypt.hashSync(password);
  const user = new User({
    fname,
    lname,
    email,
    password: hashedPassword,
    phone,
    role,
  });
  try {
    await user.save();
  } catch (err) {
    console.log(err);
  }
  return res.status(201).json({ message: user });
};

const login = async (req, res, next) => {
  const { email, password } = req.body;
  let existingUser;
  try {
    existingUser = await User.findOne({ email: email });
  } catch (err) {
    console.log(err);
  }
  if (!existingUser) {
    return res
      .status(400)
      .json({ message: "user doesn't exist. Please signup" });
  }
  const isPasswordCorrect = bcrypt.compareSync(password, existingUser.password);
  if (!isPasswordCorrect) {
    return res.status(401).json({ message: "invalid email or password" });
  }

  const token = jwt.sign({ id: existingUser._id }, "change1122", {
    expiresIn: "1h",
  });
  res.cookie(String(existingUser._id), token, {
    path: "/",
    expires: new Date(Date.now() + 1000 * 3600),
    httpOnly: true,
    sameSite: "lax",
  });
  return res
    .status(200)
    .json({ message: "user logged in sucessfully", user: existingUser, token });
};

const verifyToken = (req, res, next) => {
  const cookies = req.headers.cookie;
  const token = cookies.split("=")[1];
  if (!token) {
    res.status(404).json({ message: "no token found" });
  }
  jwt.verify(String(token), "change1122", (err, user) => {
    if (err) {
      return res.status(404).json({ message: "invalid token" });
    }
    req.id = user.id;
  });
  next();
};

const getUser = async (req, res, next) => {
  const id = req.id;
  let user;
  try {
    user = await User.findById(id, "-password");
  } catch (err) {
    console.log(err);
  }
  if (!user) {
    res.status(404).json({ message: "user not found with the id" });
  }
  return res.status(200).json({ user });
};

const logout = async (req, res, next) => {
  const cookies = req.headers.cookie;
  console.log(cookies);
  const token = cookies.split("=")[1];
  if (!token) {
    res.status(404).json({ message: "no token found" });
  }
  const user = req.id;
  res.clearCookie(`${user}`);
  req.cookies[`${user}`] = "";
  return res.status(200).json({ message: "successfully logged out" });
};

exports.signup = signup;
exports.login = login;
exports.verifyToken = verifyToken;
exports.getUser = getUser;
exports.logout = logout;

Here is the error

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at new NodeError (node:internal/errors:372:5)    at ServerResponse.setHeader (node:_http_outgoing:576:11)
    at ServerResponse.header (E:\Reacct\pos\server\node_modules\express\lib\response.js:794:10)
    at ServerResponse.send (E:\Reacct\pos\server\node_modules\express\lib\response.js:174:12)
    at ServerResponse.json (E:\Reacct\pos\server\node_modules\express\lib\response.js:278:15)
    at getUser (E:\Reacct\pos\server\controller\user-controller.js:86:25)
    at processTicksAndRejections (node:internal/process/task_queues:96:5) {
  code: 'ERR_HTTP_HEADERS_SENT'
}
[nodemon] app crashed - waiting for file changes before starting...

I think i have an issue with cookies or token, I am new so i don't understand it properly.

Phil
  • 157,677
  • 23
  • 242
  • 245
  • `return res.status(404).json({message:"invalid token"})` only executes within the `jwt.verify()` callback. It will not prevent the `next()` from being called – Phil Aug 09 '22 at 00:52
  • Hey thanks for the reply, can u elaborate please? – abdul wahab nawaz Aug 09 '22 at 01:04
  • It is giving "invalid token" response now – abdul wahab nawaz Aug 09 '22 at 01:24
  • Does this answer your question? [Error: Can't set headers after they are sent to the client](https://stackoverflow.com/questions/7042340/error-cant-set-headers-after-they-are-sent-to-the-client) – Phil Aug 09 '22 at 01:46
  • 1) In `verifyToken`, move `next()` into the callback function, just after `req.id = user.id`. 2) Everywhere else you have `res.status(404).json(...)` should be prefixed with `return` – Phil Aug 09 '22 at 01:47
  • did all that , now it is giving an "invalid token" error – abdul wahab nawaz Aug 09 '22 at 02:14
  • Tried debugging the values you're using in `jwt.verify()`? Even `console.error(err)` would be more useful than ignoring the error completely – Phil Aug 09 '22 at 02:18

0 Answers0