Cross-Site Browser Cookie Setting

April 14th, 2007 by Ralf S. Engelschall

Let me share some experiences of this week. Perhaps it is of interest to someone who has solve a similar problem…

Suppose your organization runs three websites: www.example.com (your corporation), www.example.net (your community network) and www.example.org (your open source project). And under www.example.com/login.cgi you have the login page for your fellows. Once the customer is authenticated there, an authorization cookie containing an issued “certificate” should be set in the browser. This certificate in turn will be checked by all web pages under www.example.com, www.example.net and www.example.org to to determine whether the user is access granted or not.

Setting the authorization cookie for the domain “.example.com” from www.example.com/login.cgi is trivial, of course. You just send the cookie in the HTTP response and that’s it. But how do you set the same cookie also for the two sibling domains “.example.net” and “.example.org“? Because of the “same origin policy” enforced by all browsers, if you just return the two additional cookies also in the HTTP response of www.example.com/login.cgi they will be silently ignored by the browser. So what to do?

The the solution simply is that only a HTTP response from somewhere under www.example.net can set the cookie for “.example.net” and a HTTP response from somewhere under www.example.org can set the cookie for “.example.org“. But remains the important question: how can we automatically and unobtrusively load something from www.example.net and www.example.org in the response from www.example.com/login.cgi?

The key here is Cross-Site AJAX, as abstracted in my new jQuery plugin jquery.xsajax.js. Short recap: in JavaScript one dynamically generate a <script> DOM element with a type attribute set to text/javascript and a src attribute set to the URL of the foreign URL. But how is this of help here?

Well, in JavaScript we load on the displayed page of www.example.com/login.cgi the two foreign URLs www.example.net/reflector.cgi and www.example.org/reflector.cgi. Behind those two CGIs is nothing more than a simple “certificate” reflector, i.e., it expects the “certificate” in the query string and returns it as a cookie in the HTTP response header. For things like embedded images it doesn’t work, but for scripts all known browsers accept to set cookies!

The content of the two CGIs has to be of type text/javascript but can be just empty. Only the cookie in the HTTP response is what we are interested in. And because the cookie is now set for the “same origin” by the two reflector CGIs, we result in the “certificate” set in three cookies: one set directly with the HTTP response of www.example.com/login.cgi and two set indirectly with the HTTP response of www.example.net/reflector.cgi and ww.example.org/reflector.cgi through the asynchronously loaded scripts in the background. You got the trick? Voila!

PS: I have to confess that some small problem remains. For MSIE one small cruel trick is necessary: the reflector CGIs have to send a P3P header which contains some necessary bits (which particular one I intentionally leave as an exercise to the reader ;-) to force MSIE into also accepting the cookie

Leave a Reply