Cross-Domain Cookies

Go To StackoverFlow.com

183

I have two webapps WebApp1 and WebApp2 in two different domains.

  1. I am setting a cookie in WebApp1 in the HttpResponse.
  2. How to read the same cookie from HttpRequest in WebApp2?

I know it sounds weird because cookies are specific to a given domain, and we can't access them from different domains; I've however heard of CROSS-DOMAIN cookies which can be shared across multiple webapps. How to implement this requirement using CROSS-DOMAIN cookies?

Note: I am trying this with J2EE webapps

2010-07-27 09:10
by SundarJavaDeveloper


106

As other people say, you cannot share cookies, but you could do something like this:

  1. centralize all cookies in a single domain, let's say cookiemaker.com
  2. when the user makes a request to example.com you redirect him to cookiemaker.com
  3. cookiemaker.com redirects him back to example.com with the information you need

Of course, it's not completely secure, and you have to create some kind of internal protocol between your apps to do that.

Lastly, it would be very annoying for the user if you do something like that in every request, but not if it's just the first.

But I think there is no other way...

2010-07-27 09:23
by alcuadrado
If there is no other way, then how does StackExchange/OpenID work - Hawken 2012-10-26 21:30
@Hawken StackExchange/OpenID follows the same process as described above. You are directed to a different site (SO > SX), confirm your identity, and then are directed back to SO with the information you need. The OpenID Spec explains more, although Wikipedia does it more plainly - Nick Q. 2013-09-30 22:42
@alcuadrado How can you identify different users with this solution? Let say a user from a.com logged in and you set the information needed. Now when user go to b.com that uses same same script/application/plug-in how will you know that is the same user - Olcay Ertaş 2015-07-03 08:24
All users are logged in in cookiemaker.com actually. And it redirects the user to the different sites with a special and secure message that verifies that they are logged in and who they are. How to implement it is up to you, there are infinite ways of doing so. Maybe you can use this: http://jwt.io - alcuadrado 2015-07-10 12:14
@nickq This isn't unique to OpenID, SAML2 implementations conceptually work in pretty much the same way - Phil Lello 2016-04-10 10:25
@Andrew_1510 cookiebaker would be better ;- - Richard Turner 2016-05-12 09:16
@alcuadrado, could you please explain a bit more detailed: 1) how cookiemaker knows where to redirect user after he is authenticated? Should origin-url come in querystring? 2) How "information you need" is passed to example.com while redirecting to it at step 3 - Oleksandr Pshenychnyy 2016-10-10 16:46
Both have almost the same answer. 1) You redirect to something like cookimaker.com?redirection=yoursite.com 2) also as a query string paramete - alcuadrado 2016-10-11 05:52
Here is post with image tag , is that a better solution - stom 2016-12-13 09:35


95

Yes, it is absolutely possible to get the cookie from domain1.com by domain2.com. I had the same problem for a social plugin of my social network, and after a day of research I found the solution.

First, on the server side you need to have the following headers:

header("Access-Control-Allow-Origin: http://origin.domain:port");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Methods: GET, POST");
header("Access-Control-Allow-Headers: Content-Type, *");

Within the PHP-file you can use $_COOKIE[name]

Second, on the client side:

Within your ajax request you need to include 2 parameters

crossDomain: true
xhrFields: { withCredentials: true }

Example:

type: "get",
url: link,
crossDomain: true,
dataType: 'json',
xhrFields: {
  withCredentials: true
}
2014-09-16 06:07
by Ludovic
Or if you are not wanting to filter on origin, just use $SERVER['HTTPORIGIN'] instead of - Joel Teply 2015-04-29 16:22
This is the only things that worked for me. Also, * was not accepted as origin, so @Joel Teply's tip is needed - Guessed 2015-09-27 20:14
It worked perfectly when I run the code on localhost, but at runtime I don't see the cookies being set to the API and I get a 401 (unauthorized) error as expected. any ideas - Heba Gomaah 2015-10-14 13:17
This won't work if third-party cookies are disabled (automatic for some browser situations). See https://blog.zok.pw/web/2015/10/21/3rd-party-cookies-in-practice/ and http://www.allannienhuis.com/archives/2013/11/03/blocked-3rd-party-session-cookies-in-iframes/ for more information - robocat 2016-02-24 04:12
Don't use Joel's tip, because it is "in essence" the same as setting it to "*" which can open up subtle security holes so is discouraged, see http://stackoverflow.com/questions/12001269/what-are-the-security-risks-of-setting-access-control-allow-origi - rogerdpack 2017-04-14 18:50
on the server side of which domain - Nick Manning 2018-02-22 22:48


