Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting a cookie on a subdomain from an ajax request

I have a webapp on www.example.com and an API on api.example.com.

The webapp makes ajax calls to the API.

Somewhere I need to put a cookie on api.example.com to keep sessions track.

To track my problem I've set test cookies on both subdomaines from the webapp and the api. The webapp set a cookie on .exemple.com and the api set one on .exemple.com and another on api.exemple.com. Cookies are set using Domain=.exemple.com only. No path, no HTTPOnly.

Note: In the end I need only one on api.exemple.com. But theses are for the tests.

Direct queries using my browser (Firefox 16) works fine. Query on api: the two cookies are set and sent. Query on www: the cookie is set and the two from the api is sent too. (Provided I query www after the api, of course).

Now, I clean the browser cookies and query www only. Query on www: works fine, same as before. Subquery on api, from www's ajax request: no cookies are sent. Set-Cookies does nothing. Using Firebug I see the cookies in the response. But no traces of them on subsequent requests or the page informations.

I event tried to enable the cookies log on Firefox. Absolutly no traces of the cookies from api, not even a reject notice.

In the end I only need a way to store one cookie on api. And for that, I quite open :)

Informations: The two servers are NodeJS. I've tried to set the cookie on the server side (Set-Cookie header), on the client side (document.cookies), manually using firebug.

Others posts I've checked with no solutions (And many others which I don't recall):

setting cross-subdomain cookie with javascript

Cookies and subdomains

Can subdomain.example.com set a cookie that can be read by example.com?

like image 641
Alexandre Avatar asked Oct 21 '12 20:10

Alexandre


2 Answers

Set the allow Credentials header on api

Access-Control-Allow-Credentials: true

Use withCredentials for the request

$.ajax({
    url: a_cross_domain_url,
    xhrFields: { 
        withCredentials: true 
    }
});

Otherwise the XMLHttpRequest will not send the cookies, regardless of the Access-Control-Allow-Credentials header.

Remove the wildcard on Access-Control-Allow-Origin

Access-Control-Allow-Origin: http://www.example.com

The wildcard * will not work. The browser will discard the response if withCredentials was set.

References:

http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/

https://developer.mozilla.org/en-US/docs/HTTP_access_control

http://arunranga.com/examples/access-control/credentialedRequest.html

http://api.jquery.com/jQuery.ajax/

like image 132
Alexandre Avatar answered Oct 11 '22 10:10

Alexandre


In addition to the correct answer of Alexandre, this is my working CORS setting via .htaccess.

Added to .htaccess file on api.example.com in the directory with the phps (or above):

<IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin "https://www.example.com"
    Header set Access-Control-Allow-Headers "Origin, Content-Type, X-Auth-Token"
    Header set Access-Control-Allow-Credentials "true"
</IfModule>

And on www.example.com, I added to my AJAX call xhrFields: {withCredentials: true}. Here are all the settings:

jQuery.ajax({
    url: myURL,
    type: "POST",
    xhrFields: {withCredentials: true},
    dataType: "text",
    contentType: "text/xml; charset=\"utf-8\"",
    cache: false,
    headers: "",
    data: myCallJSONStr,
    success: function(myResponse) { etc....

Where URL makes a call to a php on api.example.com.

Please note that Alexandre is right, you must specify an exact subdomain, any wildcards unfortunately will not work. So this will NOT work:

Header set Access-Control-Allow-Origin "*"

This setting will be blocked by CORS when using the Access-Control-Allow-Credentials "true" setting.

like image 31
Al-Noor Ladhani Avatar answered Oct 11 '22 10:10

Al-Noor Ladhani