37 votes

Comment gérer correctement la session et le jeton d'accès avec Facebook PHP SDK 3.0?

Dans le SDK PHP 3.0, il n'y a pas de getSession() ou de gestion de session disponible en dehors de l'api Facebook. Il y a quelques jours, les développeurs de Facebook ont également mis à jour le sdk JavaScript, selon ce billet de blog et ce rapport de bug.

Au cours des derniers jours, un changement a été introduit dans le SDK JS hébergé qui a cassé toute compatibilité entre lui et le SDK PHP actuel (2.x and 3.x). Les développeurs qui utilisent à la fois le SDK JS et PHP sur leurs sites web risquent de rencontrer des échecs de l'API côté serveur.

Cependant, je ne sais pas si cela affecte vraiment mon problème. Comme dans la réponse à cette question, j'obtiens le jeton d'accès du dialogue OAuth avec PHP et enregistre le nouveau jeton d'accès en session.

Solution de contournement actuelle

Le code suivant montre comment je gère ces sessions. $_REQUEST['session'] est le contenu de la réponse du dialogue OAuth.

if(isset($_REQUEST['session'])) {

    $response = json_decode(stripslashes($_REQUEST['session']), true);

    if(isset($response['access_token'])) {
        $this->api->setAccessToken($response['access_token']);
        $_SESSION['access_token'] = $this->api->getAccessToken();
    }

}
elseif(isset($_SESSION['access_token']) && ! isset($_REQUEST['signed_request'])) 
    $this->api->setAccessToken($_SESSION['access_token']);
elseif(isset($_REQUEST['signed_request'])) {
    Session::invalidate('fbuser');
    $_SESSION['access_token'] = '';
}

Voici comment je gère les données utilisateur :

try {
    $this->user = Session::getVar('fbuser');
    if ($this->user === false || is_null($this->user)) {
        $facebookUser = $this->api->api('me?fields=id,name,first_name,last_name');
        $this->user = new FBUserModel(array('fbId' => $facebookUser['fbId'], ...));
        Session::setVar('fbuser', $this->user);
    }
}

Le Problème

Tout semble correct lors des tests. Seule une fois une erreur s'est produite : la première fois après que l'autorisation ait été définie. Maintenant, depuis que l'application est en ligne, il semble que l'erreur se produise en moyenne avec chaque deuxième utilisateur dans

$facebookUser = $this->api->api('me?fields=id,name,first_name,last_name');

avec l'erreur :

Un jeton d'accès actif doit être utilisé pour interroger les informations sur l'utilisateur actuel.

Question

Pourquoi cela se produit-il ? C'est très difficile à déboguer car l'erreur semble se produire uniquement lorsque qu'un utilisateur entre dans l'application pour la première fois, après l'authentification de l'application et que le jeton d'accès a changé. Et même cela ne se produit pas à chaque fois. Comment devrais-je gérer la session et le jeton d'accès correctement avec le nouveau SDK PHP ?

Toute aide serait grandement appréciée !

Édition

J'ai découvert qu'il y a des problèmes IE avec les cookies/sessions à l'intérieur d'un iFrame. Comme vu dans ce billet de blog. Avec ce conseil et quelques recherches supplémentaires, j'ai ajouté les lignes suivantes dans mon bootstrap :

ini_set('session.use_trans_sid', 1);
header('P3P:CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"');

Maintenant c'est bien mieux, mais les informations de près de 2 utilisateurs sur 50 se perdent entre les étapes de la page de destination (authentification) -> formulaire -> et enregistrement. Il y a donc encore quelque chose que j'ai raté.

Édition 2

J'ai modifié ma gestion des utilisateurs de

if ($this->user === false || is_null($this->user)) {
    // obtenir les données de l'utilisateur
}

à

if ((is_object($this->user) && $this->user->fbId == '') || $this->user === false || is_null($this->user)) {
    // obtenir les données de l'utilisateur
}

Cela semble aider un peu. Je pense que le problème principal se situe quelque part dans ma session.

De plus, j'ai ajouté un bloc try/catch pour voir si une exception Facebook OAuthException est lancée quelque part dans mon application. Si tel est le cas, je redirige vers la top location de la Page et du Tab de Facebook pour obtenir un nouveau signed request. Bien que cela puisse aider à résoudre ce problème, je veux éviter que mon application ne doive rediriger l'utilisateur.

Édition 3

Après quelques jours d'intense débogage et de journalisation, j'ai découvert que le $_REQUEST['session'] provenant de la méthode FB.ui permissions.request est parfois vide.

Voici comment je le gère :

Voici les choses que j'inclus toujours :

FB.provide("UIServer.Methods", {'permissions.request': {size : {width: 575, height: 300}, url: 'connect/uiserver.php', transform : FB.UIServer.genericTransform}});

