Reputation: 2151
The Cookie that I am sending from http://localhost:5000/users/register , is not being set into the header of http://localhost:5000/users/register. I am able to access the cookie in the body but not in the headers.
My App.js code is
require("dotenv").config();
const express = require("express");
const mongoose = require("mongoose");
const cors = require("cors");
const fileUpload = require("express-fileupload");
const cookieParser = require("cookie-parser");
const users = require("./routers/users");
const app = express();
app.use(express.json());
app.use(cookieParser());
app.use(cors());
app.use(
fileUpload({
useTempFiles: true,
})
);
// connecting to MongoDB
const mongoURL = process.env.MONGO_URL;
mongoose
.connect(mongoURL, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
})
.then(() => console.log("DataBase has been connected !"))
.catch((err) => console.log("Cannot connect to database", err.message));
// routes
app.use("/users", users);
const port = process.env.PORT || 5000;
app.listen(port, () => {
console.log(`I am listening at ${port}`);
});
My Router's Code
const express = require("express");
const bcrypt = require("bcrypt");
const { Users, userSchema } = require("../models/user");
const jwt = require("jsonwebtoken");
const router = express.Router();
// registering
router.post("/register", async (req, res) => {
try {
const { name, email, password } = req.body;
console.log(name, email, password);
//console.log(Users);
//console.log(userSchema);
let user = await Users.findOne({ email });
if (user) return res.status(404).json({ msg: "The email already exists" });
if (password.length < 6)
return res.status(404).json({ msg: "The password is less than 6" });
// Hashing password
const newPassword = await bcrypt.hash(password, 10);
// creating a user and saving in db
user = await new Users({ name, email, password: newPassword });
await user.save();
// creating JWT token for authenticating the user
const accessToken = createAccessToken({ id: user._id });
const refreshToken = createRefreshToken({ id: user._id });
// Cookie is being sent in the headers to the listed "path"
res.cookie("refreshToken", refreshToken, {
httpOnly: true,
path: "/users/refreshtoken",
});
res.json({ accessToken });
//return res.json({ password, newPassword, user, accessToken, refreshToken });
} catch (err) {
return res.status(500).json({ msg: err.message });
}
});
router.get("/refreshtoken", (req, res) => {
try {
const rfToken = req.cookies.refreshToken;
if (!rfToken)
return res.status(400).json({ msg: "Please login or sign up" });
// verifying the token that we sent when user registered
// the token shows ig it's the registered user or not
jwt.verify(rfToken, process.env.REFRESH_TOKEN, (error, decoded) => {
if (error)
return res.status(400).json({ msg: "Please login or sign up" });
console.log(decoded);
const accessToken = createAccessToken({ id: decoded.id });
res.json({ decoded, accessToken });
});
res.json({ msg: "DS", rfToken });
} catch (error) {
return res.status(500).json({ msg: error.message });
}
});
const createAccessToken = (userID) => {
return jwt.sign(userID, process.env.ACCESS_TOKEN, { expiresIn: "1d" });
};
const createRefreshToken = (userID) => {
return jwt.sign(userID, process.env.REFRESH_TOKEN, { expiresIn: "7d" });
};
module.exports = router;
The Cookie is not being set to the header of the "/users/refreshtoken", it is being sent in the body, I can see the cookie in the body of "/users/refreshtoken" but not in the header. I don't know why.
Upvotes: 1
Views: 297
Reputation: 707328
This error is usually caused by improper asynchronous sequencing which causes you to have one or more code paths that can attempt to send multiple responses to the same incoming request.
I see an example of this in your router.get("/refreshtoken", ...)
route handler. One place this problem can occur is here where it's marked:
router.get("/refreshtoken", (req, res) => {
try {
const rfToken = req.cookies.refreshToken;
if (!rfToken)
return res.status(400).json({ msg: "Please login or sign up" });
// verifying the token that we sent when user registered
// the token shows ig it's the registered user or not
jwt.verify(rfToken, process.env.REFRESH_TOKEN, (error, decoded) => {
if (error)
return res.status(400).json({ msg: "Please login or sign up" });
console.log(decoded);
const accessToken = createAccessToken({ id: decoded.id });
=====>
res.json({ decoded, accessToken });
=====>
});
=====>
res.json({ msg: "DS", rfToken });
=====>
} catch (error) {
return res.status(500).json({ msg: error.message });
}
});
This code will launch the asynchronous and non-blocking jwt.verify()
function and then will immediately execute:
res.json({ msg: "DS", rfToken });
Then, some time later it will execute either:
return res.status(400).json({ msg: "Please login or sign up" });
or
const accessToken = createAccessToken({ id: decoded.id });
both of which will try to send a second response. It appears to me that your code in this route has three possible outcomes:
That means you should have three non-overlapping responses. But, you have four places you send a response and they overlap, causing duplicate responses. I don't know exactly why you have the res.json({ msg: "DS", rfToken });
line of code as it is always run anytime there is a token present (whether valid or invalid). You need to fix that. Probably you should just remove that line of code entirely or replace one of the other responses with this line of code inside the jwt.verify()
callback.
Upvotes: 1