10

I'm using fetch to do a request to the backend. The cookie ISN'T set when I use a different domain. The cookie IS set when I use the same domain.

Why is it not being set?

I modified my /etc/hosts file to use pseudonymns to test using the same and different domain, and made sure they are not blacklisted by the browser either.

If I use local-test-frontend.com for both the browser and server domain it works, but if I change the backend url to local-test-backend.com it fails.

*Note that my front end url I test it from is * http://local-test-frontend.com:3000/login

Javascript

    fetch('http://local-test-backend.com/login',  {
        mode: 'cors',
        method: 'POST',
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
        },
        body: JSON.stringify(loginRequest),
        credentials: 'include'
    }).then(// Other code here.....

Server Response Headers

Access-Control-Allow-Credentials    
true
Access-Control-Allow-Origin 
http://local-test-frontend.com:3000
Content-Length  
103
Content-Type    
application/json
Date    
Wed, 10 Jul 2019 07:23:49 GMT
Server  
Werkzeug/0.15.1 Python/3.7.3
Set-Cookie  
MY_TOKEN=a7b8ad50f19…end.com; Path=/; SameSite=Lax
tt_Gantz
  • 2,786
  • 3
  • 23
  • 43
  • Can you make your question clear? I didn't see what is the issue here? – zakir Jul 10 '19 at 08:09
  • By typing a URL into the address bar, you request an HTML document from A (from origin X). This gives an HTML document in response B. You then use JavaScript to make a request (C) to a different origin (Y) which gets a response (D). Which of those includes the `Set-Cookie` header? (I think it is a D but I want to be sure). How do you then determine that the cookie has not been set? Do you make additional requests? To which origins? – Quentin Jul 10 '19 at 08:43
  • You can't share cookies across domains https://stackoverflow.com/questions/3342140/cross-domain-cookies though – hackerl33t Jul 10 '19 at 08:45
  • @zakir Just added "Why is it not being set?" to the question body. Pretty much, when sending a request to a server, with a different domain to that of the browser, then the cookie doesn't get set by the browser – tt_Gantz Jul 10 '19 at 09:19
  • @hackerl33t I'm not trying to share cookies across domains, I'm just trying to get a cookie set for my current domain by calling a server on a different domain. Not sure if that link/answer applies? – tt_Gantz Jul 10 '19 at 09:20
  • @Quentin I determined the cookie was not set by - inspecting the browser memory and by -sending subsequent requests and - checking `document.cookie` – tt_Gantz Jul 10 '19 at 09:31
  • @tt_Gantz how bout setting it manually then after you got the response? – hackerl33t Jul 10 '19 at 10:21
  • 1
    @hackerl33t unfortunately I wanted this to be an httponly cookie (i.e. only accessible by the browser) so in this case it won't work. But that would've been a solution – tt_Gantz Jul 10 '19 at 10:49

2 Answers2

33

As of 2021 with Edge 90.0.796.0 on Linux, I managed to set CORS cookie with the following approach:

  1. Client initializes asynchronously a fetch request with credentials: 'include'. See here for more details.
  2. To do CORS, server response header must contain Access-Control-Allow-Origin explicitly set to a domain, could be different from the server domain. For example, in a Single-Page-App architecture, your frontend site is temporarily hosted at localhost:3000 and your backend server hosted at localhost:8000, then the header should be Access-Control-Allow-Origin: http://localhost:3000. See here and here.
  3. To allow client to process cookies, which is obviously a sensitive resource, server response header must further contain Access-Control-Allow-Credentials: true. See here. Note that this enforces a non-wildcard setting for Access-Control-Allow-Origin. See here - that's why in point 2 above, it has to be explicitly set to something like http://localhost:3000 rather than *
  4. When server sets the cookie, it has to include SameSite=None; Secure; HttpOnly. So overall something like Set-Cookie: session_id=12345; SameSite=None; Secure; HttpOnly. SameSite seems to be a relatively new requirement in latest browsers, and must be used with Secure together when SameSite is set to None.
  5. With regard to HttpOnly, I haven't found relevant materials, but in my experiment, omitting it caused the browser to ignore the Set-Cookie header.
  6. Further requests to the backend server also must have credentials: 'include' set.
wlnirvana
  • 1,811
  • 20
  • 36
4

I'm just trying to get a cookie set for my current domain by calling a server on a different domain.

You can't, at least not directly. Cookies belong to the origin that set them.

The closest you could come would be for the different domain to return the data in a non-Cookie format (such as the body of the response), and then to use client-side JS to store it using document.cookie.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • So it my server is on domain `server.com` and frontend is on domain `frontend.com`, then it's impossible for `frontend.com` to save a cookie automatically sent by `server.com` ? – tt_Gantz Jul 10 '19 at 09:30
  • @tt_Gantz — Correct. – Quentin Jul 10 '19 at 09:33
  • 2
    Colleagues, excuse me... But is it ok, that I see Cookies are set by another domain after the response? The remote server (cross-origin request) replies and sets PHPSSID and other coolies (!!!) – Vsevolod Azovsky Dec 25 '19 at 00:30
  • 1
    Cookies are set to the same domain unless you instruct the browser which domain it must send the cookies to. https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#define_where_cookies_are_sent – Dmitry Feb 17 '22 at 11:59