Facebook Access Tokens - php

I am trying to get the Facebook access tokens useing the bellow code:
I did create my own function before but it came back with the same error and i can't work out what is the problem.
function getAccessToken(){
$app_id = FB_APP_ID;
$app_secret = FB_SECRET_ID;
$my_url = FB_PAGE_URL;
$code = $_REQUEST["code"];
if(empty($code)) {
$_SESSION['state'] = md5(uniqid(rand(), TRUE)); //CSRF protection
$dialog_url = "https://www.facebook.com/dialog/oauth?client_id="
. $app_id . "&redirect_uri=" . urlencode($my_url) . "&state="
. $_SESSION['state'];
echo("<script> top.location.href='" . $dialog_url . "'</script>");
}
if($_REQUEST['state'] == $_SESSION['state']) {
$token_url = "https://graph.facebook.com/oauth/access_token?"
. "client_id=" . $app_id . "&redirect_uri=" . urlencode($my_url)
. "&client_secret=" . $app_secret . "&code=" . $code;
$response = file_get_contents($token_url);
$params = null;
parse_str($response, $params);
$graph_url = "https://graph.facebook.com/me?access_token="
. $params['access_token'];
$user = json_decode(file_get_contents($graph_url));
echo("Hello " . $user->name);
}
else {
echo("The state does not match. You may be a victim of CSRF.");
}
}
Taken from Server-Side Authentication but i keep getting this error:
Warning: file_get_contents(https://graph.facebook.com/oauth/access_token?
client_id=ID HERE&redirect_uri=URLHERE&cli
ent_secret=SECRECT&code=AQCI5rNgw9zCPHWGozeT59asg7_022u5tVc5XSef49BiX
IaF5_MAMqFwsqOAquUHgjOu_99ONwUV6IC7k-jV6DsWf9ni3jm8t59aHCBp1jrFaDthPbIKLNLQ-
fZgB5MLh1le5BAPKj_l57jhTLTBfOdxRU30mFCMYzMch8MYFpCmJ9GrjSSGwt0OKb_LNqMoRf8) [function.file-
get-contents]: failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request
Anyone know the fix?

It might be a problem with the file_get_contents method, since the url you are constructing looks ok.
If you search for "facebook file_get_contents failed to open stream" you'll get quite a few results on the matter, a lot right here on stack overflow.
It looks like a HTTPS problem with the file_get_contents as states in this thread: [function.file-get-contents]: failed to open stream.
Maybe try some other method of issuing http requests? Maybe curl?
Just to test things, try to use curl from the command line with the same url you tried with the php script and see what you get.

Looking at the request response, you haven't defined your Facebook application settings.
You're using FB_APP_ID, FB_SECRET_ID and FB_PAGE_URL when you request a token, but in the response I can see these are defined as: "ID HERE", "SECRECT" and "URLHERE" respectively.

I have managed to fix this issue using the PHP SDK,
and after a long battle with the SDK to get it to do what i wanted.
I did also open another question with the same idea but with another problem.
This problem has now been solved.
Check out this question for the answer to this problem: Facebook Access Token Server Side Authentication

Related

Accessing one's profile using Facebook's Php Sdk & Graph API

