0

Currently I am trying to save a JWT token in the clients cookies after a login fetch. When looking at the set-cookie response in the Network tab of dev tools I get This set cookie was blocked because its domain attribute was invalid with regards to the current host url.

cookie set response

This is the code I use to set the cookie:

const token = user.generateVerificationToken();
const cookieOptions = {
    domain: 'http://dev.com:3000',
    // expires: new Date(Date.now() + 60000),
    maxAge: 30 * 24 * 60 * 60 * 1000, // 30 days
    httpOnly: true,
    secure: req.secure || req.headers['x-forwarded-proto'] === 'https',
};
  
res.cookie('jwt', token, cookieOptions);

These are the cors settings:

app.use( cors({credentials: true, origin: 'http://dev.com:3000'}) );

This is what the fetch request looks like on the client:

let res = await fetch( 'http://api.dev.com:4000/login', {
        body: JSON.stringify(data), // login data
        headers: {
            'Content-Type': 'application/json'
        },
        method: 'POST',
        credentials: 'include'
    })

/etc/hosts:

127.0.0.1 dev.com
127.0.0.1 api.dev.com

Can anyone help with this? I can't find what needs to be done to fix this.

Jared Parker
  • 390
  • 2
  • 3
  • 16

1 Answers1

3

This has nothing to do with CORS. Instead, this is a problem with cookies (cross-domain issue).

You're trying to set a cookie for dev.com:3000, but the API is located on api.dev.com:4000. It is cross-domain and cross-origin, and because of that, it is invalid cookie.

If I recall correctly, it is impossible for you to set cookies to a different domain. If such things were possible, it would be a serious security issue.

So, there are two possible solutions to your problem:

  • If you really want to set cookie for dev.com:3000, the workaround that will work is to provide the cookie value as a res object from your API, and then in the front-end, you turn that res into a cookie. You can use various JavaScript's APIs or plugins for that, such as document.cookie, react-cookie, universal-cookie, js-cookie, and many more.
  • If you ask for my opinion, just turn that api.dev.com:4000 to api.dev.com:3000, or run them in the same port. It is possible to send cookies from the same domain origin.
  • I noticed that you're using Next.js. You can use the serverless API to receive the cookie from your backend (you still have to send the cookie via res too), then set the cookie using the serverless API. As the serverless API and the frontend are located in the same 4000 port, the cookie should be valid. This way, you can preserve the httpOnly attribute of the cookie.

For further reference, refer to my answer on this question.

Nicholas
  • 2,800
  • 1
  • 14
  • 21
  • Thank this really helps clear things up. Where you say 'change api.dev.com:4000 to api.dev.com:3000' how do I go about doing this on a local environment. Because in production they'll be on the same port (different servers, same domain), but with local development how do I go about this. Do I need to edit this in /etc/hosts, do I need to proxy requests, or something else? – Jared Parker Mar 14 '21 at 12:56
  • I thought you're using `api.dev.com` in the development? It should be possible to change the port if you're using different subdomains. If you're using `localhost` however, you just set the `origin` to `*`. Don't forget to change it in production. – Nicholas Mar 14 '21 at 13:06
  • Did my answer help you? If so, please mark it as accepted. Thanks. – Nicholas Mar 15 '21 at 00:54