I have two webapps WebApp1 and WebApp2 in two different domains.
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
This question is related to
cookies
web-applications
cross-domain
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.
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:
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
I've created an NPM module, which allows you to share locally-stored data across domains: https://www.npmjs.com/package/cookie-toss
By using an iframe hosted on Domain A, you can store all of your user data on Domain A, and reference that data by posting requests to the Domain A iframe.
Thus, Domains B, C, etc. can inject the iframe and post requests to it to store and access the desired data. Domain A becomes the hub for all shared data.
With a domain whitelist inside of Domain A, you can ensure only your dependent sites can access the data on Domain A.
The trick is to have the code inside of the iframe on Domain A which is able to recognize which data is being requested. The README in the above NPM module goes more in depth into the procedure.
Hope this helps!
As other people say, you cannot share cookies, but you could do something like this:
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...
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.
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.
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 siparis bulunamadi.</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">Siparis 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">Siparis 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çmis siparisleriniz yükleniyor. Lütfen kisa bir süre sonra tekrar kontrol ediniz. Tesekkü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>
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.
Since it is difficult to do 3rd party cookies and also some browsers won't allow that.
You can try storing them in HTML5 local storage and then sending them with every request from your front end app.
Cross-site cookies are allowed if:
Set-Cookie
response header includes SameSite=None; Secure
as seen here and hereLet's clarify a "domain" vs a "site"; I always find a quick reminder of "anatomy of a URL" helps me. In this URL https://example.com:8888/examples/index.html
, remember these main parts (got from this paper):
https://
example.com
8888
/examples/index.html
.Notice the difference between "path" and "site" for Cookie purposes. "path" is not security-related; "site" is security-related:
path
Servers can set a Path
attribute in the Set-Cookie
, but it doesn't seem security related:
Note that
path
was intended for performance, not security. Web pages having the same origin still can access cookie viadocument.cookie
even though the paths are mismatched.
site
The SameSite attribute, according to web.dev article, can restrict or allow cross-site cookies; but what is a "site"?
It's helpful to understand exactly what 'site' means here. The site is the combination of the domain suffix and the part of the domain just before it. For example, the
www.web.dev
domain is part of theweb.dev
site.
This means what's to the left of web.dev
is a subdomain; yep, www
is the subdomain (but the subdomain is a part of the host; see the BONUS reply in this answer)
In this URL https://www.example.com:8888/examples/index.html
, remember these parts:
https://
example.com
8888
www.example.com
example.com
www
/examples/index.html
Useful links:
(Be careful; I was testing my feature in Chrome Incognito tab; according to my chrome://settings/cookies
; my settings were "Block third party cookies in Incognito", so I can't test Cross-site cookies in Incognito.)
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
}
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;
}
}
}
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
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.
Source: Stackoverflow.com