141 votes

L'astuce des iframes de cookies tiers de Safari ne fonctionne plus ?

Voici donc la énième revanche de la question " comment faire fonctionner les cookies tiers dans Safari ", mais je la pose à nouveau car je pense que les règles du jeu ont changé, peut-être après février 2012. L'une des astuces standard pour obtenir des cookies tiers dans Safari était la suivante : utiliser du javascript pour POST vers une iframe cachée. Cela permettait de faire croire à Safari que l'utilisateur avait interagi avec le contenu tiers et donc d'autoriser la création de cookies.

I pensez à Cette faille a été comblée à la suite du léger scandale où il a été révélé que Google utilisait cette astuce avec ses publicités. Au moins, en utilisant cette astuce, j'ai été complètement incapable de définir des cookies dans Safari. J'ai trouvé quelques publications aléatoires sur Internet qui affirmaient qu'Apple travaillait à la suppression de cette faille, mais je n'ai trouvé aucune information officielle.

En guise de solution de repli, j'ai même essayé de redessiner le cadre principal de la tierce partie de manière à ce que vous deviez cliquer sur un bouton avant que le contenu ne se charge, mais même ce niveau d'interaction directe n'a pas suffi à faire fondre le cœur froid de Safari.

Quelqu'un sait-il avec certitude si Safari a effectivement comblé cette lacune ? Si oui, existe-t-il d'autres solutions de contournement (autres que l'inclusion manuelle d'un identifiant de session dans chaque requête) ?

23 votes

L'utilisation d'un iframe tiers qui nécessite des cookies est certainement no par définition une attaque de sécurité ! Nous gérons une boutique en ligne qui est utilisée dans une iframe sur une multitude de domaines différents, et nous avons toutes sortes de problèmes avec Safari ces derniers temps, donc je suis également très intéressé par la réponse à cette question (légitime).

14 votes

Presque tous ceux qui créent des applications Facebook ont ce problème avec Safari. Les applications Facebook fonctionnent dans une iframe et, par définition, elles proviennent toutes de tiers. C'est pourquoi la prise en charge de Safari pour les applications Facebook est un peu aléatoire : vous ne pouvez pas utiliser de cookies.

0 votes

Je n'arrive pas à reproduire ce problème sur safari 5.1.7. Il accepte le cookie de mon application facebook iframe avec le paramètre par défaut "pas de cookies tiers". Cependant, Chrome 19.0.1084.46, avec le même paramètre, bloque le cookie.

50voto

Whiteagle Points 974

Je voulais juste laisser ici une solution simple et fonctionnelle qui ne nécessite pas d'interaction avec l'utilisateur .

Comme je l'ai déclaré dans un poste que j'ai fait :

En gros, tout ce que vous devez faire, c'est charger votre page sur top.location, créer la session et la rediriger vers facebook.

Ajoutez ce code en haut de votre index.php et mettre $page_url à l'onglet final/URL de votre application et vous verrez que votre application fonctionnera sans aucun problème.

<?php
    // START SAFARI SESSION FIX
    session_start();
    $page_url = "http://www.facebook.com/pages/.../...?sk=app_...";
    if (isset($_GET["start_session"]))
        die(header("Location:" . $page_url));

    if (!isset($_GET["sid"]))
        die(header("Location:?sid=" . session_id()));
    $sid = session_id();
    if (empty($sid) || $_GET["sid"] != $sid):
?>
   <script>
        top.window.location="?start_session=true";
    </script>
<?php
    endif;
    // END SAFARI SESSION FIX
?>

Note : Ce texte a été conçu pour Facebook, mais il pourrait fonctionner dans d'autres situations similaires.


Edit 20-Dec-2012 - Maintien de la demande signée :

Le code ci-dessus ne maintient pas les post-données des demandes, et vous perdriez la signed_request, si votre application repose sur des demandes signées, n'hésitez pas à essayer le code suivant :

Note : Cette version est encore en cours de test et peut être moins stable que la première version. Utilisez à vos risques et périls / Vos commentaires sont appréciés.

(Merci à CBroe pour m'avoir orienté dans la bonne direction ici permettant d'améliorer la solution)

