web-dev-qa-db-fra.com

Facebook PHP SDK 5 :: API 2.4 :: La validation de la falsification de requête intersite a échoué. Param requis "état" manquant

J'ai fait un script très simple PHP, juste pour essayer de se connecter via Facebook et obtenir un accessToken. Mais lorsque j'essaie le code suivant, je reçois une exception du SDK: «La validation de la falsification d'une requête intersite a échoué. Param requis "état" manquant. ».

Voici mon code:

require_once __DIR__ . '/facebook-sdk-v5/autoload.php';
session_start();

$fb = new Facebook\Facebook([
    'app_id' => '{my-own-app-id}',
    'app_secret' => '{my-own-app-secret}'
]);

// Check to see if we already have an accessToken ?
if (isset($_SESSION['facebook_access_token'] )) {
    $accessToken = $_SESSION['facebook_access_token'];
    echo "Horray we have our accessToken:$accessToken<br />\n";

} else {
    // We don't have the accessToken
    // But are we in the process of getting it ? 
    if (isset($_REQUEST['code'])) {
        $helper = $fb->getRedirectLoginHelper();
        try {
            $accessToken = $helper->getAccessToken();
            } catch(Facebook\Exceptions\FacebookResponseException $e) {
              // When Graph returns an error
              echo 'Graph returned an error: ' . $e->getMessage();
              exit;
        } catch(Facebook\Exceptions\FacebookSDKException $e) {
              // When validation fails or other local issues
              echo 'Facebook SDK returned an error: ' . $e->getMessage();
            exit;
        }

        if (isset($accessToken)) {
              // Logged in!
              $_SESSION['facebook_access_token'] = (string) $accessToken;

              // Now you can redirect to another page and use the
              // access token from $_SESSION['facebook_access_token']

              echo "Finally logged in! Token:$accessToken";
        }           
    } else {
        // Well looks like we are a fresh dude, login to Facebook!
        $helper = $fb->getRedirectLoginHelper();
        $permissions = ['email', 'user_likes']; // optional
        $loginUrl = $helper->getLoginUrl('http://mywebsite.com/myapp/index.php', $permissions);

        echo '<a href="' . $loginUrl . '">Log in with Facebook!</a>';
    }

}

exit;
12
Éric Senterre

J'ai dû ajouter ces lignes sur certains serveurs:

$helper = $fb->getRedirectLoginHelper();
if (isset($_GET['state'])) {
    $helper->getPersistentDataHandler()->set('state', $_GET['state']);
}

Je reçois cette erreur au hasard, en fonction de la configuration du serveur.

22
M.Dalda

session_start () au début des deux scripts. J'ai eu la solution à partir d'ici: https://github.com/facebook/facebook-php-sdk-v4/issues/473

9
Ruhul Amin

Si vous utilisez une version "www" de votre site pour générer le lien de connexion et que vous êtes redirigé vers la version non-www, vous rencontrerez des problèmes avec votre session. Assurez-vous donc d’accéder à la version www de votre site, puis définissez l’URL de rappel sur la même version www. Vous pouvez également définir des redirections permanentes dans la configuration de votre serveur pour vous assurer que toute personne accédant à votre site à partir de la version non www sera redirigée vers la version www ou vice versa.

9
che-azeh

J'ai également rencontré le même problème et après des recherches sur stackoverflow Putting line 

$_SESSION['FBRLH_state']=$_GET['state']; 

ci-dessus a résolu mon problème 

$helper = $fb->getRedirectLoginHelper();  
3
ashutosh

C’est un problème courant auquel de nombreuses personnes sont confrontées dans FB Api. ce n'est qu'un problème de SESSION. Pour résoudre ce problème, ajoutez du code tel que.

Sur le script de rappel habituellement fb-callback.php ajoute "session_start ();" juste avant d'inclure le fichier de chargement automatique de facebook. et ensuite "$ _SESSION ['FBRLH_state'] = $ _ GET ['state'];" après le "$ helper = $ fb-> getRedirectLoginHelper ();" ligne. 

Exemple : 

