Facebook API Session contents randomly changing - php

So I posted a previous question before about this, but deleted it because I've discovered my problem.
Basically, I was getting this error:
Facebook SDK returned an error: Cross-site request forgery validation failed. The "state" param from the URL and session do not match.
I was able to pinpoint that for some bizarre reason, my $_SESSION['FBRLH_state'] as changing. Here is the login.php that generates the login url for the user:
session_start();
}
require_once $_SERVER['DOCUMENT_ROOT'] . '/src/Facebook/autoload.php';
$fb = new Facebook\Facebook ([
'app_id' => '??????',
'app_secret' => '????',
'default_graph_version' => 'v2.4'
]);
$helper = $fb->getRedirectLoginHelper();
$loginUrl = $helper->getLoginUrl('http://example.ca/login-callback.php');
echo 'Login';
print_r($_SESSION);
When I do a print_r($_SESSION);, I get this:
Array ( [FBRLH_state] => d116b427b433a0b3dc41a858782cd690 )
However (get ready for the magic), upon redirection to the login-callback.php file, the array of $_SESSION mysteriously changes to this:
Array ( [FBRLH_state] => e99c4ece0f8e48ab53dea6a4826c5593 )
Here is the code for login-callback.php
<?php
header("Content-type: text/html;charset=utf-8");
session_start();
print_r($_SESSION);
require_once $_SERVER['DOCUMENT_ROOT'] . '/src/Facebook/autoload.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/Database.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/User.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/vars/constants.php';
//Create the Facebook service
$fb = new Facebook\Facebook ([
'app_id' => '????',
'app_secret' => '????',
'default_graph_version' => 'v2.4'
]);
$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)) {
$mysqli = Database::connection();
// Logged in!
$_SESSION['facebook_access_token'] = (string) $accessToken;
When I print $_SESSION (the first thing I do right after the headers), I get a completely different value from the login.php one. It makes no sense because they're both on the same domain (non-www) and they have the same document.cookie PHPSESSID
But, there's a catch. If I press back on login-callback.php (since login.php redirects to it, and then the login fails due to this weird session magic), the $_SESSION values mysteriously match. This doesn't work if I refresh, ONLY when I press back. I think this is some important clue as to what's going on but I have no idea.
Can someone please help me on this extremely frustrating issue? Anyone with any idea of what might be going on?
Edit: Also, I created a blank file with just
session_start();
print_r($_SESSION);
And the values I get always match login-callback.php which means that login.php must be changing some session values (but.... I can't figure out how since when I print_r($_SESSION); at the bottom of the file I still get the same weird values)

Weirdest solution, the problem was solved when I removed the </head> (basically I let <head> be unclosed)

Related

Cant get an accessToken from FB sdk

I would like to get images from my Instagram account to my web page. So I try to use FB php sdk and get accessToken first according this documentation. But it returns null. I don't know what is wrong with the code.
public function getMedia()
{
$fb = new \Facebook\Facebook([
'app_id' => self::APP_ID,
'app_secret' => self::APP_SECRET,
'default_graph_version' => 'v2.10',
//'default_access_token' => '{access-token}', // optional
]);
$helper = $fb->getRedirectLoginHelper(); // Whichever helper I use access-token is null
dd($helper->getAccessToken());
}
I need help with it. It could be so simple.
EDIT:
After few hours I have this, but the last command throws an Facebook\Exceptions\FacebookResponseException Invalid OAuth access token signature. As I see the token is app id and app secret joined with pipe. "733163597544229|xxxxxxxxxxxxx9d14362xxxx3a6". This should work but does not work.
public function getMedia()
{
$fb = new \Facebook\Facebook([
'app_id' => self::APP_ID_FB,
'app_secret' => self::APP_SECRET_FB,
'default_graph_version' => 'v2.10',
//'default_access_token' => '{access-token}', // optional
]);
$token = $fb->getApp()->getAccessToken();
$response = $fb->get('https://graph.instagram.com/me/media?fields=media_url,media_type', $token->getValue());
}
If I've understood the docs correctly, if you want to get an access token dynamically, according to https://developers.facebook.com/docs/facebook-login/web, you need enable fb-login for your app
https://developers.facebook.com/apps/
select your app
add fb-login & follow the tips.
Otherwise you should just be able to get an access token for your app from the web interface and use that over and over.
See also : https://developers.facebook.com/docs/facebook-login/access-tokens#apptokens
There's also:
https://developers.facebook.com/tools/explorer/?method=GET&path=me%3Ffields%3Did%2Cname&version=v9.0
Which enables you to generate an access token, and test out a call to the graph api, AND allows you to export code you can copy/paste:
try {
// Returns a `FacebookFacebookResponse` object
$response = $fb->get(
'/me',
'{access-token}'
);
} catch(FacebookExceptionsFacebookResponseException $e) {
echo 'Graph returned an error: ' . $e->getMessage();
exit;
} catch(FacebookExceptionsFacebookSDKException $e) {
echo 'Facebook SDK returned an error: ' . $e->getMessage();
exit;
}
$graphNode = $response->getGraphNode();
EDIT:
I see in your original question you state:
As I see the token is app id and app secret joined with pipe. "733163597544229|xxxxxxxxxxxxx9d14362xxxx3a6". This should work but does not work.
According to the docs, if you want to supply an access token as {app_id}|{client-token} (not sure what secret you're using here) you should append this to the URL, which is not in the URL you're using.
See example here: https://developers.facebook.com/docs/facebook-login/access-tokens#clienttokens
The URL they use is:
curl -i -X GET "https://graph.facebook.com/{your-user-id}/accounts?access_token={user-access-token}
So for you this be:
$response = $fb->get('https://graph.instagram.com/me/media?fields=media_url,media_type&access_token=733163597544229|{client_token}');
EDIT 2:
I managed to get your sample working so perhaps these screen shots will help:
PHP Code:
<?php
$accessToken="EAAJIZAj**************************************************************************************************************************************************************************ZD";
require_once __DIR__ . '/Facebook/autoload.php'; // change path as needed
//echo __DIR__ . '/Facebook/autoload.php';
$fb = new \Facebook\Facebook([
'app_id' => '642**********502',
'app_secret' => '0185*****************f743',
'default_graph_version' => 'v2.10',
'default_access_token' => "{$accessToken}"
]);
try {
// Get the \Facebook\GraphNodes\GraphUser object for the current user.
// If you provided a 'default_access_token', the '{access-token}' is optional.
$response = $fb->get('/me');
} 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;
}
$me = $response->getGraphUser();
echo 'Logged in as ' . $me->getName();
?>
I took the source code from https://github.com/facebookarchive/php-graph-sdk and copied the src/Facebook dir into my project. I amended the path location in my code
require_once __DIR__ . '/Facebook/autoload.php'; // change path as needed
//echo __DIR__ . '/Facebook/autoload.php'; //<< comment out everything else and check the path is correct with this.
Working code: (same as above) with successful output shown at the bottom of the screen shot.
If you need to get the app secret go to the apps settings to uncover it:
Seems you were right - the access token does have an expiry and I had to refresh mine since using it yesterday.
As far as I know this will probably not work to get the access token .
To get access token you need to implement the login with facebook in your app to get the access token . If your app is only used by limited user then you can get access token on this link https://developers.facebook.com/tools/explorer/ but if your app is used by wide range of user and each user has their own data then you need to implement oauth2 in your app

What to place in header to use the Facebook PHP web SDK properly?

I have a website with a working user signup and login system. Recently, I decided that I should add Facebook signup option. I wish to add a Facebook sign in button in the signup page and get their email, first name and last name on sign in so they don't have to insert their details.
I read though most of the Facebook developer help docs including:
https://developers.facebook.com/docs/php/howto/example_facebook_login
https://developers.facebook.com/docs/php/howto/example_retrieve_user_profile
Those links tells me how to let a user to login and how to get user data from their profile.
I understand how all those parts work but I don't know how to put them together. Can anyone please teach me how to do so? Thank you soooo much!
Ok, I finally found how to do it...
So, the first part is to set up files correctly. Here is how you do it:
Download the php sdk kit from fb (here)
Place the files in the "src" folder to your website main directory
The second part is to make the page where you want to link with fb:
Include the fb autoload page in your php page by doing
require_once 'autoload.php'; at the top of the file
Authorize fb to use your app by placing
$fb = new Facebook\Facebook([
'app_id' => 'XXXXXXXXXXXXXXXX',
'app_secret' => 'XXXXXXXXXXXXXXXXXXXXXXXXXX',
'default_graph_version' => 'v2.6',
]);
right after the code in 1st step
This is basicly how you should start your code to link with fb user profile. The following code is what i used to get a user's name, email and profile image.
<?php
session_start();
require_once 'Facebook/autoload.php';
$fb = new Facebook\Facebook([
'app_id' => 'XXXXXXXXXXXXXXXX',
'app_secret' => 'XXXXXXXXXXXXXXXXXXXXXXXXXX',
'default_graph_version' => 'v2.6',
]);
$helper = $fb->getRedirectLoginHelper();
$permissions = ['email']; // optional
try {
if (isset($_SESSION['facebook_access_token'])) {
$accessToken = $_SESSION['facebook_access_token'];
} else {
$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)) {
if (isset($_SESSION['facebook_access_token'])) {
$fb->setDefaultAccessToken($_SESSION['facebook_access_token']);
} else {
// getting short-lived access token
$_SESSION['facebook_access_token'] = (string) $accessToken;
// OAuth 2.0 client handler
$oAuth2Client = $fb->getOAuth2Client();
// Exchanges a short-lived access token for a long-lived one
$longLivedAccessToken = $oAuth2Client->getLongLivedAccessToken($_SESSION['facebook_access_token']);
$_SESSION['facebook_access_token'] = (string) $longLivedAccessToken;
// setting default access token to be used in script
$fb->setDefaultAccessToken($_SESSION['facebook_access_token']);
}
// redirect the user back to the same page if it has "code" GET variable
if (isset($_GET['code'])) {
header('Location: ./');
}
// getting basic info about user
try {
$profile_request = $fb->get('/me?fields=name,first_name,last_name,email');
$requestPicture = $fb->get('/me/picture?redirect=false&height=300');
$picture = $requestPicture->getGraphUser();
$profile = $profile_request->getGraphNode()->asArray();
} catch(Facebook\Exceptions\FacebookResponseException $e) {
// When Graph returns an error
echo 'Graph returned an error: ' . $e->getMessage();
session_destroy();
// redirecting user back to app login page
header("Location: ./");
exit;
} catch(Facebook\Exceptions\FacebookSDKException $e) {
// When validation fails or other local issues
echo 'Facebook SDK returned an error: ' . $e->getMessage();
exit;
}
// printing $profile array on the screen which holds the basic info about user
// Now you can redirect to another page and use the access token from $_SESSION['facebook_access_token']
} else {
// replace your website URL same as added in the developers.facebook.com/apps e.g. if you used http instead of https and you used non-www version or www version of your website then you must add the same here
$loginUrl = $helper->getLoginUrl('http://xxxxx', $permissions);
echo '<META HTTP-EQUIV="refresh" content="0;URL=' . $loginUrl . '">';}
?>
I wish that this could help anyone who is also stuck like me, bye~

Issue with facebook login and the php-sdk : callback page is loaded twice

So I posted a question the other day about a bug I was having while trying to implement facebook login using the facebook php-sdk on my site: After changing website domain, facebook login returns error "This authorization code has been used" . I've been getting an error message "This authorization code has been used" on my callback page (see below).
However, I set up a counter (see code below) using a session on the page to see how often it was being loaded. In fact, I found the page was being loaded twice each time I clicked the login button, and therefore the authorisation code is being loaded twice on two pages, resulting in the error. My problem now is solving why the page loads twice. If anyone can tell me I would be very grateful.
If it helps, here is my code.
/index.php
<?php
$fb = new Facebook\Facebook([
'app_id' => '{APP ID}',
'app_secret' => '{APP SECRET}',
'default_graph_version' => 'v2.1',
]);
$helper = $fb->getRedirectLoginHelper();
$permissions = ['email']; // Optional permissions
$fbLink = $helper->getLoginUrl('http://{domain}/facebook-callback.php', $permissions);
?>
Login
/facebook-callback.php
<?php
session_start();
//session counter (note: this increments 2 each time, when it should only increment 1)
if (isset($_SESSION["counter"])) {
$_SESSION["counter"] = $_SESSION["counter"]+1;
} else {
$_SESSION["counter"] = 0;
}
echo $_SESSION["counter"];
if (($loader = require_once '/var/www/html/vendor/autoload.php') == null) {
die('Vendor directory not found, Please run composer install.');
}
$fb = new Facebook\Facebook([
'app_id' => '{app id}',
'app_secret' => '{app secret}'
]);
$helper = $fb->getRedirectLoginHelper();
try {
$accessToken = $helper->getAccessToken();
} catch(Facebook\Exceptions\FacebookResponseException $e) {
echo 'Graph returned an error: ' . $e->getMessage();
} catch(Facebook\Exceptions\FacebookSDKException $e) {
echo 'Facebook SDK returned an error: ' . $e->getMessage();
}
...
//My code is longer than this but I get the error from the try statement above, so I did not think it necessary to add it here.
?>
Hope I've given enough information. I will praise whoever finds an answer to this, as I've been struggling with it for days now.

Codeigniter, facebook SDK 5, not working

I have followed this tutorial https://www.sammyk.me/upgrading-the-facebook-php-sdk-from-v4-to-v5 and so far I have managed to integrate the SDK into codeignitor etc
In my controller I have
function facebook(){
require_once __DIR__ . '/../vendor/autoload.php';
$fb = new Facebook\Facebook([
'app_id' => 'xxx',
'app_secret' => 'xxx',
'default_graph_version' => 'v2.5',
]);
$helper = $fb->getRedirectLoginHelper();
$permissions = ['email', 'user_posts']; // optional
$callback = 'http://localhost/project/api/index.php/social/facebook-callback';
$loginUrl = $helper->getLoginUrl($callback, $permissions);
echo $loginUrl;
}
And this generates a url for me. I then follow this link and it takes me to facebook I click ok then it goes to a redirect page.
On that page i have
function facebook_callback(){
require_once __DIR__ . '/../vendor/autoload.php';
$fb = new Facebook\Facebook([
'app_id' => 'xxx',
'app_secret' => 'xxx',
'default_graph_version' => 'v2.5',
]);
$helper = $fb->getRedirectLoginHelper();
try {
$accessToken = $helper->getAccessToken();
} catch(Facebook\Exceptions\FacebookSDKException $e) {
// There was an error communicating with Graph
echo $e->getMessage();
exit;
}
if (isset($accessToken)) {
// User authenticated your app!
// Save the access token to a session and redirect
$_SESSION['facebook_access_token'] = (string) $accessToken;
// Log them into your web framework here . . .
// Redirect here . . .
exit;
} elseif ($helper->getError()) {
// The user denied the request
// You could log this data . . .
var_dump($helper->getError());
var_dump($helper->getErrorCode());
var_dump($helper->getErrorReason());
var_dump($helper->getErrorDescription());
// You could display a message to the user
// being all like, "What? You don't like me?"
exit;
}
// If they've gotten this far, they shouldn't be here
http_response_code(400);
exit;
}
When I land on the page I get as an error
Cross-site request forgery validation failed. Required param "state" missing.
Why does this happen? Is this to do with the sessions? I have followed the tutorial and nothing seems to work. Any other documents I have found I have tried to for example session_start(); and Overwriting Persistent Data but to no avail!
Any point in the right direction will be very much appreciated. I have googled this loads and there are no clear answers.
Best regards
Ok answer found!
Pay special attention to the Overwriting Persistent Data in the tutorial! So it is a session related issue. Also doing it late at night is ill-advised.
What I missed was that you have to start the process from scratch, ie facebook route and get a brand new url link, then paste that link in the url, and you will be redirected to the facebook_callback. And you will then get the data you require.
Answer here incase someone else falls in the "what the hell is going on (when late at night trap)!"

Facebook OAuth, page not found

I've been trying to implement the Facebook OAuth SDK for the past couple of days but keep running into a weird broken link error.
I have followed their instructions on the facebook SDK and used this code for login.php (???? to censor app ID and secret)
$fb = new Facebook\Facebook ([
'app_id' => '????????????????',
'app_secret' => '????????????????',
'default_graph_version' => 'v.2.4'
]);
$helper = $fb->getRedirectLoginHelper();
$loginUrl = $helper->getLoginUrl('http://url.ca/login-callback.php');
This redirects to the login-callback.php file which is what Facebook recommends. Using their provided template code for login-callback.php, mine looks like this:
<?php
session_start();
require_once 'src/Facebook/autoload.php';
//Create the Facebook service
$fb = new Facebook\Facebook ([
'app_id' => '????????????????',
'app_secret' => '????????????????',
'default_graph_version' => 'v.2.4'
]);
$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']
}
?>
But after being redirected from login.php (clicking on the a href element), I arrive at this:
Sorry, this page isn't available
The link you followed may be broken, or the page may have been removed.
On the Facebook page, no prompt to login, no nothing. I've made my app public already and added this Url to the app as well as ensuring OAuth is enabled, but nothing seems to be working. Does anyone with experience using Facebook OAuth have any idea what's going on?
Is that 'v.2.4' a typo in your question?
The string used in the API should be v2.4 - if you have an extra '.' it's linking you to a URL similar to the real URL of the login dialog, but with an invalid version number in the path

Categories