Ionică Bizău Ionică Bizău - 3 days ago 5
Javascript Question

Setting cross-site cookie on Safari

Having two websites:

A
and
B
. I want that the users that open website
B
to get redirected to another website (e.g.
http://example.com
) if they didn't visit the website
A
.

To do this I tried to set a cookie on website
B
(by just loading a page on website
A
, setting the cookie). When opening the website
B
I check for that cookie.

This works nice, except on Safari. Safari blocks setting the cookie on website
B
. I searched a lot and found out that Safari blocks the third-party cookies by default.

Another solution to the problem could be using the
Referer
header (when clicking a link on website
A
the referer will be sent to website
B
)–this fails for the users that don't want to get tracked and they disabled the referer header.

Is there a simple solution to this problem, without having a database where we store the ips or something similar?

Here is the code I currently have:

Website B index.php
:

<?php
$cookie_name = "visited_first_website";

if(isset($_COOKIE[$cookie_name]) ) {
echo "Visited";
} else {
$newURL = "https://example.com";
header('Location: '.$newURL);
}
?>


This is running on website A, using
B/set-cookie.js
.

window.addEventListener("DOMContentLoaded", function () {
var iframe = document.createElement("iframe");
//iframe.style.display = "none";

var scripts = document.getElementsByTagName("script");
var src = scripts[scripts.length - 1].src;
var websiteBAddress = src.match(new RegExp("https?://[^/]*"))[0];

iframe.setAttribute("src", websiteBAddress + "/js/embed.php");
document.body.appendChild(iframe);
});


The
embed.php
file looks like this:

<?php
$cookie_name = "visited_first_website";
$cookie_value = time();
setcookie($cookie_name, $cookie_value, time() + (86400 * 2), "/"); // 86400 = 1 day
header('Access-Control-Allow-Origin: *');
?>
<!DOCTYPE html>
<html>
<body>
</body>
</html>


So, what is the simplest workflow to solve this?

I tried to load an image tag too, but it didn't work:

<img src="B/js/embed.php">

Answer

This seems to be impossible to achive. Safari only accepts cookies from pages the user has navigated to him-/herself.

There was a rather hacky workaround back in 2010 (source), but the comments of 2013 and later state that it doesn't work anymore. I tried these things so far:

  • The original hack from 2010 (original and some variations).
  • Request the page via a post-form-element with the iFrame as target.
  • Load a script that initialises the session (sets a cookie) via...
    • img-tag
    • script-tag
    • AJAX-call via jquery

All without any success. I found out that even google maps and analyrics don't set any cookies in Safari.

It might be possible to circumvent the problem by loading a page via link, that sets a cookie and immediatly after that, redirects to the page with the embeded iFrame. I didn't test this method, though because it wouldn't satisfy our needs regarding usability and esthetics. Be cautious about using this when the page with the iFrame is reachable via deep link!

Comments