59

As far as I know, cookies are limited by the "same origin" policy. However, with CORS you can receive and use the "Server B" cookies to establish a persistent session from "Server A" on "Server B".

Although, this requires some headers on "Server B":

Access-Control-Allow-Origin: http://server-a.domain.com
Access-Control-Allow-Credentials: true

And you will need to send the flag "withCredentials" on all the "Server A" requests (ex: xhr.withCredentials = true;)

You can read about it here:

http://www.html5rocks.com/en/tutorials/cors/

https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS

2013-04-06 00:55
by Vitae Aliquam
This wont work for some users because CORS cookies will not work if third-party cookies are disabled e.g. Safari by default e.g. Mozilla settings. Google more examples and an article about why Facebook doesn't use third party cookies - robocat 2016-02-24 03:36
Does stack exchange / openID use CORS - RayLoveless 2016-06-24 20:01
FWIW I just tested a normal CORS withCredentials XHR and it worked on FF/Safari/Chrome...though I wouldn't doubt that facebook/google use more sophisticated scheme - rogerdpack 2017-04-14 19:11


20

There's no such thing as cross domain cookies. You could share a cookie between foo.example.com and bar.example.com but never between example.com and example2.com and that's for security reasons.

2010-07-27 09:15
by Darin Dimitrov
Hi thanks for the reply, can u please add more clarity on configuration part, how to create/configure domain and subdomain in j2ee environment?? - SundarJavaDeveloper 2010-07-27 11:29
This is a question that is more adapted to http://serverfault.com where you will get answers from experts in the domain - Darin Dimitrov 2010-07-27 11:36
Hi, I tried having two webapps WebApp.domain.com ==> here i add cookie in respose as follows: Cookie cookie = new Cookie("namedCookie","test"); cookie.setDomain(".domain.com"); response.addCookie(cookie);

WebApp1.domain.com==>Here i tried to access the cookie as follows, but cant able to access

