How does Facebook set cross-domain cookies for iFrames on canvas pages?
Asked Answered
C

1

85

I was browsing Facebook's documentation reading about canvas applications and I came across an example application: http://developers.facebook.com/docs/samples/canvas. As I read through their example, however, I got very confused about their use of cookies in the iframe application.

A little backstory...

I had already played around with using iframes for embeddable widgets (unrelated to Facebook) and I found out a few browsers (Chrome, Safari, etc.) have strict cookie policies and don't allow cross-domain cookies set in iframes (Firefox, on the other hand, allows iframes to set cross-domain cookies in iframes). For example, if foo.com has an iframe with src="http://bar.com/widget" the iframe widget will not be able to set any cookies for bar.com and therefore will have trouble persisting state within the iframe: bar.com will interpret every request (including ajax requests) from the widget as a fresh request without an established session. I struggled, and found a way around this by using JSONP and javascript to set cookies for foo.com instead...

... and so?

Well, I was looking at the example canvas iframe Facebook application and I noticed that their application (hosted on runwithfriends.appspot.com) is able to set a cookie, u, with the current user's id along with a few other parameters for the runwithfriends.appspot.com domain. It sends this cookie with every request... and it works in both Chrome and Firefox! WTF? How does Facebook get around the cross-domain cookie restrictions on Chrome?

(I already know the answer now, but I thought this might be helpful for anyone struggling to figure out the same thing -- I'll post the answer below.)

Cupel answered 15/1, 2011 at 20:19 Comment(1)
Update: the latest versions of some browsers (Safari v6.x+ on OS X, Safari on iOS 6+, and I assume Chrome and FF soon) do not allow for setting of cross-domain cookies anymore, even on post-to-iframe requests.Cupel
C
89

So the iFrame isn't actually setting the u cookie for the runwithfriends.appspot.com domain. What Facebook does is it creates a form, <form action="runwithfriends.appspot.com/..." target="name_of_iframe" method="POST"> and uses javascript to submit the form on page load. Since the form's target is the iframe, it doesn't reload the page... it just loads the iframe with the POST's response. Apparently even Chrome and other browsers with strict cookie policies set cookies for cross domain requests if they are POST requests...

Cupel answered 15/1, 2011 at 21:0 Comment(22)
I created a proof of concept sinatra app to demonstrate how this works: github.com/agibralter/iframe-widget-testCupel
Hey Aaron, Do you have a pure Javascript version of this code/demo please?Leadership
@LShetty -- sorry, I'm not sure I understand what you mean... pure Javascript? The Ruby portion of the demo acts as the web server... do you mean you want to see the demo written in Node.js?Cupel
I has same hard time LShetty had. I don't get what your code is for. what about a php solution, i don't get form your code where's the beef..Consignee
@Seth I haven't checked in a while, but the latest version of Safari (v6.0/iOS6 and I assume soon Chrome and FF) don't allow this trick anymore: the cookies don't get set on post-to-iframe requests. I'd have to look into how Facebook is handling this for new browsers. For now, localStorage seems like a good alternative method.Cupel
Here is a little post about it nfriedly.com/techblog/2010/08/…Towland
Let me just tell you, that if you have "disable third party cookies" that workaround iframe thing will stop working i believe.Caliph
A lot has changed in the last 5 years... :)Cupel
today, with Chrome (Chromium 51 on linux): with cookies set with domain B, then try to read from an iframe (domain B) within parent page (domain A) : impossible*. localStorage() with script in iframe (domain B) : impossible*, you have an "acced denied" error message. * means impossible except if user doesn't uncheck "Block third party..." in settings/content. if you uncheck both work but don't count on users to uncheck...Exchangeable
So is there a way to set 3rd party cookie today, when it is set in browser to block 3rd party cookie? Or is can someone verify that it is not possible today in any way?Duhon
@Duhon It is not possible, as that is exactly what the relevant browser setting is for. If it was possible, that would be a security bug in the affected browsers and would certainly be fixed soon after.Donne
@Donne it certainly was possible as I used that loophole for an embeddable polling application from 2009-2013, and it worked in all browsers with default settings. It was not treated as a security bug for some reason as it was left open for a very, very long time.Cupel
@AaronGibralter I definitely don’t doubt that. But browsers’ security policies do change, and 5-9 years is a long time in the development of web browsers. Today, if you opt to block third-party cookies, that usually works reliably.Donne
@Donne true true.Cupel
lol, these comments actually do explain a lot about the evolution of web browser cookies over time ...Sonya
I'm trying to see how facebook cookies httponly are been set today but when debugging the network request I can see some request but there is not set-cookie on the headers, any idea how this is happening? @AaronGibralterMonotype
Honestly, I haven't looked at how this works with modern browsers...Cupel
Third-party cookies will be phased out totally in the next 1.5 - 2 years, at least in Chrome, Safari, and most probably Firefox. They were already phased out on the newest versions of Safari and from the incognito mode of Chrome. Users can also turn them off. The current workaround for the browsers where it still works is to check if cookies are saveable from an iframe and if not - shortly open iframe domain in main window (redirect to url and back by JS). Then with proper parameter SameSite (for example SameSite=None) in the cookie they work, but only in those browsers.Gertrudis
Sounds like me trying to figure out how to pass microsoft's b2c session cookie across subdomains via iframe is a solution that's very limited now.Misogyny
I have recently posted a related answer for anyone who would be interested in having a look.Royall
Can you please explain your answer better?! I really don't understand. I have a site a that contains literally no script tags and only one iframe which points to a facebook like button. When I load site a and check the value of document.cookie it has a cookie called datr= which facebook is setting on my domain not their own. I checked my HTTP headers just to be sure and there is no set-cookie header coming from my own site and no script tags anywhere on the page, the cookie must be coming from the iframe. Please explain to me how facebook can set a cookie on a different domain?!!Licastro
I'm just going to say that over 13 years have passed since I wrote and answered this question, and it's overwhelmingly likely that a lot of things with browser security have changed... I'm not too sure what the state of affairs is in modern Chrome, etc.Cupel

© 2022 - 2024 — McMap. All rights reserved.