最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Express not setting Cookie - Stack Overflow

programmeradmin1浏览0评论

I have 2 servers. One hosting a next.js application on localhost:5555 and another hosting an express server for the api on localhost:4444.

The authentication api returns a cookie however this is not being set in the browser running on localhost:5555.

  res.cookie('cokkieName', 'bob', {
        domain: '127.0.0.1:5555',
        maxAge: 900000,
        httpOnly: true,
    });

    res.status(200).json({
        session: jwtSigned,
        role: 'default',
    });

My cors setup is:

const options: cors.CorsOptions = {
    allowedHeaders: ['Origin', 'X-Requested-With', 'Content-Type', 'Accept', 'X-Access-Token', 'Authorization'],
    credentials: true,
    methods: 'GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE',
    origin: 'http://localhost:5555',
    preflightContinue: false,
};

I'd prefer to set the cookie with the api rather than on the via next.js.

I've tried alternating the cors settings but have had no success. The client call uses axios and has withCredentials set.

I have 2 servers. One hosting a next.js application on localhost:5555 and another hosting an express server for the api on localhost:4444.

The authentication api returns a cookie however this is not being set in the browser running on localhost:5555.

  res.cookie('cokkieName', 'bob', {
        domain: '127.0.0.1:5555',
        maxAge: 900000,
        httpOnly: true,
    });

    res.status(200).json({
        session: jwtSigned,
        role: 'default',
    });

My cors setup is:

const options: cors.CorsOptions = {
    allowedHeaders: ['Origin', 'X-Requested-With', 'Content-Type', 'Accept', 'X-Access-Token', 'Authorization'],
    credentials: true,
    methods: 'GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE',
    origin: 'http://localhost:5555',
    preflightContinue: false,
};

I'd prefer to set the cookie with the api rather than on the via next.js.

I've tried alternating the cors settings but have had no success. The client call uses axios and has withCredentials set.

Share Improve this question asked Oct 23, 2019 at 12:56 memyselfandmyiphonememyselfandmyiphone 1,1104 gold badges21 silver badges43 bronze badges 4
  • Did you try remove the port in the domain part of your cookie configuration ? – mJehanno Commented Oct 23, 2019 at 13:08
  • I did. The result was the same and the cookie wasn't set. – memyselfandmyiphone Commented Oct 23, 2019 at 13:17
  • Try it with real domains, localhost interacts poorly with storage, cookies, CORS, also in browser-dependent ways as I remember. Fake some 127.0.0.1 domains via hosts or something. Edit: it seems to be "wontfix" in case of Chrome for example (stackoverflow.com/questions/10883211/…) – tevemadar Commented Oct 27, 2019 at 14:47
  • Please try to change 127.0.0.1:5555 to localhost:5555 – Vo Kim Nguyen Commented Oct 29, 2019 at 2:28
Add a comment  | 

5 Answers 5

Reset to default 11 +100

As mentioned in the other answer, you cannot set cookie on a different domain, as it can be a security risk.

But from your question...

Since the API server is running the authentication logic, the cookie should be set on the API server domain, NOT on client domain

So in your API server, you can change code to

res.cookie('cokkieName', 'bob', {
        domain: '127.0.0.1:4444',
        maxAge: 900000,
        httpOnly: true,
    });

or just remove the domain as it defaults to server domain.

res.cookie('cokkieName', 'bob', {
            maxAge: 900000,
            httpOnly: true,
 });

As you have a client running on localhost:5555 and API server running on localhost:4444, it's a cross domain call and you need to pass withCredentials option to axios to pass the cookie. You might not be able to see the cookie in browser, as it can be a security risk, but can echo the cookie value on server console.

axios.get("url",{
    withCredentials: true
    }).then(res => {
            console.log(res);
    });

Note that credentials option work only if Access-Control-Allow-Origin header is not a wildcard like *

I have a created a server to mimic the code you posted. The server basically echoes the request cookie back.

It can be accessed through this stackblitz. You can toggle the withCredentials flag to see the difference in response

You can not set a cookie for other domains, Because that would be an enormous security risk.

But if you are looking for a way to share a cookie between your applications, the only way you have is to share a single domain between these applications, either separate them by url prefix or create one of them as a subdomain of other.

domain.com and api.domain.com. This way by specifying domain.com in your cookie both domains have access to it

If you concern about developing environment of yours, you can use Nginx and proxy_pass these two applications in single domain

What you are trying to do is definitely possible, the problem is that cookies are not port specific: Are HTTP cookies port specific? so you should specify a domain name but no port.

If you set a Cookie on its own domain (or if you don't specify it at all), all of the subsequent requests will carry the cookie even if initiated by a different port (only when withCredentials set to true, though). Also, note that, if set, the domain of the Cookie must match exactly the current domain, or parent domain (localhost is considered as different than 127.0.0.1)

Note: doing so shows the following warning in Chrome:

A cookie associated with a cross-site resource at http://example.com/ was set without the SameSite attribute. A future release of Chrome will only deliver cookies with cross-site requests if they are set with SameSite=None and Secure. You can review cookies in developer tools under Application>Storage>Cookies and see more details at https://www.chromestatus.com/feature/5088147346030592 and https://www.chromestatus.com/feature/5633521622188032.

So, prepare your code for the future web standards!

I had a similar problem with nuxt.js. To set cookies in your browser using express, I suggest using the library Cookies

In my case I set cookies in express like this:

setResponseCookie(req, res, token, strategyName) {

    const isHttps = req.protocol === 'https';
    let { cookie: { maxAge } } = config;
    const cookieSettings = isHttps => ({
        maxAge,
        httpOnly: true,
        secure: isHttps,
    });

    const cookies = new Cookies(req, res);
    cookies.set('auth.strategy', strategyName, cookieSettings(isHttps))
    cookies.set('auth.token', token, cookieSettings(isHttps))
}

and then in express route you can add to this like:

let token = sign(user);
this.setResponseCookie(req, res, token, 'local-login')
res.json({ token, status: 'success' });

or

let token = sign(req.user);
this.setResponseCookie(req, res, token, 'google')
res.redirect(config.client.url);

I managed to fix this issue of the server not setting the browser cookies by setting my res.cookie like the following

res.cookie("Test", "If you see this then it works", {httpOnly: false, secure: true, sameSite: "none"}).json({message: "Finished"});

I checked to see if the cookie was set by opening up the chrome dev tools, going to the application, then cookies, then the site URL.

There are a few things I would like to preference about the above code. This method only works on a URL starting with https, this means it will not fix the problem if on a URL like http://localhost:3000. I don't know if it matters if httpOnly is true or false. Also, What is necessary when setting the cookie this way is to pass in the properties secure: true, sameSite: "none". Passing these values into res.cookie was what finial fixed the issue for me. I have not seen this solution posted anywhere and decided I out to let you know.

My code that fetches the data from the API and triggers the server to set the browser cookie looks like this for anyone who is interested.

fetch(domain.com/testSetCookie', {
        method: 'get',
        mode: "cors",
        credentials: 'include' //<-- important
    })
    .then((res) => {
        //console.log(res);
        return; //res.json();
    })
    .then((data) => {
        console.log(data);));
    })
    .catch((err) => {
        console.log("an error happeoned");
        console.log(err);  
    });
发布评论

评论列表(0)

  1. 暂无评论