// Start Session Fix
session_start();
$page_url = "http://www.facebook.com/pages/.../...?sk=app_...";
if (isset($_GET["start_session"]))
    die(header("Location:" . $page_url));
$sid = session_id();
if (!isset($_GET["sid"]))
{
    if(isset($_POST["signed_request"]))
       $_SESSION["signed_request"] = $_POST["signed_request"];
    die(header("Location:?sid=" . $sid));
}
if (empty($sid) || $_GET["sid"] != $sid)
    die('<script>top.window.location="?start_session=true";</script>');
// End Session Fix

0 votes

Merci, cela fonctionne comme un charme et c'est si facile à mettre en œuvre dans les applications existantes :-)

0 votes

Donc celui-ci fonctionne essentiellement avec quelques redirections, non ?

0 votes

Exactement @AaronGibralter, il fait deux redirections lorsque cela est nécessaire. L'idée principale est d'éviter de demander un clic à l'utilisateur.

35voto

drewrichards Points 506

Vous avez dit que vous étiez prêt à ce que vos utilisateurs cliquent sur un bouton avant que le contenu ne se charge. Ma solution consistait à faire en sorte qu'un bouton ouvre une nouvelle fenêtre du navigateur. Cette fenêtre établit un cookie pour mon domaine, rafraîchit l'ouvreur et se ferme ensuite.

Donc votre principal script pourrait ressembler à :

<?php if(count($_COOKIE) > 0): ?>
<!--Main Content Stuff-->
<?php else: ?>
<a href="http://stackoverflow.com/safari_cookie_fix.php" target="_blank">Click here to load content</a>
<?php endif ?>

Alors safari_cookie_fix.php ressemble à ça :

<?php
setcookie("safari_test", "1");
?>
<html>
    <head>
        <title>Safari Fix</title>
        <script type="text/javascript" src="/libraries/prototype.min.js"></script>
    </head>
    <body>
    <script type="text/javascript">
    document.observe('dom:loaded', function(){
        window.opener.location.reload();
        window.close();
    })
    </script>
    This window should close automatically
    </body>
</html>

0 votes

Je pensais à quelque chose comme ça. Cela fonctionne parfaitement. Je le charge en même temps que le dialogue d'autorisation. Merci !

0 votes

Il semblerait que cette solution contourne également les paramètres de Safari, et qu'une fois qu'elle sera connue de tous, elle sera supprimée tout comme les autres "solutions". Je suis à la recherche d'une solution totalement différente, car il devient évident que les cookies tiers sont désormais le diable, même lorsqu'ils sont utilisés de manière appropriée.

1 votes

Cette solution a fonctionné pour moi, cependant, la popup est-elle nécessaire ? Pourriez-vous rediriger votre iframe vers la page safari, placer le cookie, puis rediriger vers le jeu avec des en-têtes de redirection ? Ou bien avez-vous besoin de la fenêtre contextuelle pour que l'utilisateur ait une forme de contact direct avec le serveur ?

15voto

vwoelm Points 226

J'ai trompé Safari avec un .htaccess :

#http://www.w3.org/P3P/validator.html
<IfModule mod_headers.c>
Header set P3P "policyref=\"/w3c/p3p.xml\", CP=\"NOI DSP COR NID CUR ADM DEV OUR BUS\""
Header set Set-Cookie "test_cookie=1"
</IfModule>

Et ça a cessé de fonctionner pour moi aussi. Toutes mes applications perdent la session dans Safari et sont redirigées hors de Facebook. Comme je suis pressé de réparer ces applications, je suis actuellement à la recherche d'une solution. Je vous tiendrai au courant.

Edit (2012-04-06) : Apparemment, Apple a "corrigé" le problème avec la version 5.1.4. Je suis sûr que c'est la réaction au Google-truc : "Un problème existait dans l'application de sa politique de cookies. Les sites web tiers pouvaient définir des cookies si la préférence "Bloquer les cookies" dans Safari était définie sur le paramètre par défaut de "De tiers et d'annonceurs". http://support.apple.com/kb/HT5190

1 votes

