Question

Safari on a Mac has a Block cookies set to From third parties and advertisers by default.

It stops the SharedObject from working if the embedded swf is from a different domain.

This problem isn't new: Safari 3rd party cookie iframe trick no longer working?

Has anyone found a solution (other then passing the Session ID through GET/POST params in each request)?

NOTE: I have no access to the site, which is embedding the swf, so there is no way to alter that HTML or to put any JavaScript, etc.

Was it helpful?

Solution

function setCookie(){
   if ( navigator.userAgent.indexOf('Safari') != -1 &&
        navigator.userAgent.indexOf('Chrome') == -1 ){
      window.open('safari.php','','width=200,height=100' );
   }
}

// then we set the cookie in safari.php

Source: http://www.reizbombardement.de/archives/safari-5-1-4-enforces-cookie-policy

//UPDATE 23 July 2013

This crappy way of fixing this issue used to work until Safari 6.

Please see @Fabio Antunes and @ncubica comments below.

//UPDATE 23 July 2013 by Fabio Antunes

Here's my code

On the landing page we'll have a brief description about the app and a button saying something like "enter". I'm using jquery to simplify this process, creating a listener for the click event, I'll just put the javascript code, since I'm assuming you already have the rest of the html code for the landing page:

$(document).on("click", "#bt-landing", function(){
var left = (screen.width/2)-(500/2);
            var top = (screen.height/2)-(250/2);
            window.open('URL_FOR_THE_PHP_THAT_WILL_CREATE_THE_SESSION', '_blank', 'width=500,height=250,toolbar=0,location=0,menubar=0, top='+top+', left='+left);
});

This you'll open a small window, with 500 by 250 px, centered on your screen.

The code I have for the small window is this:

<?php setcookie("safari_cookie", "1");?>
    <html>
        <head>
            <meta charset="utf-8">
            <title>THE NAME OF YOUR APP OR SOMETHING THAT THE USER WE'LL READ AND ASSUME THAT THIS SMALL WINDOW IS RELIABLE</title>
        </head>
        <body>
        <script type="text/javascript">
        $(document).ready(function(){
           setTimeout(function(){window.close()},1000);
        })
        </script>
        </body>
    </html

OTHER TIPS

Safari does still block cookies from domains which it has not visited in the top window.

To workaround this, we count($_COOKIES) in PHP and direct the browser to a page on our domain whose job it is to simply send the browser back to where it came from. It's a dirty trick which means some users will unnecessarily get moved away and then back, but then, the web is full of dirty tricks.

If you cannot set top.location.href to a page on the domain which needs to set cookies, or you cannot alter a page on said domain, then I can confidently say you'll need to use URL-based sessions.

However, an alternative option (which still requires being able to create a page on the domain) is to request that the user clicks on your SWF, you can then trigger window.open and have the URL point to the page you created. All it needs to do is load successfully, then the user (or even JS on the popup page itself) can close the popup. You may then set cookies.


I develop Facebook apps, which live inside iframes, which suffer this problem. Every single app has to be shipped with this fix.

I can say from very recent experience that this is not a problem with Safari on a Mac, nor have I ever experienced it as a problem.

You mentioned the setting is blocking cookies from 3rd parties: SharedObject storage is never from a third party, it's from the site you're visiting (the 1st party?). So I don't think that will ever be an issue.

Using the Flash Player settings panel, the user can disable the SharedObject (or limit the amount of storage space). So in general, your app should handle the case where the SharedObject is not available.

However, I think most users are not aware of the SharedObject and that they can disable it.

You may need to use a cross-domain policy file for the swf to work correctly.

http://kb2.adobe.com/cps/142/tn_14213.html

I've solved in this way, but it's better to use HTML5 localstorage and make webservices restful because holding session variables in server2 make your application not well scalable. Here the code i've used to solve the 3rd party cookie problem. Basically guests of server1 goes first to server2 in order to take "the coin :D" and suddenly he come back to server1. In this way session variables of server2 are avaliable in all navigation. www.yourserver.com/index.html page

<script src="js/jquery.cookie.js" type="text/javascript"></script>
<script src="js/mobile-detect.js" type="text/javascript"></script>
<script>
var md = new MobileDetect(window.navigator.userAgent);
if (md.userAgent()=='Safari') {
    var firstsafariuser = $.cookie('safari-user');
    if (firstsafariuser != 'true') {
        $.cookie('safari-user', true);
        location.href='http://www.yourserver2.com/coin.php?frompage='
        +location.href.replace(location.hash,"")+'&hashtags='+location.hash.substr(1);
    }
}
</script>

www.yourserver2.com/coin.php

<?php
session_start(); 
if (isset($_GET["frompage"])&&$_GET["frompage"]!=null){
    $url=$_GET["frompage"];
} else {
    $url='http://www.yourserver.com';
}
if (isset($_GET["hashtags"])&&$_GET["hashtags"]!=null){
    $hash='#'.$_GET["hashtags"];
} else {
    $hash='';
}
header('Location:'.$url.$hash);
?>

P.S. window.open are seen like a kind of popup so you might have problem with ad-blockers or browser settings.

Just to add a cleaner way without setTimeout and or jquery for the safari.xxx page. Works fine with the latest ios (8.1.2), I know for 8.1.0 there was a bug where the window/tab wouldn't close.

Here is the code:

<%
request.getSession(true); //or anyway to set the cookie depending on your language (jsp here)
%>

<script type="text/javascript">
    window.addEventListener("load", window.close);
</script>

The popup is not an issue in my case since it is initiated by a click from the user.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top