66

Seems that something similar already has been discussed on stackoverflow, but i could not find exactly the same.

I am trying to send Cookie with CORS(Cross-origin resource sharing), but it is not working.

This is my code.

$.ajax(
    { 
      type: "POST",
      url: "http://example.com/api/getlist.json",
      dataType: 'json',
      xhrFields: {
           withCredentials: true
      },
      crossDomain: true,
      beforeSend: function(xhr) {
            xhr.setRequestHeader("Cookie", "session=xxxyyyzzz");
      },
      success: function(){
           alert('success');
      },
      error: function (xhr) {
             alert(xhr.responseText);
      }
    }
);

I dont see this cookie in request HEADER.

abatishchev
  • 92,232
  • 78
  • 284
  • 421
Kirill Reva
  • 1,027
  • 3
  • 12
  • 16

4 Answers4

70

You cannot set or read cookies on CORS requests through JavaScript. Although CORS allows cross-origin requests, the cookies are still subject to the browser's same-origin policy, which means only pages from the same origin can read/write the cookie. withCredentials only means that any cookies set by the remote host are sent to that remote host. You will have to set the cookie from the remote server by using the Set-Cookie header.

monsur
  • 39,509
  • 15
  • 93
  • 91
  • That is really strange. Why i can not pass cookies in the Header? – Kirill Reva Jan 23 '13 at 12:47
  • 5
    Although CORS allows cross-origin requests, the cookies are still subject to the browser's same-origin policy, which means only pages from the same origin can read/write the cookie. – monsur Jan 23 '13 at 13:00
  • Thanks everybody. Seems there is no to discuss here. – Kirill Reva Jan 23 '13 at 18:11
  • so how do we set them with `Set-Cookie` on the server/client making the request? – chovy Feb 06 '14 at 21:16
  • 9
    The cookies get set automatically, but are not readable by the webpage you sent the cors request from, because it's on another domain. if you issue another cors request the browser will however automatically append the cookie to the request (if withCredentials is set to true!!). The only thing that's different from normal ajax requests ist that you can't read the cookie content with JavaScript. – Dominik Goltermann Mar 07 '14 at 12:37
  • I've not set withCredentials, so the subsequent requests don't seem to be sending the cookie back to the remote server. After I set `withCredentials`, I'm getting an error in Chrome that `XMLHttpRequest cannot load . Response to preflight request doesn't pass access control check: A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin '' is therefore not allowed access. The credentials mode of an XMLHttpRequest is controlled by the withCredentials attribute.` where XXX is remote and YYY is local. – asgs Jun 21 '16 at 17:02
  • So, a couple other things. The request must return the `Access-Control-Allow-Origin` which corresponds to that of the requester (not *). On Chrome now you must also specify ["SameSite=None", "Secure"] in the set-cookie request too! – meawoppl Mar 27 '20 at 19:01
  • I posted an answer below that clarifies some of the modern needs here. – meawoppl Mar 27 '20 at 19:18
22

Please note this doesn't solve the cookie sharing process, as in general this is bad practice.

You need to be using JSONP as your type:

From $.ajax documentation: Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation.

$.ajax(
    { 
      type: "POST",
      url: "http://example.com/api/getlist.json",
      dataType: 'jsonp',
      xhrFields: {
           withCredentials: true
      },
      crossDomain: true,
      beforeSend: function(xhr) {
            xhr.setRequestHeader("Cookie", "session=xxxyyyzzz");
      },
      success: function(){
           alert('success');
      },
      error: function (xhr) {
             alert(xhr.responseText);
      }
    }
);
Kenster
  • 18,710
  • 21
  • 68
  • 90
abc123
  • 16,261
  • 6
  • 46
  • 76
  • 2
    Thanks @Justin Schuhmann Actually i indeed need to make CORS request , not JSONP. Does not CORS support cookie passing? – Kirill Reva Jan 22 '13 at 15:59
  • Hi, Actually using dataType: "text", worked for me like a charm! Thanks! – Eswar Rajesh Pinapala Jan 10 '14 at 06:53
  • 1
    What is bad practice? Using cookies in CORS requests? If so, why is it bad practice? – Mnebuerquo Aug 31 '14 at 20:23
  • @Mnebuerquo I'm sorry? cookie sharing is a bad practice, unless it is to sub-domains. Because a cookie isn't secure, so just send the necessary data over the AJAX call. Other than sending them as "security" i don't know why you'd waste your time with thme. – abc123 Sep 01 '14 at 23:09
  • 2
    I see. I didn't realize the OP was trying to send a cookie to a different domain than that which set it. Javascript being able to send cookies to a different domain would enable all kinds of session hijacking. Ideally you'd make your cookies http-only so the javascript can't touch them at all. I must have been sleeping when I read this the first time. Thanks! – Mnebuerquo Sep 03 '14 at 13:10
  • This likely won't work any more. https://blog.chromium.org/2019/05/improving-privacy-and-security-on-web.html Take a look at the answer I posted below which clarifies some of the changes made recently in chrome – meawoppl Mar 27 '20 at 19:23
14

There have been a slew of recent changes in this arena, so I thought a fresh answer would be helpful.

To have a cookie sent by the browser to another site during a request the following criteria must be met:

A lot of people find their way to this post trying to do local development against a remote endpoint, which is possible if the above criteria are met.

meawoppl
  • 2,397
  • 21
  • 29
  • 1
    In case of a XMLHttpRequest (which adds a `X-Requested-With` header) you might also need to set the `Access-Control-Allow-Headers` to `X-Requested-With` serverside otherwise CORS policy might block the request – Shocker Oct 31 '20 at 15:02
5

I had this same problem. The session ID is sent in a cookie, but since the request is cross-domain, the browser's security settings will block the cookie from being sent.

Solution: Generate the session ID on the client (in the browser), use Javascript sessionStorage to store the session ID then send the session ID with each request to the server.

I struggled a lot with this issue, and there weren't many good answers around. Here's an article detailing the solution: Javascript Cross-Domain Request With Session

Per Kristian
  • 661
  • 8
  • 10
  • 1
    Is this solution secure? I feel like it has a security breach. I'm not sure if it's recommended to store the session ID in the sessionStorage – Mollo Feb 18 '20 at 18:30
  • This approach does not work for serverless type applications, where jwt tokens are used as cookies... – meawoppl Mar 27 '20 at 19:24