i’m trying to get Facebook user id using the php sdk like this
$fb = new FacebookFacebook([
'app_id' => '11111111111',
'app_secret' => '1111222211111112222',
'default_graph_version' => 'v2.4',
]);
$helper = $fb->getRedirectLoginHelper();
$permissions = ['public_profile','email']; // Optional permissions
$loginUrl = $helper->getLoginUrl('http://MyWebSite', $permissions);
echo '<a href="' . $loginUrl . '">Log in with Facebook!</a>';
try {
$accessToken = $helper->getAccessToken();
var_dump($accessToken);
} catch (FacebookExceptionsFacebookResponseException $e) {
// When Graph returns an error
echo 'Graph returned an error: ' . $e->getMessage();
exit;
} catch (FacebookExceptionsFacebookSDKException $e) {
// When validation fails or other local issues
echo 'Facebook SDK returned an error: ' . $e->getMessage();
exit;
}
if (!isset($accessToken)) {
if ($helper->getError()) {
header('HTTP/1.0 401 Unauthorized');
echo "Error: " . $helper->getError() . "n";
echo "Error Code: " . $helper->getErrorCode() . "n";
echo "Error Reason: " . $helper->getErrorReason() . "n";
echo "Error Description: " . $helper->getErrorDescription() . "n";
} else {
header('HTTP/1.0 400 Bad Request');
echo 'Bad request';
}
exit;
}
// Logged in
echo '<h3>Access Token</h3>';
var_dump($accessToken->getValue());
// The OAuth 2.0 client handler helps us manage access tokens
$oAuth2Client = $fb->getOAuth2Client();
// Get the access token metadata from /debug_token
$tokenMetadata = $oAuth2Client->debugToken($accessToken);
echo '<h3>Metadata</h3>';
var_dump($tokenMetadata);
// Validation (these will throw FacebookSDKException's when they fail)
$tokenMetadata->validateAppId($config['11111111111']);
// If you know the user ID this access token belongs to, you can validate it here
//$tokenMetadata->validateUserId('123');
$tokenMetadata->validateExpiration();
if (!$accessToken->isLongLived()) {
// Exchanges a short-lived access token for a long-lived one
try {
$accessToken = $oAuth2Client->getLongLivedAccessToken($accessToken);
} catch (FacebookExceptionsFacebookSDKException $e) {
echo "<p>Error getting long-lived access token: " . $helper->getMessage() . "</p>nn";
exit;
}
echo '<h3>Long-lived</h3>';
var_dump($accessToken->getValue());
}
$_SESSION['fb_access_token'] = (string)$accessToken;
but it give me this error:
Facebook SDK returned an error:
Cross-site request forgery validation failed.
The "state" param from the URL and session do not match.
please any help i’m new in php and Facebook sdk’s thank for any help in advance.
I found that as long as I enabled PHP sessions before generating the login url, and at the top of the script Facebook eventually redirects to, it works just fine on its own without setting a cookie (as per ale500’s answer). This is using the 5.1 version of the sdk.
At the top of both scripts, I added…
…and it “just worked”.
Here’s a barebones complete example that worked for me:
auth.php
auth_callback.php
Why?
As an additional note, this is explained in the Docs on the repo. Look at the warning on this page.
I’m adding this note because it’s important to keep in mind should you happen to be running your own session management or if you’re running multiple web servers in parallel. In those cases, relying upon php’s default session methods won’t always work.
insert this code after
$helper = $fb->getRedirectLoginHelper();
Lots of great answers already mentioned, here is the one which helped for me,
I found that the problem is Cross-site request forgery validation failed. Required param âstateâ missing in FB code and here is the solution
After this line
Add the below code,
I got this error while using the Facebook SDK in Symfony2, writing a Twig Extension to display data from the API in templates.
The solution for me was adding
'persistent_data_handler'=>'session'
to the Facebook object config, which causes the state data to be stored in a session key instead of memory:By default, it was using the built-in memory handler, which didn’t work properly for me. Maybe because some functions are being called from within a Twig Extension, as the memory handler does work when using the SDK exclusively in normal controllers/services.
Apparently the state is set when you call
getLoginUrl()
, and is retrieved anytime you callgetAccessToken()
. If the saved state returnsnull
(because your data handler isn’t as persistent as it should be), the CSRF validation check fails.If you need to treat sessions in a particular way or you want to store the state somewhere else, you can also write your own handler with
'persistent_data_handler' => new MyPersistentDataHandler()
, using the FacebookSessionPersistentDataHandler as an example.This happens when the Facebook library cannot match up the state param it receives back from Facebook with the one that it sets, by default, in the session. If you are using a framework such as Laravel, Yii2, or Kohana that implements its own session storage the standard Facebook session implementation will likely not work.
To fix it you need to create your own implementation of the
PersistentDataInterface
using your framework’s session library and pass this to theFacebookFacebook
constructor.Here’s an example of a Laravel persistence handler from Facebook:
Example constructor params:
More info here:
https://developers.facebook.com/docs/php/PersistentDataInterface/5.0.0
Finally, looking into FB code, I discovered that the problem
and similars are caused by PHP variable
$_SESSION['FBRLH_state']
that for some “strange” reason when FB call the login-callback file.To solve it I store this variable
"FBRLH_state"
AFTER the call of function$helper->getLoginUrl(...)
. Is very important to do only after the call of this function due to is inside this function when the variable$_SESSION['FBRLH_state']
is populated.Below an example of my code in the login.php:
And in the login-callback.php before calling all FB code:
Last, but not least, remember also to include code for PHP session so..
I hope this response can help you to save 8-10 hours of work 🙂
Bye, Alex.
For me, the problem was that I wasn’t running a session before the script.
So, I added
session_start();
before instantiating theFacebook
class.The Facebook object has an instance variable called
persistentDataHandler
, usually an instance ofFacebookSessionPersistentDataHandler
, which has a set and a get method to access the native PHP sessions.When generating the callback url using:
The methode
FacebookRedirectLoginHelper->getLoginUrl()
will create a 32-character random string, add it to the$loginUrl
and save it to the code below using thepersistentDataHandler
‘s set method.Later when the
$helper->getAccessToken();
is called, the state param in the url will be compared to the stored in the same session to prevent CSRF. If not match, this will exception be thrown.All these being said, you need to make sure your native PHP session feature is properly set during this process. You can check it, by adding
after
and before
to see if that 32-character string is there.
Hope it helps!
With Symfony, it doesn’t work because the way session are managed.
To resolve the problem you can create a new handler wich work with symfony’s session.
FacebookDataHandlerSymfony.php :
And when you create the FB Object, you have just to specifie the new class :
The same issue occurred to me on laravel 5.4 i solved this issue by putting
at the top of the script.
Below is the sample laravel controller namespace to give you a example how it will work.
the issue is occurring because is has not yet started so by adding session start at the top of the script we are just starting the session.
hope it may help somebody..
you receive this error if you origin hostname is different than the target hostname once authenticated.
with this statement, if the visitor on your website used http://www.mywebsite.com/ the cross-site error will be raised.
You must ensure that origin and target hostname are exactly the same, including the eventual www prefix.
Fixed version:
This might be kinda late but I hope it helps others since this problem still persists.
I had this problem for a while and I’ve searched around and have seen a lot of different solutions, many of which disable the CSRF check. So after everything I’ve read, this is what worked for me.
For what I understand, you get this error when your redirect URL doesn’t match the one you have setup on your app settings so my issue was fixed every easily but I have also seen people have issues by not having their session started properly, so I will cover both issues.
Step 1: Ensure your session has started when it needs to.
for example: fb-config.php
if your facebook callback code is on another file aside from the config, then start the session on that file too.
for example: fb-callback.php
Now, what solved my actual issue.
Step 3: Set up your redirect URL in your app settings.
In your Facebook Login app settings, go to the Valid OAuth redirect URIs where you should have added the url that points to your fb-callback.php file.
then setup your redirect url as follows.
Why both with and without www and why use SERVER_NAME?
because your Valid OAuth redirect URI needs to match your redirect url in your code and if in you app settings you only set your OAuth redirect as http://example.com/fb-callback.php and set up your $redirectURL as http://example.com/fb-bacllback.php to make it match but the user entered your site as http://www.example.com then the user will get the Facebook SDK error: Cross-site request forgery validation failed. Required param âstateâ missing from persistent data because the URL the user is at, doesn’t EXACTLY match what you have setup. Why? I have no freaking idea.
My approach makes it so if the user enters your site as http://example.com or http://www.example.com, it will always match what you setup in your app settings. why? because $_SERVER[‘SERVER_NAME’] will return the domain with or without the www depending on how the user entered the url in the browser.
This are my findings and this is about the only thing that worked for me without removing the CSRF check and so far, no issues.
I hope this helps.
you could just do this set the session with the new state
In my case i have checked error and found error which lead me to solution with executing code:
before script. Worked like a charm. For your location check: timezones.europe.php
Easy fix for me.
I changed:
to:
removing the
'www'
solved the problem.The error is triggered if origin hostname is different than the target hostname [as Souch mentioned]. When visitors typed in URL address box as “http://website.com” that is different from “http://www.website.com“. We redirect them to the correct URL, by adding the following codes at topmost position before session_start().
Yii2 solution that works for me:
I had the same error, because I forgot to add “www.” to the sender address. In the Client-OAuth Settings there has to be the correct name.
This is a common issue that many people facing in FB Api. this is only a SESSION problem. To solve this issue add some code like.
On callback script usually fb-callback.php add “session_start();” just before you include the facebook autoload file. and then “$_SESSION[‘FBRLH_state’]=$_GET[‘state’];” after the “$helper = $fb->getRedirectLoginHelper();” line.
Example :
Might help someone, who is using Javascript Helper in frontend for authenticating the user and in PHP one is trying to to extract access_token from Redirect Login Helper. So use following
instead of
SOLUTION FOR INTERMITTENT PROBLEMS
I was a) redirecting to Facebook login link, b) redirecting from login.php to main.php. Users would travel to main.php and a few other pages, then click back back back in browser.
Eventually, they would hit login.php with a bunch of creds posted to it, but Facebook removes the $_SESSION[‘FBRLH_state’] after a single success, so even though it had the proper $_GET[‘state’], it would error out.
The solution is to a) track internally if the user is logged in and avoid the repeat Facebook logic in login.php, OR b) keep track of all recently valid state parameters for that particular user (in a session perhaps) which were set by Facebook and if the $_GET[‘state’] is in that array, then do this:
$_SESSION[‘FBRLH_state’] = $_GET[‘state’];
In this case you can do this safely without breaking CSRF protection.
For me setting the session state worked
Complete code ( in the redirect url php )
I am playing around with Symfony and was having this problem one attempt yes and the next one no.
I solved this problem by storing the facebookRedirectLoginHelper object into session, and retrieving it later on from the session instead of asking the Facebook object for it again.
The documentation (Symfony 4.3 at the time of this writing) states the following:
So I think that retrieving the object from the session inherently starts the php session.
If you are using some php framework, keep that in mind.
For me the problem was different; (I was stupid)
I had a popup window with Facebook login and again Facebook login buttons in Login/Signup page.
The reason was i had re-instantiated the Facebook and getRedirectLoginHelper objects. I had to comment out these statements in Login/Signup pages, as it was already available.
is not the way to go. Although it worked.
if you keep to see the error, just clean your browser cache.
When I’ve fixed the problem using the enobrev solution, I was continuing to experience the error.
After a while I’ve understood that I needed to clean the cache and after I’ve restarted the browser it worked!