Et cette fonction est appelée lors de la soumission du formulaire. Cela a toujours fonctionné pour moi, mais pour une raison quelconque, il envoie toujours le formulaire même si session == ''.

function getPermission(form) {

    session = $('#' + $(form).attr('id') + ' input[name="session"]');

    if($(session).val() != '') {
        form.submit();
        return;
    }

    FB.ui({method: "permissions.request", "perms": 'user_photos'}, function callback(info){
        if(info.status=='connected' && info.session !== null) {
            $(session).val(JSON.stringify(info.session));
            form.submit();
        }
    });
    return;
}

10voto

Hamza Points 506

Je suis maintenant en train d'utiliser PHP SDK 3.x sans aucun problème.

Naitik, l'auteur de la classe, a supprimé la fonction getSession(), et maintenant si vous voulez savoir si l'utilisateur est authentifié ou non, utilisez getUser().

Pour le jeton d'accès, c'est très simple, utilisez cette fonction getAccessToken(), et vous obtiendrez le jeton d'accès pour effectuer des appels à l'API Graph ou Rest.

$user = $facebook->getUser();

if ($user) {
//Utilisateur connecté
}
else {
//Utilisateur non connecté
}

//POUR OBTENIR LE JETON D'ACCÈS
$access_token = $facebook->getAccessToken();

//FAIRE UN APPEL À L'API AVEC CELA
$user_info = $facebook->api('me?fields=id,name,first_name,last_name&access_token='.$access_token);

5voto

Sascha Galley Points 7516

Ma solution

Eh bien, étant donné que tout ce que j'ai fait était juste une solution temporaire en attendant la sortie du nouveau SDK JS, il semble n'y avoir aucune meilleure pratique. Définir session.use_trans_sid sur 1 et ajouter l'en-tête P3P a aidé à surmonter les problèmes de cookies iFrame d'IE (voir ma première édition). Après quelques jours de débogage intensif, j'ai découvert que la requête de permission de FB.ui n'envoie pas un nouveau jeton d'accès à chaque fois (<5%).

Si cela se produit, quelque chose a mal tourné. Mais ce petit quelque chose me rend fou. Comme cela se produit rarement, je peux supporter de rediriger les utilisateurs vers l'onglet facebook pour obtenir un nouveau jeton signé. Avec le nouveau SDK JS, espérons que cela n'arrivera plus.

Mise à jour : solution finale

Il y avait une petite chose que j'avais négligée et la solution peut être trouvée ici : problème FB n'est pas défini
Je n'ai pas chargé le SDK JS de manière asynchrone! Cela explique tout. Parfois, le fichier all.js ne se chargeait pas assez rapidement, donc il y avait une erreur JS. En raison de cela, ni le dialogue de permission ni la validation JS ne fonctionnaient et une valeur vide du champ d'entrée #session était envoyée.

2voto

Maciej Łebkowski Points 2869

Pour commencer, je déboguerais un peu plus. Journalisez le contenu des requêtes. Qu'est-ce qui est stocké dans $_SESSION, qu'est-ce qui est passé dans $_REQUEST. De plus, vérifiez s'il s'agit d'un problème de navigateur (est-ce que cela se produit indépendamment du navigateur, ou y a-t-il un modèle ?)

Mais étant donné que la correction du problème de cookie dans IE (en-tête P3P) a aidé, je suppose qu'il reste certains navigateurs qui refusent les cookies tiers. Autant que je sache, certaines versions de Safari et d'Opera font cela par défaut. De plus, cette erreur indique qu'aucun access_token n'a été fourni, contrairement à un invalide ou expiré.

Vous pouvez tester cela en désactivant les cookies tiers (en utilisant about:config dans Firefox par exemple), en désautoriser votre application (en utilisant la section "Applications et sites web" en bas des paramètres de confidentialité Facebook), supprimer les cookies (liés à votre URL de toile) et ensuite lancer l'application.

By the way, il y a toujours une possibilité que Facebook ne renvoie pas le jeton d'accès même s'il le devrait, comme décrit dans le bogue 17236

1voto

benny Points 11

Salut, j'ai rencontré le même problème semble que je l'ai résolu en observant l'API JS et en redirigeant vers la page de connexion PHP-SDK si les informations de l'utilisateur sont lisibles

exemple:

function check_fb_status(){
    FB.api('/me', function(response){
     if(response.name) window.location='<?php echo $facebook->getLoginUrl(); ?>';
     else check_fb_status();
    });
}

check_fb_status();

si le script réussit, il charge la page de connexion et l'utilisateur est reconnu à la fois par JS et PHP SDK ;)

0voto

Rob DiMarco Points 3852

Pour information, Facebook a publié une mise à jour du SDK PHP il y a environ 2 heures, qui ajoute le support du nouveau format de cookie, si vous créez une session côté client en utilisant le SDK JavaScript. La mise à jour peut être trouvée sur le référentiel GitHub de Facebook PHP-SDK.

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