nikosson nikosson - 5 months ago 151
PHP Question

Cross-site request forgery validation failed. Required param "state" missing. Yii-2

So i've got login(here it called facebook) action in my controller, login-callback action and display action, where i want to view information using Facebook API. I've read about my problem and 've found that seems like my sessions are switched off, but i also read that in Yii-2 they are automatically switched on when an app is initialised. Also i tried it without framework, and it worked well. Maybe someone faced with such a problem in Yii-2?

Login action

**public function actionFacebook()**
{
$fb = new Facebook([
'app_id' => 'my_app_id',
'app_secret' => 'my_app_secret',
'default_graph_version' => 'v2.5',
]);
$helper = $fb->getRedirectLoginHelper();
$permissions = ['user_friends']; // optional
$loginUrl = $helper->getLoginUrl('http://myblog.local/site/callback', $permissions);

return $this->render('facebook', [
'loginUrl' => $loginUrl,
]);

}


Callback action

**public function actionCallback()**
{
$fb = new Facebook([
'app_id' => 'my_app_id',
'app_secret' => 'my_app_secret',
'default_graph_version' => 'v2.5',
]);

$helper = $fb->getRedirectLoginHelper();
try {
$accessToken = $helper->getAccessToken();
} catch(FacebookResponseException $e) {
// When Graph returns an error
echo 'Graph returned an error: ' . $e->getMessage();
exit;
} catch(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']

return $this->redirect('/site/display',302);
}
}


Display action(where i want to view information using Facebook API)

public function actionDisplay()
{
$fb = new Facebook([
'app_id' => '491899464333863',
'app_secret' => 'f684b9467c548991cc3a91e028163e15',
'default_graph_version' => 'v2.5',
]);

// Sets the default fallback access token so we don't have to pass it to each request
$fb->setDefaultAccessToken($_SESSION['facebook_access_token']);

try {
$response = $fb->get('/me');
$userNode = $response->getGraphUser();
} catch(FacebookResponseException $e) {
// When Graph returns an error
echo 'Graph returned an error: ' . $e->getMessage();
exit;
} catch(FacebookSDKException $e) {
// When validation fails or other local issues
echo 'Facebook SDK returned an error: ' . $e->getMessage();
exit;
}

return $this->render('display', [
'userName' => $userNode,
]);
}

Answer

In Yii2, changing $S_SESSION content will not work if you didn't open a session before with session_start().

When you access session data through the session component, a session will be automatically opened if it has not been done so before. This is different from accessing session data through $_SESSION, which requires an explicit call of session_start().

Source: http://www.yiiframework.com/doc-2.0/guide-runtime-sessions-cookies.html

Yii2 has a class to manage sessions. So, you could store the accesToken in your callback action with:

$session = Yii::$app->session;
$session['accessToken'] =  $accessToken; 

And then, in your display action:

$session = Yii::$app->session;
[...]
$fb->setDefaultAccessToken($session['accessToken']);

Remember that you could check the $_SESSION content with the debug toolbar.

More info: http://www.yiiframework.com/doc-2.0/yii-web-session.html