Ionică Bizău Ionică Bizău - 8 months ago 38
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 Source

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!