express icon indicating copy to clipboard operation
express copied to clipboard

Cookies set on development, but not on production

Open henriquedevelops opened this issue 1 year ago • 1 comments

2 Docker containers:

  1. Server: Express.JS REST API with JWT authentication.
  2. Client: Next.JS app that uses Axios to talk with the server.

I tested it on localhost with Docker Compose: Everything working fine (both Postman and the browser successfully store the token as a cookie to use on subsequent requests.).

I deployed it to Google Cloud Run (one service for each container). Everything working fine except that now only requests made through Postman are storing the token as a cookie.

The browser (the Next.JS app) no longer does the same, even though the request returns a successful response there is no token in the browser cookies.

I did some research, found a few similar problems, and the solutions usually involve setting up some CORS configurations, so I updated my code by adding these configurations, but the issue remains.

I am currently trying it like this:

Server-side:

export const login = async (req: Request, res: Response) => {

...

  const accessToken = jwt.sign({ username, id, isAdmin }, jwtSecret, {
    expiresIn: "12h",
  });

  res
    .status(200)
    .cookie("accessToken-Myapp", accessToken, {
      secure: true,
      sameSite: "none",
    })
    .end();
};
const app = express();

app.use(helmet());
app.use(
  rateLimit({
    max: 300,
    windowMs: 60 * 60 * 1000,
    message: "Please try again later!",
  })
);

const corsConfig = {
  origin: true,
  credentials: true,
  allowedHeaders: ["Content-Type", "Authorization"],
};

app.use(cors(corsConfig));
app.options("*", cors(corsConfig));

app.use(express.json());
app.use(cookieParser());
app.use("/images", express.static("images"));

app.get("/health", (_, res: Response) => res.sendStatus(200));
app.use("/api/v1/auth", authRouter);

Client-side:

import axios from "axios";

export default axios.create({
  baseURL: `https://my-cloud-run-server-container-address/api/v1/`,
  withCredentials: true,
});

henriquedevelops avatar Apr 30 '23 00:04 henriquedevelops

Are you running the NextJS app locally, and backend elsewhere? If that is so, your cookie probably got restricted to the backend's ip/domain

b1ek avatar Jul 18 '23 03:07 b1ek

in your login function, try setting httpOnly to true, your cookie might be deemed insecure as clientside JS can access it, and might be ignored

res .status(200) .cookie("accessToken-Myapp", accessToken, { secure: true, sameSite: "none", httpOnly: true }) .end(); };

danillo7789 avatar Aug 01 '24 16:08 danillo7789

I agree with @danillo7789, here's the same thing,

res
  .status(200)
  .cookie("accessToken-Myapp", accessToken, {
    secure: true, // Ensure you are using HTTPS in production
    httpOnly: true, // This ensures the cookie is not accessible via JavaScript
    sameSite: "none"
  })
  .end();

Also, I would take a look at this res.cookie(name, value [, options]) in Express 4x API Reference.

IamLizu avatar Aug 03 '24 03:08 IamLizu