Facebook PHP SDK 5 :: API 2.4 :: Cross-site request forgery validation failed. Required param "state" missing

36,382

Solution 1

I had to add this lines in some servers:

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

I get this error randomly, depending of the server config.

Solution 2

session_start() at the beginning of both the scripts. I got solution from here: https://github.com/facebook/facebook-php-sdk-v4/issues/473

Solution 3

If you're using a "www" version of your site to generate the login link and you get redirected to the non-www version, you'll run into issues with your session. So make sure you access the www version of your site and then define the callback url to the same www version. Also, you can define permanent redirects in your server configuration to make sure anyone accessing your site from the non-www version gets redirected to the www version or vice versa.

Solution 4

I also ran into the same problem and after researching on stackoverflow putting line

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

above has solved my problem

$helper = $fb->getRedirectLoginHelper();  

Solution 5

Setting [PersistentDataHandler] explicitly before you get your tokens will guarantee that the request will be a success. Below shows how to fetch $_GET['state'] & simply inject it into the "to be used [helper]" on Symfony 2.x | 3.x

I had the exact same issue as the O.P. and this fixed my problem.

//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'));
Share:
36,382
Éric Senterre
Author by

Éric Senterre

All kind of web dev.

Updated on May 09, 2020

Comments

  • Éric Senterre
    Éric Senterre about 4 years

    I did a very simple PHP script, just to try to login via Facebook and get an accessToken. But when I try the following code, I get an Exception from the SDK : « Cross-site request forgery validation failed. Required param "state" missing. ».

    Here is my 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;
    
  • Tatters
    Tatters almost 9 years
    Hi Éric, I have the same error. Bit of a noob myself. I swear it was working fine a few days ago but now I have the same error as yourself. My provider is running UTF-8 (default_charset)...are you saying this needs to change to UTF8 w/o BOM for the login to work? Thanks
  • Éric Senterre
    Éric Senterre almost 9 years
    Yes your PHP file needs an encoding of UTF8 w/o BOM. Otherwise the PHP file send a character before "session_start()" can create his cookies in the HTTP header (or something like that). I get in this problem in part because I'm a new user of Notepad++. And I blindly set my encoding to UTF8 because French accents weren't showing correctly on my page, like I used to do in EditPlus. So basically, YES set your PHP file encoding to UTF8 w/o BOM. I can't guarantee that it'll fix your problem, but it solved mine.
  • Tatters
    Tatters almost 9 years
    Nice one, thanks. I'll give it a try and see what happens.
  • CodeGuru
    CodeGuru almost 8 years
    Too much to change.
  • grpaiva
    grpaiva over 7 years
    I've been struggling with this issue for hours and that's the only solution that works for me. Thanks man!
  • Duy Hoang
    Duy Hoang over 7 years
    It worked like a charm. This is the best answer. Thank you
  • andrewtweber
    andrewtweber about 7 years
    You should not change vendor files!
  • tomasbedrich
    tomasbedrich almost 7 years
    Do NOT do this! This effectively bypasses a CSRF check.
  • 3DFace
    3DFace almost 7 years
    Be aware that such solution breaks CSRF protection. Because protection based on comparison of stored token and received one. Provided code force them to match - its overwrite stored token with received.
  • Phyllis Sutherland
    Phyllis Sutherland over 6 years
    Be aware that this solution bypasses a CSRF check put in place by the API.
  • Phyllis Sutherland
    Phyllis Sutherland over 6 years
    Be aware that this solution bypasses a CSRF check put in place by the API.
  • Nanang Koesharwanto
    Nanang Koesharwanto over 6 years
    @andrewtweber : no more options for me, as I already tried several methods, and this is the only method that works in my case.
  • Amila K.
    Amila K. about 6 years
  • Leonardo Max
    Leonardo Max over 3 years
    we all know that we cannot change supplier files, but this solution has solved it!
  • Nanang Koesharwanto
    Nanang Koesharwanto over 3 years
    @CodeGuru, I don't think so, because it's only add one line script in function makeUrl, and one line in function validateCsrf.