I'm having a problem to make my facebook app working on Safari.
The issue is related to the PHP session variables.
I am aware that Safari has a problem dealing with cross domain sessions (inside an iframe) and i found around 2 types of solutions:
- Setting the p3p header: i've tried many p3p header found around but no one of them worked [for example:
header('P3P: CP="NOI ADM DEV COM NAV OUR STP"');
].
- Sending a post to the iframe, using javascript. This creates interaction and sessions should work. But the fact is that i do not control the iframe container, as that is facebook.
Does anyone know an alternative solution?
Thanks!
EDIT: Confirmed, this workaround no longer works on Safari 5.1 on Mac. Discussed here: Safari 3rd party cookie iframe trick no longer working?
I don't know what's your use case but in our app we have a welcome screen with an 'Allow Access' button that opens the permissions dialog. When the user clicks 'Allow Access' I use that to open a new window that sets the session and closes immediately (this was proposed in the question linked above). After the user has allowed access you can just reload the page? In our case this is not needed since all communication to the server is with ajax.
I'm using the second solution and have no problem with it, here's my code (using jQuery):
/**
* Hack for Safari cross-domain cookies. See:
* http://anantgarg.com/2010/02/18/cross-domain-cookies-in-safari/
*/
$(document).ready( function() {
var isSafari = (/Safari/.test(navigator.userAgent));
if (isSafari) {
var iframe = $( "<iframe />" );
iframe.attr( "id", "cookieframe" );
iframe.attr( "name", "cookieframe" );
iframe.hide();
var form = $( "<form />" );
form.attr( "id", "cookieform" );
form.attr( "target", "cookieframe" );
form.attr( "enctype", "application/x-www-form-urlencoded" );
form.attr( "action", "startsession.php" );
form.attr( "method", "post" );
$("body").append( iframe );
$("body").append( form );
form.submit();
}
} );
In startsession.php I'm just starting the session:
<?php session_start();
I am late to this but it may well help someone else looking up this problem.
The only method I could make work was to detect safari from inside my iframe and redirect to another page momentarily where I could set my session cookie - then redirect back.
<?php
// sort out ie with the below header
header('P3P:CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"');
session_start();
$_SESSION = array();
// if Safari and no cookies have been set yet, take me to another page to set a session cookie
if (strpos($_SERVER['HTTP_USER_AGENT'], 'Safari') && !strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome')) {
if (count($_COOKIE) === 0) {
echo '<script>
top.location = "http://www.domain.com/setcookie.php";
</script>';
}
}
?>
Then from setcookie.php
<?php
//inside setcookie.php
header('P3P: CP="CAO PSA OUR"');
session_start();
$_SESSION = array();
echo
'<script>
top.location = "http://www.backtooriginaldomain.com";
</script>';
?>
its a bit lame but does work and doesn't interfere with the other browsers. The other method is to use a popup window although my safari had this blocked by default.
by far not the nicest solution but you don't need any extra Pages
put the Solution on the very first position on your page so you only see some white Flickering.
<?php
if (isset($_GET['safarifix'])) {
session_start();
echo '<script type="text/javascript">top.location = \''.$_GET['safarifix'].'\'</script>';
exit();
}
if (!isset($_COOKIE, $_COOKIE['PHPSESSID'])) {
header('P3P: CP="CAO PSA OUR"');
echo '<script type="text/javascript">top.location = document.URL + "?safarifix=" + encodeURIComponent(document.referrer)</script>';
exit();
}
?>
send your referring url to the page where you actually do your stuff.
nothing additional needed.
then reffer back to the page you have been in the first place.