Search code examples
reactjsherokucookiessession-cookiesnetlify

Unable to set cookie between React and express


I am trying to set a cookie between my react frontend (on netlify) and my express backend (on heroku). My code does work perfectly fine in localhost but not in production. In production I am getting an 500 server error and the cookie is not being set on the frontend. (If I remove the code that set the cookie on the backend, the code works as expected).

I know this question has been answered but I am still unable to find a solution.

Any help with this would be greatly appreciated.

Here some links I tried

Cross-Domain Session Cookie (Express API on Heroku + React App on Netlify)

Not able to set/receive cookies cross-domain using Netlify and Heroku

Cookie sent to localhost but not to https domain

My code:

Index.ts (express)

import express from "express";
import routes from "./routes";
import connectToDb from "./utils/connectToDb.util";
import dotenv from "dotenv";
import apiError from "./middlewares/apiError.middleware";
import cookieParser from "cookie-parser";
import deserializeUser from "./middlewares/deserializeUser";
import cors from "cors";
import session from "cookie-session";

dotenv.config();
const app = express();
const PORT = process.env.PORT || 5000;

app.use(
  cors({ origin: true, credentials: true, exposedHeaders: ["set-cookie"] })
);
app.use(express.json());
app.use(cookieParser());
app.use(deserializeUser);

app.enable("trust proxy");
app.set("trust proxy", 1);
app.use(
  session({
    secret: "dede",
    sameSite: "none",
    maxAge: 1000 * 60 * 60 * 24 * 7,
    secure: false,
  })
);

app.use(routes);
app.use(apiError);

app.listen(PORT, () => {
  console.log(`Server started on ${PORT}`);

  connectToDb();
});

Login Controller (express)

export const login = async (
  req: Request<{}, {}, UserLoginInput>,
  res: Response,
  next: NextFunction
) => {
  try {
    const user = await findUserByEmail(req.body.email);

    if (!user) {
      return next(UserError.invalidInputError("email"));
    }

    const isPasswordValid = await user.validatePassword(req.body.password);

    if (!isPasswordValid) {
      return next(UserError.invalidInputError("password"));
    }

    const jwt_token = createToken(user._id);

    res.cookie("jwt_token", jwt_token, {
      maxAge: 1000 * 60 * 60 * 24 * 7,
      httpOnly: true,
      domain: "https://website.com",
      sameSite: "none",
    });

    res.status(200).json({ user });
  } catch (error) {
    console.log("ERROR in login", error);
    res.status(500).send(error);
  }
};

Api call (React)

import axios from "axios";

const API_URL = process.env.REACT_APP_BACKEND_URL || "http://localhost:5000";

const api = axios.create({
  baseURL: API_URL + "/api/users",
  withCredentials: true,
});

export const login = async (email: string, password: string) => {
  const response = await api.post("/login", { email, password });

  console.log(response);

  return response.data;
};

Solution

  • I recently got the same issue, I can clearly see the cookie in the response, but somehow it didn't show up in the browser store. And I also tried the links you mentioned above, trying to set up sameSite,secure and domain properties and etc. None of them worked out in my case. But in the end I deployed my frontend app and backend app under the same url on Heroku following a video I found on youtube, the link is here:https://www.youtube.com/watch?v=5dQC2JUd27g, hopefully, it will solve your problem.