Cookie[]cks = request.getCookies(); for(int i=0;i

Any idea on this - SundarJavaDeveloper 2010-07-28 07:01

often repeated but not true, see my answer below or here http://stackoverflow.com/questions/16186645/cross-domain-cookies-a-maybe-new-ide - Raphael Jeger 2013-04-24 12:31
Yes there is. You just need to use CORS - Anoyz 2015-04-30 16:40
How to share cookies between foo.example.com and bar.example.com - Jeff Tian 2016-08-18 07:43
Here is post with image tag , is that a better solution for asp mvc - stom 2016-12-13 09:36
"never" here is a bit misleading since you can access through CORS and "use 2 cookies" at the same time on the same page, as it were...which is almost like sharing them : - rogerdpack 2017-04-14 18:51


10

Do what Google is doing. Create a PHP file that sets the cookie on all 3 domains. Then on the domain where the theme is going to set, create a HTML file that would load the PHP file that sets cookie on the other 2 domains. Example:

<html>
   <head></head>
   <body>
      <p>Please wait.....</p>
      <img src="http://domain2.com/setcookie.php?theme=whateveryourthemehere" />
      <img src="http://domain3.com/setcookie.php?theme=whateveryourthemehere" />
   </body>
</html>

Then add an onload callback on body tag. The document will only load when the images completely load that is when cookies are set on the other 2 domains. Onload Callback :

<head>
   <script>
   function loadComplete(){
      window.location="http://domain1.com";//URL of domain1
   }
   </script>
</head>
<body onload="loadComplete()">

setcookie.php

We set the cookies on the other domains using a PHP file like this :

<?php
if(isset($_GET['theme'])){
   setcookie("theme", $_GET['theme'], time()+3600);
}
?>

Now cookies are set on the three domains.

2014-12-01 16:27
by Hossain Khademian
Good, then how can we read from another domain - Elby 2015-08-18 09:12
This doesn't work if the 'Block third party cookies' feature is enabled - Jens 2016-07-25 18:18


8

You cannot share cookies across domains. You can however allow all subdomains to have access. To allow all subdomains of example.com to have access, set the domain to .example.com.

It's not possible giving otherexample.com access to example.com's cookies though.

2010-07-27 09:16
by Daniel Egeberg
how come .google.com cookies show up when browsing to YouTube then - Hawken 2012-10-26 21:06
Google analytics tags. Those cookies come from google.com, not from youtube.com - Entendu 2013-09-12 22:58


7

You can attempt to push the cookie val to another domain using an image tag.

Your mileage may vary when trying to do this because some browsers require you to have a proper P3P Policy on the WebApp2 domain or the browser will reject the cookie.

If you look at plus.google.com p3p policy you will see that their policy is:

CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info."

that is the policy they use for their +1 buttons to these cross domain requests.

Another warning is that if you are on https make sure that the image tag is pointing to an https address also otherwise the cookies will not set.

2014-01-08 23:22
by Bryan Focht
Care to elaborate a little - frequent 2014-11-25 08:21


5

There's a decent overview of how Facebook does it here on nfriedly.com

There's also Browser Fingerprinting, which is not the same as a cookie, but serves a like purpose in that it helps you identify a user with a fair degree of certainty. There's a post here on Stack Overflow that references upon one method of fingerprinting

2012-02-21 16:13
by byZero


1

function GetOrder(status, filter) {
    var isValid = true; //isValidGuid(customerId);
    if (isValid) {
        var refundhtmlstr = '';
        //varsURL = ApiPath + '/api/Orders/Customer/' + customerId + '?status=' + status + '&filter=' + filter;
        varsURL = ApiPath + '/api/Orders/Customer?status=' + status + '&filter=' + filter;
        $.ajax({
            type: "GET",
            //url: ApiPath + '/api/Orders/Customer/' + customerId + '?status=' + status + '&filter=' + filter,
            url: ApiPath + '/api/Orders/Customer?status=' + status + '&filter=' + filter,
            dataType: "json",
            crossDomain: true,
            xhrFields: {
                withCredentials: true
            },
            success: function (data) {
                var htmlStr = '';
                if (data == null || data.Count === 0) {
                    htmlStr = '<div class="card"><div class="card-header">Bu kriterlere uygun sipariş bulunamadı.</div></div>';
                }
                else {
                    $('#ReturnPolicyBtnUrl').attr('href', data.ReturnPolicyBtnUrl);
                    var groupedData = data.OrderDto.sort(function (x, y) {
                        return new Date(y.OrderDate) - new Date(x.OrderDate);
                    });
                    groupedData = _.groupBy(data.OrderDto, function (d) { return toMonthStr(d.OrderDate) });
                    localStorage['orderData'] = JSON.stringify(data.OrderDto);

                    $.each(groupedData, function (key, val) {

                        var sortedData = groupedData[key].sort(function (x, y) {
                            return new Date(y.OrderDate) - new Date(x.OrderDate);
                        });
                        htmlStr += '<div class="card-header">' + key + '</div>';
                        $.each(sortedData, function (keyitem, valitem) {
                            //Date Convertions
                            if (valitem.StatusDesc != null) {
                                valitem.StatusDesc = valitem.StatusDesc;
                            }

                            var date = valitem.OrderDate;
                            date = date.substring(0, 10).split('-');
                            date = date[2] + '.' + date[1] + '.' + date[0];
                            htmlStr += '<div class="col-lg-12 col-md-12 col-xs-12 col-sm-12 card-item clearfix ">' +
                        //'<div class="card-item-head"><span class="order-head">Sipariş No: <a href="ViewOrderDetails.html?CustomerId=' + customerId + '&OrderNo=' + valitem.OrderNumber + '" >' + valitem.OrderNumber + '</a></span><span class="order-date">' + date + '</span></div>' +
                        '<div class="card-item-head"><span class="order-head">Sipariş No: <a href="ViewOrderDetails.html?OrderNo=' + valitem.OrderNumber + '" >' + valitem.OrderNumber + '</a></span><span class="order-date">' + date + '</span></div>' +
                        '<div class="card-item-head-desc">' + valitem.StatusDesc + '</div>' +
                        '<div class="card-item-body">' +
                            '<div class="slider responsive">';
                            var i = 0;
                            $.each(valitem.ItemList, function (keylineitem, vallineitem) {
                                var imageUrl = vallineitem.ProductImageUrl.replace('{size}', 200);
                                htmlStr += '<div><img src="' + imageUrl + '" alt="' + vallineitem.ProductName + '"><span class="img-desc">' + ProductNameStr(vallineitem.ProductName) + '</span></div>';
                                i++;
                            });
                            htmlStr += '</div>' +
                        '</div>' +
                    '</div>';
                        });
                    });

                    $.each(data.OrderDto, function (key, value) {
                        if (value.IsSAPMigrationflag === true) {
                            refundhtmlstr = '<div class="notify-reason"><span class="note"><B>Notification : </B> Geçmiş siparişleriniz yükleniyor.  Lütfen kısa bir süre sonra tekrar kontrol ediniz. Teşekkürler. </span></div>';
                        }
                    });
                }
                $('#orders').html(htmlStr);
                $("#notification").html(refundhtmlstr);
                ApplySlide();
            },
            error: function () {
                console.log("System Failure");
            }
        });
    }
}

Web.config

Include UI origin and set Allow Crentials to true

<httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="http://burada.com" />
        <add name="Access-Control-Allow-Headers" value="Content-Type" />
        <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
        <add name="Access-Control-Allow-Credentials" value="true" />
      </customHeaders>
    </httpProtocol>
2017-03-15 04:56
by user7712621


1

The smartest solution is to follow facebook's path on this. How does facebook know who you are when you visit any domain? It's actually very simple:

The Like button actually allows Facebook to track all visitors of the external site, no matter if they click it or not. Facebook can do that because they use an iframe to display the button. An iframe is something like an embedded browser window within a page. The difference between using an iframe and a simple image for the button is that the iframe contains a complete web page – from Facebook. There is not much going on on this page, except for the button and the information about how many people have liked the current page.

So when you see a like button on cnn.com, you are actually visiting a Facebook page at the same time. That allows Facebook to read a cookie on your computer, which it has created the last time you’ve logged in to Facebook.

A fundamental security rule in every browser is that only the website that has created a cookie can read it later on. And that is the advantage of the iframe: it allows Facebook to read your Facebook-cookie even when you are visiting a different website. That’s how they recognize you on cnn.com and display your friends there.

Source:

2018-06-07 18:32
by Morteza Shahriari Nia
I think an iframe would rarely classify as the best or the smartest way to do anything.. but it is the easiest - Orun 2018-07-25 15:57


0

One can use invisible iframes to get the cookies. Let's say there are two domains, a.com and b.com. For the index.html of domain a.com one can add (notice height=0 width=0):

<iframe height="0" id="iframe" src="http://b.com" width="0"></iframe>

That way your website will get b.com cookies assuming that http://b.com sets the cookies.

The next thing would be manipulating the site inside the iframe through JavaScript. The operations inside iframe may become a challenge if one doesn't own the second domain. But in case of having access to both domains referring the right web page at the src of iframe should give the cookies one would like to get.

2013-06-22 01:08
by Vadym Tyemirov
Just a warning: There are some serious issues with cookies in iframes on Safari. They apparently don't work cross domain - mvds 2013-12-04 11:23


-2

Read Cookie in Web Api

var cookie = actionContext.Request.Headers.GetCookies("newhbsslv1");


                    Logger.Log("Cookie  " + cookie, LoggerLevel.Info);
                    Logger.Log("Cookie count  " + cookie.Count, LoggerLevel.Info);

                    if (cookie != null && cookie.Count > 0)
                    {
                        Logger.Log("Befor For  " , LoggerLevel.Info);
                        foreach (var perCookie in cookie[0].Cookies)
                        {
                            Logger.Log("perCookie  " + perCookie, LoggerLevel.Info);

                            if (perCookie.Name == "newhbsslv1")
                            {
                                strToken = perCookie.Value;
                            }
                        }
                    }
2017-03-15 04:29
by user7712621
This does not handle the OP question of using on two different domain - Niklas Wulff 2018-10-09 09:29
Ads