Apparemment, Apple l'a "corrigé" avec la version 5.1.4. Je suis sûr que c'est la réaction à l'affaire Google : "Un problème existait dans l'application de sa politique en matière de cookies. Les sites Web tiers pouvaient définir des cookies si la préférence "Bloquer les cookies" dans Safari était réglée sur le paramètre par défaut "De tiers et d'annonceurs". support.apple.com/kb/HT5190

1 votes

Je pense donc que ce commentaire de vwoelm est le plus proche de la réponse que je cherchais. Tout d'abord, je voulais avoir la confirmation qu'Apple avait définitivement comblé la faille et la référence à l'article du support Apple est exactement cela. La deuxième partie de ma question reste cependant d'actualité. Quelles sont les options de contournement possibles ? Il est clair que nous pouvons coder les ID de session en tant que paramètres GET/POST, mais quelles sont les autres options ? Le stockage local fonctionne-t-il dans ce contexte ? Les cookies Flash ?

0 votes

@vwoelm : c'est effectivement la réponse que je cherchais (mais n'espérais pas). Si vous mettez cela dans une réponse plutôt que dans un commentaire, je vous attribuerai la prime.

14voto

joost Points 861

Dans votre contrôleur Ruby on Rails, vous pouvez utiliser :

private

before_filter :safari_cookie_fix

def safari_cookie_fix
  user_agent = UserAgent.parse(request.user_agent) # Uses useragent gem!
  if user_agent.browser == 'Safari' # we apply the fix..
    return if session[:safari_cookie_fixed] # it is already fixed.. continue
    if params[:safari_cookie_fix].present? # we should be top window and able to set cookies.. so fix the issue :)
      session[:safari_cookie_fixed] = true
      redirect_to params[:return_to]
    else
      # Redirect the top frame to your server..
      render :text => "<script>alert('start redirect');top.window.location='?safari_cookie_fix=true&return_to=#{set_your_return_url}';</script>"
    end
  end
end

0 votes

Y a-t-il un problème similaire avec les sessions dans safari ?

0 votes

Vous pouvez remplacer set_your_return_url par request.env['HTTP_REFERER'] puisque nous sommes dans une iframe :-D

0 votes

J'ai essayé cette solution, et le seul problème est que je ne peux pas retourner à l'url de l'iframe parent. Existe-t-il une méthode dans Rails pour obtenir l'url de l'iframe parent ? Merci.

9voto

Sascha Galley Points 7516

J'ai eu le même problème et aujourd'hui j'ai trouvé une solution qui fonctionne bien pour moi. Si l'agent utilisateur contient Safari et qu'aucun cookie n'est défini, je redirige l'utilisateur vers la boîte de dialogue OAuth :

<?php if ( ! count($_COOKIE) > 0 && strpos($_SERVER['HTTP_USER_AGENT'], 'Safari')) { ?>
<script type="text/javascript">
    window.top.location.href = 'https://www.facebook.com/dialog/oauth/?client_id=APP_ID&redirect_uri=MY_TAB_URL&scope=SCOPE';
</script>
<?php } ?>

Après l'authentification et la demande d'autorisations, la boîte de dialogue OAuth redirige vers mon URI dans l'emplacement supérieur. Il est donc possible d'installer des cookies. Pour toutes nos applications de canevas et d'onglet de page, j'ai déjà inclus le script suivant :

<script type="text/javascript">
    if (top.location.href==location.href) top.location.href = 'MY_TAB_URL';
</script>

Ainsi, l'utilisateur sera à nouveau redirigé vers l'onglet de la page Facebook avec une cookie valide déjà installé et la demande signée est à nouveau affichée.

0 votes

Bon travail sur ce point. J'ai mis à jour la vérification de l'agent utilisateur pour m'assurer que Chrome n'était pas également dans l'agent utilisateur puisque Chrome a également Safari dans la chaîne de l'agent utilisateur. La redirection vers la page de votre domaine, la définition des cookies nécessaires/le démarrage de la session, puis la redirection vers votre application sur apps.facebook.com ont fonctionné à merveille. Cela semble idiot, mais cela fonctionne bien. Merci Sascha pour l'astuce !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X