0

Backend is written with Expressjs:

middleware used as following

app.use(cookieParser())

app.all('*', function (req, res, next) {
    res.header("Access-Control-Allow-Origin", process.env.FRONTEND);
    res.header("Access-Control-Allow-Credentials", true);
    res.header("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,PATCH,OPTIONS");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    res.header("Access-Control-Allow-Headers", "Content-Type, Authorization, x-csrf-token");
    next()
});

argument for sending cookie:

try {
    const oneHourFromNow = new Date(Date.now() + 3600000)
    const Admins = await Admin.find({ password: req.body.password, name: req.body.name }).select("-password").select("-token").select("-_id");
    if (Admins.length > 0) {
        res.cookie("admin-cookie", "123", {
            httpOnly: false,
            secure: true,
            // sameSite: "none",
            expires: oneHourFromNow,
            domain: process.env.DOMAIN,
            path: "/",
        });
        res.status(200).send("Cookie set")

Frontend request detail:

    const handleSubmit = async (event) => {
    console.log("state", username, password)
    event.preventDefault();
    let data = JSON.stringify({
        "name": username,
        "password": password
    });

    let config = {
        method: 'post',
        maxBodyLength: Infinity,
        // url: 'http://localhost:5000/client/login',
        url: `${process.env.REACT_APP_BASE_URL}/client/login`,
        headers: {
            'Content-Type': 'application/json',
        },
        data: data,


        credential: 'include'
    };
    axios.defaults.withCredentials = true;

    axios.request(config, { withCredentials: true })
        .then((response) => {
            console.log("cookie response", response)
            if (response.status === 200) {
                console.log("success")
                // window.location.href = "/products";
            }
            console.log(JSON.stringify(response.data));
        })
        .catch((error) => {
            console.log(error);
        });

};

After I hosted both as two separate Cloud Run service on GCP, the request can be sent with correct response status 200, and a cookie can be found under inpection(F12) -> network -> login as below:enter image description here

Note there's a exclamation mark around Domain, but I find no explanation for that...

However, under application, storage -> cookies, it's not there enter image description here

I tried everything I can find online and none worked.

A few things worth noting for troubleshooting:

  1. cookie is presents in the response, so the request is successfully made, and the response does receive a header with 'Set-cookie' and its cookie detail
  2. it also works fine in localhost and with postman, for localhost, I can see the cookie being stored under application -> storage -> cookies
  3. frontend and backend are hosted on different URL generated by GCP Cloud Run

I tried change the CORS policy header, I tried adding withCredential in multiple ways in the frontend and numerous console.log, I also tested with local deployment and postman. I pretty much tried what I can find online, none has worked.

idchi
  • 761
  • 1
  • 5
  • 15
  • What are the values of `process.env.DOMAIN`, `process.env.FRONTEND`, and `process.env.REACT_APP_BASE_URL`? What is the [Web origin](https://developer.mozilla.org/en-US/docs/Glossary/Origin) of your server? You can redact those values a bit if you want to divulge the exact ones. – jub0bs May 11 '23 at 07:35
  • _Note there's a exclamation mark around Domain, but I find no explanation for that..._ Be aware that you cannot simply use any values for the `Domain` attribute. The set of valid values is determined by the domain of the server that sets the cookie in question. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#domaindomain-value: _Only the current domain can be set as the value, or a domain of a higher order, unless it is a public suffix._ You may not even need to set your cookie with a `Domain` attribute: _specifying `Domain` is less restrictive than omitting it._ – jub0bs May 11 '23 at 07:41
  • Does this answer your question? [Javascript fetch is not sending Cookie Header (CORS)](https://stackoverflow.com/questions/70590447/javascript-fetch-is-not-sending-cookie-header-cors) – jub0bs May 11 '23 at 07:49
  • Guys, thank you for your kindly help, I guess I've made tiny changes to my code too much. Then they didn't even work on localhost anymore, so I changed back to the version where it was working. And found that after I deployed the app on google cloud run, I was able to set the cookie on the backend website. I saw it under application. Once I changed the domain of the cookie to frontend's domain (different domain), the cookie cannot be set appropriately again. I guess it's more of setting cookie for one website from one other website's response. I will be back when I gain more network knowledge – Tianze Hua May 12 '23 at 15:14

0 Answers0