Comment gérer correctement la session et le jeton d'accès avec Facebook PHP SDK 3.0?
Dans le PHP 3.0 SDK, il n'y a pas de getSession()
ni de gestion de session en dehors de l'API Facebook disponible. Il y a quelques jours, les développeurs de facebook ont également mis à jour le sdk JavaScript, selon cette entrée de blog et ce rapport de bogue.
Au cours des derniers jours, un changement a été introduit dans le SDK hébergé JS qui a brisé toute la compatibilité entre elle et le courant PHP SDK (2.x et 3.x) . Les développeurs qui utilisent à la fois le JS et PHP Le SDK sur leurs sites Web est probable pour voir l'échec de l'API côté serveur.
Cependant, je ne sais pas si cela affecte vraiment mon problème. Comme dans réponse de cette question, je récupère le jeton d'accès de la boîte de dialogue OAuth avec PHP et enregistre le nouveau jeton d'accès dans la session.
Contournement actuel
Le code suivant montre comment je gère ces sessions. $_REQUEST['session']
est le contenu de la réponse de la boîte de 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 de l'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 bien pendant les tests. Une fois qu'une erreur est survenue: la première fois après que l'autorisation a été définie. Maintenant, puisque l'application est en ligne, il semble que l'erreur se produise en moyenne avec un utilisateur sur deux
$facebookUser = $this->api->api('me?fields=id,name,first_name,last_name');
avec l'erreur:
An active access token must be used to query information about the current user.
Question
Pourquoi cela se produit-il donc? Il est très difficile de déboguer car l'erreur semble se produire uniquement lorsqu'un utilisateur entre dans l'application pour la première fois, après que l'authentification de l'application et le jeton d'accès ont été modifiés. Et même cela ne se produit pas à chaque fois. Comment dois-je gérer la session et le jeton d'accès correctement avec le nouveau PHP SDK?
Toute aide serait très appréciée!
Modifier
J'ai découvert qu'il y avait quelques IE problèmes de cookies/session dans un iFrame. Comme vu dans cet article de blog. Avec cet indice 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 beaucoup mieux, mais les informations d'environ 2 utilisateurs sur 50 sont perdues entre les étapes de la page de destination (authentification) -> formulaire -> et l'enregistrement. Donc, il y a encore quelque chose qui m'a manqué.
Modifier 2
J'ai modifié la gestion de mes utilisateurs depuis
if ($this->user === false || is_null($this->user)) {
// get user data
}
à
if ((is_object($this->user) && $this->user->fbId == '') || $this->user === false || is_null($this->user)) {
// get user data
}
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 quelque part dans mon application, une OAuthException
de Facebook est lancée. Si tel est le cas, je redirige l'emplacement top vers la page et l'onglet Facebook pour obtenir une nouvelle demande signée. Bien que cela puisse aider à résoudre ce problème, je souhaite éviter que mon application ait à rediriger l'utilisateur.
Modifier 3
Après quelques jours de débogage et de journalisation intenses, j'ai découvert que le $_REQUEST['session']
provenant de la méthode FB.ui permissions.request était rarement vide.
Voici comment je le gère:
Voici ce que j'ai toujours inclus:
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. Toujours travaillé pour moi, mais de toute façon, il envoie toujours le formulaire bien que 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;
}
Ma solution
Eh bien, puisque tout ce que j'ai fait n'était qu'une solution de contournement jusqu'à la sortie du nouveau SDK de JS, il ne semble pas exister de meilleure pratique. Définir session.use_trans_sid
sur 1 et ajouter l'en-tête P3P ont permis de surmonter les problèmes de cookie iFrame IE (voir ma première modification). Après quelques jours de débogage intensif, j'ai découvert que le permission_request
de FB.ui n'envoyait pas à chaque fois un nouveau jeton d'accès (<5%).
Si cela se produit, quelque chose s'est mal passé. 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 une nouvelle demande signée. Espérons que cela ne se produira plus avec le nouveau SDK JS.
Mise à jour: solution finale
J'ai surveillé une petite chose et la solution peut être trouvée ici: FB n'est pas un problème défini
Je n'ai pas chargé le SDK JS de manière asynchrone! Cela explique tout. Parfois, le fichier all.js n’était pas chargé assez rapidement, il y avait donc une erreur JS. Pour cette raison, ni la boîte de dialogue d'autorisation ni la validation JS n'ont fonctionné et une valeur d'entrée #session vide a été envoyée.
J'utilise maintenant 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 Graph ou Rest API.
$user = $facebook->getUser();
if ($user) {
//USER Logged-In
}
else {
//USER not Logged-In
}
//TO GET ACCESS TOKEN
$access_token = $facebook->getAccessToken();
//MAKE AN API CALL WITH IT
$user_info = $facebook->api('me?fields=id,name,first_name,last_name&access_token='.$access_token);
Pour commencer, je déboguerais un peu plus. Consignez le contenu des demandes. Ce qui est stocké dans $ _SESSION, ce qui est passé dans $ _REQUEST. Vérifiez également s’il s’agit d’un problème lié au navigateur (se produit-il quel que soit le navigateur ou existe-t-il un motif?)
Mais comme la résolution du problème de cookie dans IE (en-tête P3P) a aidé, j’imagine qu’il reste quelques navigateurs qui nient les cookies tiers. Autant que je sache, certaines versions de Safari et Opera le font par défaut. De plus, cette erreur indique qu’aucun access_token
n’a été fourni, par opposition à un invalide ou à un expiré.
Vous pouvez tester cela en désactivant les cookies tiers ( avec about: à l'aide de: config dans firefox , par exemple), en annulant l'autorisation de votre application (à l'aide de la section "Applications et sites Web" au bas de paramètres de confidentialité de Facebook ), en supprimant les cookies (liés à l'URL de votre toile), puis en lançant l'application.
En passant, il est toujours possible que facebook ne retourne pas le jeton d’accès même s’il le devrait, comme décrit dans le bogue 17236
Salut, j'ai couru dans le même problème semble que je l'ai résolu avec regarder l'API JS et redirige vers la page de connexion PHP-SDK si les informations de l'utilisateur est lisible
exemple:
<script language="JavaScript">
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();
</script>
si le script réussit, il charge la page de connexion et l'utilisateur est reconnu à la fois par JS et par PHP SDK;)
Pour votre information, Facebook a publié une mise à jour du SDK PHP il y a environ 2 heures, qui prend en charge le nouveau format de cookie si vous créez une session sur le client à l'aide du SDK JavaScript. La mise à jour se trouve sur Facebook PHP-SDK GitHub repo .