<?php 
session_start(); /*Add session start*/
include 'vendor/autoload.php';
include 'config.php'; /*Facebook Config*/
$helper = $fb->getRedirectLoginHelper();
$_SESSION['FBRLH_state']=$_GET['state']; /*Add This*/
try {
  $accessToken = $helper->getAccessToken();
} ?>

Définir explicitement [PersistentDataHandler] avant d’obtenir vos jetons garantira le succès de la demande. Vous trouverez ci-dessous comment récupérer $ _GET ['state'] et l'injecter simplement dans le "à utiliser [assistant]" sur Symfony 2.x | 3.x

J'ai eu exactement le même problème que l'O.P. et cela a résolu mon problème.

//create your new facebook sdk instance
$this->fb = new Facebook([
   'app_id' => $facebookAppId,
   'app_secret' =>$facebookAppSecret,
   'default_graph_version' =>$facebookDefaultGraphVersion
]);    

//retrieve the helper
$this->helper = $this->fb->getRedirectLoginHelper();

//below is the money shot
//setting this explicitly before you get your tokens will guarantee that the request will be a success. It Fetches $_GET['state'] & simply injects it into the "to be used [helper]"
$this->helper->getPersistentDataHandler()->set('state', $request->query->get('state'));
2
Dan Baddeley

vous recevez cette erreur si votre nom d’hôte Origin est différent du nom d’hôte cible une fois authentifié.

$loginUrl = $helper->getLoginUrl('http://mywebsite.com/myapp/index.php', $permissions);

avec cette déclaration, si le visiteur de votre site Web a utilisé http://www.mywebsite.com/ , l'erreur intersite sera générée.

Vous devez vous assurer que l'origine et le nom d'hôte cible sont exactement les mêmes, y compris le préfixe www éventuel.

Version fixe:

$loginUrl = $helper->getLoginUrl('http://'.$_SERVER['SERVER_NAME'].'/myapp/index.php', $permissions);
2
Jean.R

J'ai rencontré un problème similaire et j'ai trouvé la solution de Nanang Koesharwanto. Cela ressemble plus à un hasard, car la modification des fichiers source dans le répertoire du fournisseur est une très mauvaise idée. .__ Alors, voici le truc. 

public function callback(Request $request)
{
    $this->helper->getPersistentDataHandler()->set('state', $request->state);
    return $this->helper->getAccessToken();
}

Si cela échoue, mettez use Session; dans votre contrôleur.

1
Rajender Joshi

J'essayais d'implémenter la connexion à Facebook dans Symfony avec le kit de développement logiciel PHP et j'avais la même erreur "La validation de la demande de cross-site a échoué. Param requis" état "manquant".

J'ai résolu le problème en ajoutant persistent_data_handler paramètre à mon instanciation de l'application facebook avec un gestionnaire personnalisé qui implémente le SDK PersistentDataInterface de Facebook PHP.

Fonctionne comme un charme.

public function facebookCallbackAction(Request $request) {
    $session = $request->getSession();

    $fb = new \Facebook\Facebook([
        'app_id' => $this->container->getParameter('facebook_app_id'),
        'app_secret' => $this->container->getParameter('facebook_app_secret'),
        'default_graph_version' => 'v2.5',
        'persistent_data_handler' => new SymfonyPersistentDataHandler($session),
    ]);
}

Mon gestionnaire personnalisé:

use Facebook\PersistentData\PersistentDataInterface;
use Symfony\Component\HttpFoundation\Session\Session;

class SymfonyPersistentDataHandler implements PersistentDataInterface {
    protected $session;
    protected $sessionPrefix = 'FBRLH_';

    public function __construct(Session $session) {
        $this->session = $session;
    }

    public function get($key) {
        return $this->session->get($this->sessionPrefix . $key);
    }

    public function set($key, $value) {
        $this->session->set($this->sessionPrefix . $key, $value);
    }
}
1
Julien F.

Laravel 5.2

J'ai aussi cette erreur "Échec de la validation de la requête intersite. Param requis" état "manquant".

et après avoir lu ceci pendant des heures. J'ai essayé de changer le script du vendeur.

