Ryan Salmons
Ryan Salmons

Reputation: 1459

Facebook PHP SDK exception error

I am getting an interesting SDK exception message from FB's PHP SDK. I set up my code exactly as the FB docs say to do..?

DEBUG ERROR MESSAGE:

[12-Jun-2014 21:08:12 UTC] PHP Fatal error:  Uncaught exception 'Facebook\FacebookSDKException' with message 'Session not active, could not store state.' in C:\WebRoot\Website\root\inc\Facebook\FacebookRedirectLoginHelper.php:188
Stack trace:
#0 C:\WebRoot\Website\root\inc\Facebook\FacebookRedirectLoginHelper.php(94):Facebook\FacebookRedirectLoginHelper->storeState('**********...')
#1 C:\WebRoot\Website\root\login\index.php(87): Facebook\FacebookRedirectLoginHelper->getLoginUrl()
#2 {main}
   thrown in C:\WebRoot\Website\root\inc\Facebook\FacebookRedirectLoginHelper.php on line 188

Facebook.php:

<?php
require_once("../inc/config.php");
require_once(ROOT_PATH . 'inc/Facebook/FacebookSession.php' );
require_once(ROOT_PATH . 'inc/Facebook/FacebookRedirectLoginHelper.php' );
require_once(ROOT_PATH . 'inc/Facebook/FacebookRequest.php' );
require_once(ROOT_PATH . 'inc/Facebook/FacebookResponse.php' );
require_once(ROOT_PATH . 'inc/Facebook/FacebookSDKException.php' );
require_once(ROOT_PATH . 'inc/Facebook/FacebookRequestException.php' );
require_once(ROOT_PATH . 'inc/Facebook/FacebookAuthorizationException.php' );
require_once(ROOT_PATH . 'inc/Facebook/GraphObject.php' );
require_once(ROOT_PATH . 'inc/Facebook/HttpClients/FacebookCurl.php' );
require_once(ROOT_PATH . 'inc/Facebook/HttpClients/FacebookHttpable.php' );
require_once(ROOT_PATH . 'inc/Facebook/HttpClients/FacebookCurlHttpClient.php' );

use Facebook\FacebookSession;

// init app with app id (APPID) and secret (SECRET)
FacebookSession::setDefaultApplication("**********","*******************");

Main Login Page:

<?php
require_once("../inc/config.php");
require_once(ROOT_PATH . 'inc/Facebook/Facebook.php' );
require_once(ROOT_PATH . "inc/LoginHelper.php");

use Facebook\FacebookSession;
use Facebook\FacebookRedirectLoginHelper;
use Facebook\FacebookRequest;
use Facebook\FacebookResponse;
use Facebook\FacebookSDKException;
use Facebook\FacebookRequestException;
use Facebook\FacebookAuthorizationException;
use Facebook\GraphObject;
use Facebook\HttpClients\FacebookCurl;
use Facebook\HttpClients\FacebookHttpable;
use Facebook\HttpClients\FacebookCurlHttpClient;

session_start();

// login helper with redirect_uri
$helper = new FacebookRedirectLoginHelper( '***********' );

Link on main login page:

<a href="<?php echo $helper->getLoginUrl();?>"><img src="<?php echo BASE_URL; ?>img/facebook-login-button.png" class="fb-login"></a>

Redirect url page:

<?php
require_once("../inc/config.php");
require_once(ROOT_PATH . 'inc/Facebook/Facebook.php' );

use Facebook\FacebookSession;
use Facebook\FacebookRedirectLoginHelper;
use Facebook\FacebookRequest;
use Facebook\FacebookResponse;
use Facebook\FacebookSDKException;
use Facebook\FacebookRequestException;
use Facebook\FacebookAuthorizationException;
use Facebook\GraphObject;
use Facebook\HttpClients\FacebookCurl;
use Facebook\HttpClients\FacebookHttpable;
use Facebook\HttpClients\FacebookCurlHttpClient;

session_start();

//get user login token from FB
$helper = new FacebookRedirectLoginHelper('*******');
try {
   $session = $helper->getSessionFromRedirect();
} catch(FacebookRequestException $ex) {
     echo $ex;
  // When Facebook returns an error
} catch(Exception $ex) {
    echo $ex;
  // When validation fails or other local issues
}
if ($session) {
    $FacebookAccessToken = $session->getToken();
   // Logged in
}

Upvotes: 5

Views: 11798

Answers (3)

horizon1711
horizon1711

Reputation: 152

For using CakePHP v3.1.6 + Facebook SDK v4.1.

In the newer SDK, \Facebook\FacebookRedirectLoginHelper class has been changed to use \Facebook\FacebookSessionPersistentDataHandler class to handle session "state". Putting $this->request->session()->start() in AppController initialize will fix the problem using Facebook SDK with AuthComponent.

public function initialize() {
    parent::initialize();
    $this->request->session()->start();

    $this->loadComponent('RequestHandler');
    $this->loadComponent('Flash');

    $this->loadComponent('Auth', [
        'authenticate' => [
            'Form' => [
                'fields' => ['username' => 'email', 'password' => 'password']
            ]
        ],
        'loginAction' => ['controller' => 'Users', 'action' => 'login']
    ]);
}

Upvotes: 0

SammyK
SammyK

Reputation: 993

To expand Chancho's answer, the SDK will check to see if a session is active before it tries to store any data to it. There are 3 ways around this.

Start a native PHP session

If you're just using PHP's native sessions, Chancho's answer will suffice. You have to make sure that session_start(); is at the very top of your script before any output is sent.

Overwrite the session handling

If you're using a web framework like Codeigniter, Yii, CakePHP, Laravel, etc, they usually have their own ways of storing a session. To overwrite the default session store, you'll need to write your own class that extends the \Facebook\FacebookRedirectLoginHelper class. Then you'll need to overwrite the storeState() and loadState() methods. These are the only two methods in the whole SDK that interface with the $_SESSION variable.

You can see a laravel implementation example in the GitHub issues for the SDK. Here's the laravel implementation:

class MyFacebookRedirectLoginHelper extends \Facebook\FacebookRedirectLoginHelper
{
  protected function storeState($state)
  {
    Session::put('state', $state);
  }

  protected function loadState()
  {
    return $this->state = Session::get('state');
  }
}

Disable the session check completely

If you're trying to use the SDK in a stateless environment like the command line, there's no point in starting a session or overwriting how the session data is stored. You can simply disable the check with FacebookRedirectLoginHelper::disableSessionStatusCheck().

To disable the session check just run this.

$helper = new FacebookRedirectLoginHelper('*******');

$helper->disableSessionStatusCheck();

$session = $helper->getSessionFromRedirect();

// . . . 

I hope that helps!

Upvotes: 13

Azox
Azox

Reputation: 1940

Put session_start(); on the TOP of your file

Upvotes: 13

Related Questions