I wanted to create a small webpage in my website that shows all the activities(statuses) of ONLY my facebook account if anyone visits the page.
So I went over to the facebook developers page and downloaded the PHP SDK and started experimenting. But soon I discovered the access_token thing. This literally wasted so much of my time. Since these access token only lasted for a little time and extended access token last only for like 60 days(I don't want to keep updating them a lot). I searched everywhere, but to no avail. I couldn't find a way in which I could access only MY facebook posts with FB's PHP SDK & Graph API. Can you guys help me out with this?
You need to have YOUR access_token to fetch the feeds from YOUR account. There's no other token you can use accept this token.
So it would be easier for you if you have a backend server (which I guess you must be having). You can write a small script, where you can call the facebook login and get the normal access token, then extend it to 60 days validity and save it to your database with its expiration date. And before it's getting expired just run the script and the token will be refreshed. And your main website will always fetch the token from the database. Simple enough. I don't think there's anything else you can do.
If you are interested in such a script, I can help you with it-
$code = $_REQUEST["code"];
if(empty($code))
{
$dialog_url= "http://www.facebook.com/dialog/oauth?"
. "client_id=" . $APP_ID
. "&redirect_uri=" . urlencode( $post_login_url);
echo("<script>top.location.href='" . $dialog_url . "'</script>");
}
else
{
// access token
$token_url = "https://graph.facebook.com/oauth/access_token?"
. "client_id=" . $APP_ID
. "&redirect_uri=" . urlencode( $post_login_url)
. "&client_secret=" . $APP_SECRET
. "&code=" . $_REQUEST["code"];
$response1 = file_get_contents($token_url);
$params = null;
parse_str($response1, $params);
$access_token = $params['access_token'];
// extended token
$extended_token_url = "https://graph.facebook.com/oauth/access_token?"
. "grant_type=fb_exchange_token"
. "&client_id=" . $APP_ID
. "&client_secret=" . $APP_SECRET
. "&fb_exchange_token=" . $access_token;
$response2 = file_get_contents($extended_token_url);
$response2 = json_decode($response2);
$extended_access_token = $params['access_token']; // save this to the database with the expiration date(current date+60days)
}

Facebook Login Error: failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request

I'm trying to follow the example to create a server side login to Facebook from here, but with no luck. In step 7, when I try to exchange the code with a token and store it in a session for later use, I always get this error :
file_get_contents(): failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request
I know this already asked many times, but I still unable to solve this, as per this question, I tried using cURL, but it still does not work, it just returned false.
Other question told me to use the PHP SDK, but I don't know which method to use. So I'm completely lost in here.
Here's my code for calling the login form :
Login with Facebook
where LOGIN_URL is defined as :
define("LOGIN_URL", $facebook->getLoginUrl(array("redirect_uri" => APP_URL . "fb_login")));
in fb_login, I have this code :
$app->get("/fb_login", function() use($app, $facebook)
{
$code = $_REQUEST["code"];
$token_url = "https://graph.facebook.com/oauth/access_token?"
. "client_id=" . APP_ID . "&redirect_uri=" . APP_URL . $_SESSION["request_uri"] // Previous URL
. "&client_secret=" . APP_SECRET . "&code=" . $code;
$response = file_get_contents($token_url); // Doesn't work
$params = null;
parse_str($response, $params);
$_SESSION["access_token"] = $params["access_token"];
// Let's try with cURL...
// $ch = curl_init();
// curl_setopt($ch, CURLOPT_URL, $token_url);
// curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// $output = curl_exec($ch); // Returns false
// curl_close($ch);
$graph_url = "https://graph.facebook.com/me?access_token="
. $params["access_token"];
$user = json_decode(file_get_contents($graph_url));
echo("Hello " . $user->name);
var_dump($code); die();
});
Any help is appreciated. Thanks before.
To directly answer the question, the problem is most likely that you do not urlencode (make safe for URL transport) the redirect URL. The fastest fix will be:
$token_url = "https://graph.facebook.com/oauth/access_token?"
. "client_id=" . APP_ID . "&redirect_uri=" . urlencode(APP_URL . $_SESSION["request_uri"])
. "&client_secret=" . APP_SECRET . "&code=" . $code;
However, I would also suggest that you look at the Facebook SDK as this does this all for you.
Have you checked the documentation on the PHP SDK... Its quite extensive and nice.. You just need to setup your Facebook SDK as following
$facebook = new Facebook(array(
'appId' => 'your app id',
'secret'=> 'your app secret'));
Then you can retrieve login URL as
$loginURL = $facebook->loginUrl(array(
'scope' => 'read_stream',
'redirect_uri' => 'http://yourdomain/path/to/page'));
And moreover it, SDK might give you better description about your error which is handled by it which can be due to mismatch in redirect URI with app's configurations or error in app ID or secret or entirely different thing. Download SDK from here

$_GET array is always empty after facebook app authentication

I am trying to play around with authentication for an app I am working on atm. The app will be tab based. I am now strugling with an infinite loop while trying to authenticate the app. The authentication procces is like this:
if (!isset($_REQUEST["code"])) {
$_SESSION['state'] = md5(uniqid(rand(), TRUE)); //CSRF protection
$dialog_url = "http://www.facebook.com/dialog/oauth?client_id="
. $appId . "&redirect_uri=" . urlencode($redirectUri) . "&state="
. $_SESSION['state'];
echo("<script> top.location.href='" . $dialog_url . "'</script>");
exit;
}
if ($_REQUEST['state'] == $_SESSION['state']) {
$code = $_GET["code"];
$token_url = "https://graph.facebook.com/oauth/access_token?"
. "client_id=" . $appId . "&redirect_uri=" . urlencode($redirectUri)
. "&client_secret=" . $appSecret . "&code=" . $code;
$response = #file_get_contents($token_url);
$params = null;
parse_str($response, $params);
$graph_url = "https://graph.facebook.com/me?access_token="
. $params['access_token'];
$user = json_decode(file_get_contents($graph_url));
echo("Hello " . $user->name);
} else {
echo("The state does not match. You may be a victim of CSRF.");
}
The $redirectUri is now set to "http://www.facebook.com/pages/DummyPage/PAGE_ID?sk=app_APP_ID" but once I am redirected back, after the authentication, I am unable to read $_GET or $_REQUEST arrays because they are empty (even though I can see that the url I get after auth. has "code", "state" etc. in it). This will result in infinite loop, because I am stuck in the first if statement.
What is interesting here is that when I change the $redirectUri to the url where my app sits in - right now I am testing it on localhost - so I put in "http://localhost/test/index.php" - the infinite loop wont happen because I am redirected outside facebook and I can read from $_GET array.
I need to stay on facebook when authenticating. Do you guys know how to get around this problem?
Please use the Facebook PHP SDK for things that you're trying right now.
It makes the thing a lot easier and you probably get to your goal in less time.
OR
if you want to do manually and interested in learning the internals, you need to check page tab authentication and signed request

Why is my test application in an endless redirect loop?

I am using the PHP SDK Version 3.1.1 in order to make a simple call to the Graph API. I am running it locally at http://local.fb-sandbox. The facebook application settings have the site URL set to http://local.fb-sandbox/.
I am redirected to the facebook login page and then to the page requesting my permission when I go to http://local.fb-sandbox but the application then goes into a redirect loop between a URL like:
http://local.fb-sandbox/?state=e9c091bb61afe08139af4e3b153a1e9e&code=AQBDJ4yMWVOIrukx6nRkxhNbnPH9nX6OvuqOWhVJEAgLkq6Lz27iq_-B6AIAGQ_cOpBIZktCPLLs_G5Hpt8QO5PRhDUN8l-Yu3JuT0YTzwVQiAqBlgutgia60lRT-ZzE3IHguStHq4gtuPQYJh423TBer-mB8BsqERvNsoF1L4NNe90WAWU8--MFAU3Oc4eeXyI#_=_
and
https://www.facebook.com/dialog/oauth?client_id=375741229103324&redirect_uri=http%3A%2F%2Flocal.fb-sandbox%2F%3Fstate%3Dccd13778febb68d3eb1f4763a99b2ace%26code%3DAQBFegtkch4m34-2F9KMKgScrPhWzI0qeKJlvnM6uAD81BYm2xakv0S7DEbUrNwlECrgth5-YHdT8IR_vCBzW29QMh3ecOiiEk7P03wQG2V2gaxAUsMqOOZvTl_Oq3SefiLn9BvBAPQSGXQdRSZBVdsUqDT1aZ430Lcx8Ic6axaHSyHwlkkNK5EjRhYdkjYYz0YmENk64kRf4tvmX4WrH6f4&state=19a3862962dd0422628eb7c28a832380&scope=email%2Cread_stream%2Cpublish_stream%2Cuser_photos%2Cuser_videos&fbconnect=1#_=_
I have a call to session_start() at the top of my script and have tried both with and without it. The PHP cookie is being set fine.
I've seen a lot of similar questions on here regarding this redirection loop but none of the suggested answers resolved it and they are all quite old. Should this work on localhost? AM I missing an application setting in the app settings on Facebook?
UPDATE
So it seems that if you use the code from here: http://developers.facebook.com/docs/authentication/ then it works. The php-sdk example on github completely ignores this and does not include the fact that you need to check whether 'code' is set and generate your own CSRF token. You then need to make a call to grab an access token before being able to make a call to the Graph API.
Also, the SDK's getLoginURL() method returns an https:// URL which doesn't seem to work. If I craft my own URL then it works.
WORKING CODE:
if(empty($code)) {
$_SESSION['state'] = md5(uniqid(rand(), TRUE));
$login_url_params = array(
'scope' => 'email,read_stream,publish_stream,user_photos,user_videos',
'fbconnect' => 1,
'redirect_uri' => 'http://local.fb-sandbox/',
'state'=>$_SESSION['state']
); //using this array via the sdk does not work
$dialog_url = "http://www.facebook.com/dialog/oauth?client_id="
. $app_id . "&redirect_uri=" . urlencode($my_url) . "&state="
. $_SESSION['state']; //this url works
//var_dump($dialog_url);echo "<br />";
$login_url = $facebook->getLoginUrl();
//var_dump($login_url);
header("Location:{$dialog_url}");//works
//header("Location:{$login_url}");//does not work
exit;
}
if($_REQUEST['state'] == $_SESSION['state']) {
$token_url = "https://graph.facebook.com/oauth/access_token?"
. "client_id=" . $app_id . "&redirect_uri=" . urlencode($my_url)
. "&client_secret=" . $app_secret . "&code=" . $code;
$aContext = array(
'http' => array(
'proxy' => 'tcp://xxxx0:80',
'request_fulluri' => true,
),
);
$cxContext = stream_context_create($aContext);
$response = file_get_contents($token_url, FALSE, $cxContext);
$params = null;
parse_str($response, $params);
$graph_url = "https://graph.facebook.com/me?access_token=" . $params['access_token'];
$user = json_decode(file_get_contents($graph_url, FALSE, $cxContext));
//var_dump($user);exit;
}
//var_dump($user);exit;
return $app->render('test.html',array('myvar', $user));
exit();
Note that I am going through a proxy so have to set a context for the file_get_contents() calls.
If anyone can convert my code to use the proper SDK methods and get it working (bearing in mind that I need it to work behind a proxy) then you'll get the bounty.
Many of the various server-side Facebook SDKs do not handle authentication in accordance with the documentation and recommended practices Facebook has shared over the last 3 or 4 months. You found one good example of this in how the PHP SDK uses (or doesn't use) the code parameter. There are other examples such SDKs directly reading the Facebook cookies, something Facebook engineers tell developers they should not do since the cookies are just "an implementation detail" and not something developers outside of Facebook should be building dependencies on.
I am not sure where you got that code in your working code example, but I couldn't find any support for including parameters such as fbconnect=1
So given that the SDK is not implementing authentication as per Facebook recommendations and documentation, and that Facebook has provided a complete PHP implementation in their documentation, I recommend you just use the version Facebook provides, copy and pasted here for your reference from this page http://developers.facebook.com/docs/authentication/ :
<?php
$app_id = "YOUR_APP_ID";
$app_secret = "YOUR_APP_SECRET";
$my_url = "YOUR_URL";
session_start();
$code = $_REQUEST["code"];
if(empty($code)) {
$_SESSION['state'] = md5(uniqid(rand(), TRUE)); //CSRF protection
$dialog_url = "http://www.facebook.com/dialog/oauth?client_id="
. $app_id . "&redirect_uri=" . urlencode($my_url) . "&state="
. $_SESSION['state'];
echo("<script> top.location.href='" . $dialog_url . "'</script>");
}
if($_REQUEST['state'] == $_SESSION['state']) {
$token_url = "https://graph.facebook.com/oauth/access_token?"
. "client_id=" . $app_id . "&redirect_uri=" . urlencode($my_url)
. "&client_secret=" . $app_secret . "&code=" . $code;
$response = #file_get_contents($token_url);
$params = null;
parse_str($response, $params);
$graph_url = "https://graph.facebook.com/me?access_token="
. $params['access_token'];
$user = json_decode(file_get_contents($graph_url));
echo("Hello " . $user->name);
}
else {
echo("The state does not match. You may be a victim of CSRF.");
}
?>
There are several problems with this.
Your redirect_uri should be like http://local.fb-sandbox/ . There must be a trailing slash at the end - both in the code and the facebook app settings in developers.facebook.com.
You have to user uurlencode on the redirect_uri.
Don't use $_SERVER['REQUEST_URI'] in the redirect_uri. Find a way to add any parameters you need by processing app_data or adding them depending on your user journey.
As a start replace this line:
'redirect_uri' => urlencode('http://local.fb-sandbox/'),
and experiment with adding parameters later.

How to get user's data programatically, via facebook authentication?

I am able to manually get the user's data, but not programatically.
Using the server side code, as it is, from - https://developers.facebook.com/docs/authentication/
<?php
$app_id = "MY_APP_ID";
$app_secret = "MY_APP_SECRET";
$my_url = "ADDRESS_OF_CURRENT_PAGE";
session_start();
$code = $_REQUEST["code"];
if(empty($code)) {
$_SESSION['state'] = md5(uniqid(rand(), TRUE)); //CSRF protection
$dialog_url = "https://www.facebook.com/dialog/oauth?client_id="
. $app_id . "&redirect_uri=" . urlencode($my_url) . "&state="
. $_SESSION['state'];
echo("<script> top.location.href='" . $dialog_url . "'</script>");
}
if($_REQUEST['state'] == $_SESSION['state']) {
$token_url = "https://graph.facebook.com/oauth/access_token?"
. "client_id=" . $app_id . "&redirect_uri=" . urlencode($my_url)
. "&client_secret=" . $app_secret . "&code=" . $code;
$response = #file_get_contents($token_url);
$params = null;
parse_str($response, $params);
$graph_url = "https://graph.facebook.com/me?access_token="
. $params['access_token'];
$user = json_decode(file_get_contents($graph_url));
echo("Hello " . $user->name);
}
else {
echo("The state does not match. You may be a victim of CSRF.");
}
?>
The output is only Hello, the user name does not show up!
I think the problem is with the file_get_contents(), as echo-ing $response has no output, where as $token_url has the appropriate value.
$response = #file_get_contents($token_url);
PHP version = 5.2.9
Error reporting is off, but including this in the code - error_reporting(E_ALL); gives no output.
UPDATE - So, I tried this after 6 months, and it worked. The only thing that has changed since then is my hosting. I was using HostBig before. Lesson - Don't depend on $1/month hosting services, they can't be trusted.
Are you trying to run this code from localhost? If yes, then it wont work. While registering your app on facebook, you must have entered your app's website. Upload the script on server, edit your app_id, secret and the url of script. Then try executing it.
If it doesn't work even then, then try echoing your $dialog_url and $token_url. First manually copy paste your $dialog_url in browser and see what error it gives. If it asks for authentication, authenticate your app. It will get you back to the page. Then try running your $token_url in browser. It will give you the exact response what the server is providing you with.
So, I tried this after 6 months, and it worked. The only thing that has changed since then is my hosting. I was using HostBig before.
There was probably something wrong with HostBig's PHP configuration, which disabled the file_get_contents().
UPDATE - I talked to the HostBig guys, and they told me that they have disabled allow_url_fopen, for reasons of safety, and suggested cURL as the safer alternative.

Categories