Setting third-party cookies in IE and Safari

As web developers, we like to avoid situations in which you need to solve problems like “setting third-party cookies” in any web application. But in some situations you need to set a cookie from an iframe in a page on a different domain. This works fine for Chrome/FF but you may be here because you ran into issues setting the cookie in IE and Safari. It’s ok, I won’t tell anyone. But keep in mind “Going incognito doesn’t hide your browsing from your employer, your internet service provider, or the websites you visit.” :D.

It’s rather easy to work around this and its not *that* hacky…but you do need different solutions for IE and Safari.

IE

For IE, the fix is simpler (really!). All you need to do is set headers in the server side file that sets the cookies (the server side file in the iframe). In PHP, it looks something like this:


header('P3P:CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"');
//Setting the P3P:CP header to the string shown in whatever server-side file is setting the cookies will allow IE to set third-party cookies.

Safari

For Safari, there is no real workaround. You will have to open a window via JS on the embedded (iframe’d) page, then set the cookie, (as a ‘direct visitor’ to the embedded page’s domain, safari will let you set cookie since its not third party anymore), then close the window and proceed with using your (now working) cookies in the frame.

Method I

For me, I had a login process working for all other browsers (after adding the headers for IE). So, on login success, I behaved normally for all browsers except Safari. For Safari, I’d make a second call to my backend with a code that was generated on successful login. this code mapped to the user data needed in the cookie. the cookie is set in the opened window, the frame polls the cookie value until its set then closes the window and redirects frame to post-login. The JS looks something like this:


/*i'm using a code set upon successful login and calling this on login success for safari only*/
w = window.open("http://Your_SITE/set_cookies_function?code="+data.safari_code);
self.focus();
interval = setInterval(function(){
	if(getCookie("cookie1") == "" || getCookie("cookie2") == ""){
		//not set yet, continue
		//alert("not yet");
	} else {
		//alert("now");
		clearInterval(interval);
		w.close();
		window.location.href = post_login;
	}
}, 1000);

NOTE: PLEASE do not use user agent string for browser detection, ESPECIALLY for Safari. Far better to use feature detection. This one is pretty safe:


var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;

Method II

There is another way to look at the problem completely but it won’t work for all cases (and it wasn’t possible in my case, but would be my preferred method to the above).

You can simply redirect the parent frame to a page in the embedded domain upon success in the embedded login, then set cookies, then redirect to another page in the parent frame that embeds the first post-login page. In my case I had to keep the same parent frame page for pre-and-post login so this wasn’t possible. This is much simpler and I don’t think I need any examples, but if there are any comments asking for them I will update the post.

I am happy to answer questions on your specific implementations and situations with this issue.

Sreenath

About Sreenath

I am an entrepreneur and software developer. I have programmed as a hobby since the age of 8.

Leave a Reply

Your email address will not be published. Required fields are marked *