dans vendor\facebook\php-sdk-v4\src\Facebook\Helpers\FacebookRedirectLoginHelper.php à la ligne 123, je modifie ce script:

private function makeUrl($redirectUrl, array $scope, array $params = [], $separator = '&')
{
    $state = $this->pseudoRandomStringGenerator->getPseudoRandomString(static::CSRF_LENGTH);
    $this->persistentDataHandler->set('state', $state);

    return $this->oAuth2Client->getAuthorizationUrl($redirectUrl, $state, $scope, $params, $separator);
}

dans (j'ajoute Session::put('state', $state);)

private function makeUrl($redirectUrl, array $scope, array $params = [], $separator = '&')
{
    $state = $this->pseudoRandomStringGenerator->getPseudoRandomString(static::CSRF_LENGTH);
    $this->persistentDataHandler->set('state', $state);
    Session::put('state', $state);
    return $this->oAuth2Client->getAuthorizationUrl($redirectUrl, $state, $scope, $params, $separator);
}

et sur la ligne 234, je change ce script:

protected function validateCsrf()
{
    $state = $this->getState();
    $savedState = $this->persistentDataHandler->get('state');

    if (!$state || !$savedState) {
        throw new FacebookSDKException('Cross-site request forgery validation failed. Required param "state" missing.');
    }

    $savedLen = strlen($savedState);
    $givenLen = strlen($state);

    if ($savedLen !== $givenLen) {
        throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.');
    }

    $result = 0;
    for ($i = 0; $i < $savedLen; $i++) {
        $result |= ord($state[$i]) ^ ord($savedState[$i]);
    }

    if ($result !== 0) {
        throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.');
    }
}

dans (j'ai ajouté $this->persistentDataHandler->set('state', Session::get('state'));)

protected function validateCsrf()
{
    $state = $this->getState();
    $this->persistentDataHandler->set('state', Session::get('state'));
    $savedState = $this->persistentDataHandler->get('state');

    if (!$state || !$savedState) {
        throw new FacebookSDKException('Cross-site request forgery validation failed. Required param "state" missing.');
    }

    $savedLen = strlen($savedState);
    $givenLen = strlen($state);

    if ($savedLen !== $givenLen) {
        throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.');
    }

    $result = 0;
    for ($i = 0; $i < $savedLen; $i++) {
        $result |= ord($state[$i]) ^ ord($savedState[$i]);
    }

    if ($result !== 0) {
        throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.');
    }
}

c'est tout ce que j'ai fait. et l'erreur est partie.

1

Pour moi, le problème est résolu maintenant en démarrant la session en ajoutant ceci:

session_start();

au début des deux fichiers (le premier fichier générant l'URL facebook et le fichier de rappel: login.php et fb-callback.php ( https://developers.facebook.com/docs/php/howto/example_facebook_login ) ).

J'ai aussi dû ajouter ceci:

$config['app_id'] = 'myapp_id';

en haut pour éviter une autre erreur non liée.

1
Adam Tong

Comme je l’ai répondu ici: Le SDK de Facebook a renvoyé une erreur: la validation de la falsification de requête intersite a échoué. Le paramètre "state" de l'URL et de la session ne correspond pas

vous devez vous assurer que votre fonction de session native PHP est correctement définie.

1
Chao Chen

Enfin, en examinant le code FB, j’ai découvert que le problème "La validation de la demande intersite a échoué. Les paramètres" état "manquant" et autres sont causés par la variable PHP $ _SESSION ['FBRLH_state' " étrange "lorsque FB appelle le fichier login-callback.

Pour le résoudre, je stocke cette variable "FBRLH_state" APRES l'appel de la fonction $ helper-> getLoginUrl (...). Il est très important de ne le faire qu'après l'appel de cette fonction car c'est à l'intérieur de celle-ci que la variable $ _SESSION ['FBRLH_state'] est renseignée.

Ci-dessous un exemple de mon code dans le login.php:

$uri=$helper->getLoginUrl($uri, $permissions);
foreach ($_SESSION as $k=>$v) {                    
    if(strpos($k, "FBRLH_")!==FALSE) {
        if(!setcookie($k, $v)) {
            //what??
        } else {
            $_COOKIE[$k]=$v;
        }
    }
}
var_dump($_COOKIE);

Et dans le fichier login-callback.php avant d'appeler tout le code FB:

foreach ($_COOKIE as $k=>$v) {
    if(strpos($k, "FBRLH_")!==FALSE) {
        $_SESSION[$k]=$v;
    }
}

Dernier point, mais non le moindre, n'oubliez pas d'inclure également du code pour la session PHP.

if(!session_id()) {
    session_start();
}
...
...
...
...
<?php session_write_close() ?>

J'espère que cette réponse pourra vous aider à économiser 8 à 10 heures de travail:) Bye, Alex.

0
ale500

Le vrai problème ici était l'encodage de mon fichier PHP. J'ai utilisé UTF8, mais cela aurait dû être UTF8 sans nomenclature.

L'inconvénient d'un mauvais encodage était que ma SESSION ne fonctionnait pas correctement, ce qui empêchait le SDK de récupérer les informations nécessaires pour fonctionner correctement. 

Un rapport d'erreur correctement configuré aurait indiqué qu'il y avait un problème directement. 

Je pense que nous pouvons combler ce bogue dans la catégorie "noob". Mais encore, je pense que cela peut être utile à d'autres noobs comme moi. 

0
Éric Senterre

Si session_start () ne résout toujours pas le problème, vous insérez un mauvais URI dans l'URI de redirection OAuth valide de votre application de développeur Facebook. 

Pour résoudre: Tout d’abord, allez à votre fb-callback.php, recherchez l’URI que vous avez mis dans la fonction d’entête, exemple: entête ("Location: https: //localhost/home.php "). Ensuite, accédez à vos applications de développement Facebook, puis dans la barre latérale, cliquez sur Connexion Facebook, sous l'onglet Produits, puis sur Paramètres. Dans l'URI de redirection OAuth valide, ajoutez l'URI que vous avez mis dans l'en-tête. De mon exemple, je vais mettre https: //localhost/home.php

J'espère que cela t'aides.

0

vous devez vous assurer que la session démarre avant l'exécution du script. mais là encore, un 443: Network is unreachable sera lancé si vous démarrez à nouveau une session sur le même script. espérons que cela aide quelqu'un.

Je viens d'utiliser if (session_status() == PHP_SESSION_NONE){ session_start(); } 

0
Tharindu

Pour ceux d'entre vous qui utilisent cakephp 3.x et ont ce problème et vous ne savez pas comment le résoudre. Ajouter session_start (); au début de votre méthode d'authentification et de rappel. 

public function Facebookauth()
{
session_start();
 $fb = new Facebook([
      'app_id' => '{app_id}',
      'app_secret' => '{app_secret}',
      'default_graph_version' => 'v2.6',
     ..........

    ]);

you can still use 
     $session = $this->request->session();
0

Le correctif pour moi était de changer 'secure' => true en false dans config/session.php . Je l'avais accidentellement mis à true, alors que je n'utilisais pas https.

0
Jonas Menk

Pour moi, cela était dû à 'persistent_data_handler' . En ajoutant ceci dans la configuration Facebook, j'ai pu le faire fonctionner.

session_start();
$fb = new Facebook\Facebook([
  'app_id'     => '6XXXXXXXXX',
  'app_secret' => '5XXXXXXXXXXXXXX',
  'default_graph_version' => 'v2.6', 
  'persistent_data_handler' => 'session'
  ]);
0
Amit Tyagi

Pour moi, la solution consistait à intercepter l'exception en remplaçant le Facebook\Exceptions\FacebookSDKException namespaced par simplement Exception, car le script l'avait déjà utilisée.

use Facebook\Facebook;

// code ...

$fb = new Facebook([
    'app_id' => FB_APP_ID,
    'app_secret' => FB_APP_SECRET,
    'default_graph_version' => 'v2.5',
]);

$helper = $fb->getRedirectLoginHelper();
try {
    $accessToken = $helper->getAccessToken();
} catch (Exception $e) {
    echo $e->getMessage();
    exit;
}
0
michalzuber