Search code examples
node.jsexpressherokucookiescross-domain

Express/Heroku - Cookie set on server web app instead of client web app


I got this case where after deployment to Heroku, my cookies are not set to the client. When running localhost, the cookies are set as expected and its working, but after deployed to Heroku the cookies are set on the backend web app instead of the client (where I want it to be set).

The client is deployed as the first web app below, and the server as the later, so they are separated Separate client and server

When I log on into the client after it has been deployed (react), the cookie is not set there but on the backend app instead. So the cookie is set successfully, but not to my client side. enter image description here

Why are the cookies ending up here?! I want cookie on client enter image description here

My express, cookie-parser, cors app looks like like this:

const express = require("express");
const cors = require("cors");
const morgan = require("morgan");
const mongoose = require("mongoose");
var cookieParser = require("cookie-parser");

const app = express();
const PORT = process.env.PORT || 4040;
require("dotenv").config();

//connect to db
mongoose.connect(
  process.env.MONGODB_URI ||
    `mongodb+srv://${process.env.MONGODB_USER}:${process.env.MONGODB_PASSWORD}@shopproject.xaroy.mongodb.net/shopitems?retryWrites=true&w=majority`,
  {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  }
);

mongoose.connection.on("connected", () => {
  console.log("Connected to Mongodb");
});

//middleware

app.set("trust proxy", 1);
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());

app.use(
  cors({
    origin: ["https://gigvilla.herokuapp.com", "http://gigvilla.com"],
    credentials: true,
    allowedHeaders: [
      "Content-Type",
      "Accept",
      "Origin",
      "X-Requested-With",
      "Authorization",
      "Set-Cookie",
    ],
  })
);

//http req logger
app.use(morgan("tiny"));

app.get("/", (req, res) => {
  res.cookie("trol", "valle").send("hello");
});

//Getting routes to app
const authRoutes = require("./routes/auth");
const shopRoutes = require("./routes/shop");
const storeRoutes = require("./routes/store");
//below test

app.use(authRoutes);
app.use(shopRoutes);
app.use(storeRoutes);
// app.use(storeRoutes);
//test

app.listen(PORT, console.log(`server is running at ${PORT}`));

with the following snippet sending the cookie

exports.loginUser = async (req, res, next) => {
  //Validate
  const { error } = loginValidation(req.body);
  if (error) return res.status(400).send(error.details[0].message);

  //Check for existing user
  const user = await User.findOne({ email: req.body.email.toLowerCase() });
  if (!user) return res.status(400).send("Email does not exist");

  if (user.authenticated === false) return res.status(400).send("Not verified");

  //Password is correct
  const validPass = await bcrypt.compare(req.body.password, user.password);
  if (!validPass) return res.status(400).send("Invalid password");

  //Create and assign JWT token
  const token = jwt.sign(
    { userId: user._id, userName: user.user },
    process.env.JWT_TOKEN_SECRET
  );
  res
    .status(202)
    .cookie("Authorization", "Bearer " + token, {
      httpOnly: true,
      maxAge: 3600000,
      sameSite: "none",
      secure: true,
    })
    .cookie("just testing", "my name is", {
      httpOnly: false,
      maxAge: 3600000,
      sameSite: "none",
      secure: true,
      path: "/",
    })
    .json({ userName: user.user });
};

Anyone know how to solve this? Getting very desperate at this point.. (16 hours in..)


Solution

  • Herokuapp.com is included in the Mozilla Foundation’s Public Suffix List so it will prevent you from setting cookies on herokuapp.com or *.herokuapp.com. You can check the list here.

    I recommend you hosting it on any other cloud provider which can help you to set cookies.

    Also, you can check the heroku dev center why it is not allowed to set cookies. It might help you to understand the issue is not with the code, it is with the hosting.