I'm writing a facebook application in PHP with the facebook SDK.
The important parts in my code are:
$facebook = new Facebook(array(
'appId' => $ApplicationID,
'secret' => $ApplicationSecret,
'cookie' => true, // enable optional cookie support
));
$user = $facebook->getUser();
$post = $facebook->api('/' . $user . '/feed', 'post', array(
stuff
));
$_SESSION['finish'] = false;
$_SESSION['inside'] = 'yes';
$_SESSION['uid'] = $user;
$token = $facebook->getAccessToken();
echo 'Access token: ' .$token;
$_SESSION['friends'] = $facebook->api('/me/friends?access_token'.$token);
You can see I am echoing the access token.
At first, I haven't added the access_token into the query - I just added it for checking.
The problem is that the last like (with the /me/friends/) throws an exception:
OAuthException: An active access token must be used to query information about the current user.
Although I did a login, and the feed post did work (I checked at my wall, it's there). Then, my try catch block handles the exception by redirecting to the login link, this way:
catch(Exception $e) {
$login_url_params = array(
'scope' => 'stuff',
'fbconnect' => 1,
'redirect_uri' => $ApplicationURL
);
$login_url = $facebook->getLoginUrl($login_url_params);
//redirect to the login URL on facebook
echo ("EXCPETION! " . $e . "<script> top.location.href='" . $login_url . "'</script>");
exit();
}
The code writing the exception is obviously only for debugging purposes.
Well, the first time I run the application a similar code is executed by a if(!$user) condition. Then it asks for my permission and I give it. Then, again, it says the access token is invalid (but does post to my wall).
Please note that I've compared the access_tokens, and even after removing the application and doing it all again - it stayed the same.
This is very awkward behavior and I fail to understand it. May anyone please shred some light on this?
Edit: For some weird reason, the token doesn't change even after going to a different user. But the post on the wall is still made... (And the exception thrown when accessing the friends list)
For some weird reason, the token doesn't change even after going to a different user. But the post on the wall is still made... (And the exception thrown when accessing the friends list)
That sounds to me as if you don’t actually have a user currently logged in, so the SDK is just using your app access token, which is always the default token it will use before it receives another, more “specific” one.
What format does your access token have – does is look something like your_app_id|your_app_secret or your_app_id|some_random_characters? If it’s starting with your app id, it’s most definitively an app access token.
Related
I have been trying for several days now to successfully post to a client's Facebook Page wall from their website. I need to be able to do this without having a user logged in, which I was able to achieve with an extended access token generated by going to the URL provided in the docs.
What I am trying to do is to fetch an extended token using the PHP SDK as in this question - Facebook PHP SDK: getting "long-lived" access token now that "offline_access" is deprecated, however I receive the following error:
(#200) The user hasn't authorized the application to perform this action
The debug of the auth token generated by the Graph API Explorer shows myself as the User and includes the needed manage_pages and status_update scopes. However, if I run me/accounts, the perms array does not list these under the data for the page in question - not sure if this is relevant.
Here is the code that I have attempted to use:
$facebook = new Facebook(array('appId' => 'xxxxxxx', 'secret' => 'xxxxxx'));
$pageID = 'xxxxxxxx';
$facebook->setExtendedAccessToken();
$accessToken = $facebook->getAccessToken();
try {
$page_info = $facebook->api("/$pageID?fields=access_token");
print_r ($page_info);
} catch (FacebookApiException $e) {
echo $e->getMessage();
}
if( !empty($accessToken) ) {
$args = array(
'access_token' => $accessToken,
'message' => "Catch phrase!"
);
$facebook->api("/$pageID/feed","post",$args);
} else {
// Handle error
}
UPDATE
I found that if I echoed the output of getAccessToken() the result was the app ID and the secret separated by an | - is this what I should be receiving? Seems odd to me since all of the other tokens I have seen are random and much longer.
ANY help at all would be appreciated, I have wasted so much time on this so far. It just seems to work for everyone else.
UPDATE 2
Hi Warren! Looks like you're new around these parts, welcome! Thanks for your research into this, do I need to save these tokens into a DB table and check to see if they are expired every time I try to post? I am ONLY posting to a Page as the Page, apparently this requires the Page access_token rather than what I am assuming is the USER access_token. I believe I also read somewhere that the Page access token never expires, although it changes if I refresh the Graph API Explorer page or request a new user token. Very puzzling.. do not know if I even need to deal with getting new tokens in this app or just use a Page access_token that appears to work?
Also just looking at the base_facebook.php file and the following function:
/**
* Returns the access token that should be used for logged out
* users when no authorization code is available.
*
* #return string The application access token, useful for gathering
* public information about users and applications.
*/
protected function getApplicationAccessToken() {
return $this->appId.'|'.$this->appSecret;
}
Shows what you are experiencing the function setExtendedAccessToken() calls getAccessToken() which calls the function above to do the following inside setExtendedAccessToken:
$access_token_response = $this->_oauthRequest(
$this->getUrl('graph', '/oauth/access_token'),
$params = array(
'client_id' => $this->getAppId(),
'client_secret' => $this->getAppSecret(),
'grant_type' => 'fb_exchange_token',
'fb_exchange_token' => $this->getAccessToken(),
)
);
the return of this function is then {"error":{"message":"No user access token specified","type":"OAuthException","code":1}} but because there is no access_token the function just returns false
the fb_exchange_token can not be the app id and app secret combined.
I have done some testing and what I have found out is if you get the user to login, you can get there access token. If you pass this token into setAccessToken then run setExtendedToken. If you then save the toke by running getAccessToken you can use this token later when the user is logged out.
$facebook->setAccessToken($facebook->getAccessToken());
$facebook->setExtendedAccessToken();
$access_token = $facebook->getAccessToken(); // save this for later use
You need to get the user to login to ask them for permission to get access to there account. If you need to get access to a facebook page make sure they are an admin and ask for the manage_page permission.
Hope this helps
From what I have found so far the extended token that is returned when the user is logged in does not expire as you do not get back a unix timestamp so you would have no way of knowing when it expires.
This is what I have done in my application.
Request the user to login to facebook and except the access permissions. Use getAccessToken to get the current access token. With this I pass into getExtendedAccessToken then run getAccessToken again to finally get the extended access token which I store in a database for later use.
$facebook = new Facebook(array(
'appId' => 'YOURAPPID',
'secret' => 'YOURSECRET',
));
$params = array(
'scope'=>'publish_stream,manage_pages'
);
$loginUrl = $facebook->getLoginUrl($params); // Use this to request them to login in then when they are do the following you will need them to return to your app
$facebook = new Facebook(array(
'appId' => 'YOURAPPID',
'secret' => 'YOURSECRET',
));
$facebook->setAccessToken($facebook->getAccessToken());
$facebook->setExtendedAccessToken();
$access_token = $facebook->getAccessToken(); // store $access_token for later use
I made this PHP script that fetches messages to be posted at regular intervals to a Facebook Page that I administer.
My script is working fine, but depends on me as a user being logged into Facebook. I would like this script to run as a cron job so i fear the script will fail to work if i'm logged out.
How can i make it work even if i'm not logged into Facebook?
Note that I created a Facebook application as requested to be able to use the Facebook api. Is there a way to post as the Facebook application perhaps?
Here is my code, in case it helps.
require_once('config.inc.php');
require '_classes/facebook-php-sdk/src/facebook.php';
$homeurl = 'http://domain.com/to-facebook/index.php';
$post_url = '/'.PAGEID.'/feed';
// The message
$msg_body = array(
'message' => 'hello world',
);
// Post to Facebook
$facebook = new Facebook(array(
'appId' => FB_APP_ID,
'secret' => FB_APP_SECRET,
));
// Get User ID
$fbuser = $facebook->getUser();
if ($fbuser) {
try {
$postResult = $facebook->api($post_url, 'post', $msg_body );
} catch (FacebookApiException $e) {
echo $e->getMessage();
}
}else{
// I would like never to come to this point...
$loginUrl = $facebook->getLoginUrl(array('redirect_uri'=>$homeurl,'scope'=>'publish_stream,manage_pages,publish_actions,status_update,offline_access'));
header('Location: ' . $loginUrl);
}
if($postResult)
{
echo '<h1>Your message is posted on your facebook wall.</h1>';
}
* update *
I tried the cronjob and unfortunately, after a while I had the "Error validating access token: Session has expired at unix time" message. I'm puzzled. What am i doing wrong?
For sites connected to your app:
When you have the app get permission to manage_pages, you run an api with your user token which gives you the access tokens of all your pages. These tokens can last forever.
For users authorizing the app:
You can make the access_token last longer. The user would need to log in to refresh the extended token however. Read up more about "Facebook Extend Token".
There used to be a permissin that gave the app the ability to reuse the token forever, but it's no longer available. The best you can do nowadays is to simply run the api to extend the token each time the user log in to your app.
You can easy use CURL for this. Google something like that, "CURL login, CURL facebook login"
**update **
I tried the cronjob and unfortunately, after a while I had the "Error validating access token: Session has expired at unix time" message. I'm puzzled. What am i doing wrong?
I seem to have found a solution based on this answer Facebook Access Token for Pages .
It explains how to get an access_token to a specific page for your FB application.
I obtained it, then adapted my code. I tested it using a browser in which i'm not logged into facebook with, and it works.
Here is the updated script in case it helps.
$msg_body = array(
'message' => $message->message.' v/ #'.$message->author,
'access_token' => FB_ACCESS_TOKEN
);
try {
$postResult = $facebook->api($post_url, 'post', $msg_body );
} catch (FacebookApiException $e) {
echo $e->getMessage();
}
if($postResult)
{
echo '<h1>Your message is posted on your facebook wall.</h1>';
print_r($msg_body);
}
I'll run the cronjob for a few days and will get back to you if it proves not to work reliably.
I have posted this question in Facebook Developer Group but no-one could give a compete answer. I have a Facebook application which uses server side authentication. The code looks like this:
$config = array();
$config['appId'] = $fbconfig['appid'];
$config['secret'] = $fbconfig['secret'];
$config['fileUpload'] = false; // optional
$facebook = new Facebook($config);
//Facebook Authentication part
$mobile = false;
$code = false;
if (isset($_GET["code"]) && !empty($_GET["code"]) && strlen($_GET["code"])>1){
$code = trim($_GET["code"]);
}
//MOB VAR
if (isset($_REQUEST['mob']) && !empty($_REQUEST['mob']))
{
mobile = true;
}else{
}
if ($mobile){
$loginUrl = $facebook->getLoginUrl(
array(
'redirect_uri' => $fbconfig['baseUrl'].$loginpart,
'scope' => 'email,user_likes'
)
);
$token_url = "https://graph.facebook.com/oauth/access_token?client_id=".APP_ID."&redirect_uri=".urlencode($fbconfig['baseUrl'].$loginpart)."&client_secret=".$fbconfig['secret']."&code=".$code;
}else{
$loginUrl = $facebook->getLoginUrl(
array(
'redirect_uri' => $fbconfig['appBaseUrl'].$loginpart,
'scope' => 'email,user_likes'
)
);
$token_url = "https://graph.facebook.com/oauth/access_token?client_id=".APP_ID."&redirect_uri=".urlencode($fbconfig['appBaseUrl'].$loginpart)."&client_secret=".$fbconfig['secret']."&code=".$code;
}
if ((!isset($_GET['code']) || empty($_GET['code']) ) ) {
echo "<script type='text/javascript'>top.location.href = '$loginUrl';</script>";
exit;
} else{
if ($code){
$response = file_get_contents($token_url);
$params = null;
parse_str($response, $params);
$access_token = $sessionKey = $AccessToken = $params['access_token'];
if(isset($AccessToken) && !empty($AccessToken)){
if(isset($params['expires'])){
$ExpDate = $params['expires'];
I shortened the code not to annoy You.
THE PROBLEM
For some reason the code returns short $ExpDate which can be from 3000 seconds to 7000 seconds. This happens not for all users but to 10%-15% of them.
What I have tried
Despite the fact Facebook should return long-living access_token I
tried to exchange it with the /oauth/access_token? url. No
result:it returns the same expire time.
I tried to catch the $SERVER['HTTP_USER_AGENT'] to find out what in
common do the users have with short-living access_tokens. No
result:everything is different(they can be from mobile device,
desktop, IOS native Facebook app....)
I changed my settings from privacy settings to every possible version, installed, removed application many times trying to reproduce the situation. No result: for me it works perfectly.
I saved the code of the user and tried to get the access_token manually. I was not able to do that as I had forgotten that the codes can be used only one time.
How can You Guys Help
If someone has the same authentication method please check your database. Do you have the same problem?
If someone has an Idea why could this happen please help to find the reason.
If we find out that this is a bug we can create a bug report on Facebook
Thank you.
The behavior you're seeing is correct.
You're currently exchanging your code for a short-lived access token - which is required. Since Facebook removed the offline_access permission, the only way to get a longer lived access token is to exchange your short-lived access token for a long-lived access token.
Please see the article on removal of offline_access specifically Scenario 4 which relates to OAuth. This is where they introduced the concept of long-lived access tokens and tell you how to get one.
The short story to accomplish this is to take your short-lived access token - say AQADEADBEEF and GET this...
https://graph.facebook.com/oauth/access_token?grant_type=fb_exchange_token&client_id={client_id}&client_secret={client_secret}&fb_exchange_token=AQADEADBEEF
Notice the 4 parameters grant_type, client_id, client_secret, and fb_exchange_token. The URL is the same as when you gained your original access token, but the parameters are a bit different. Insert your client_id and client_secret as appropriate
You'll then get an access token with a much longer expiration time - 90 days I believe. Facebook is quite ambiguous about the length of any access token. You'll only know the expiration when you get it. The long-lived access token will still expire and Facebook currently offers NO way to renew it.
I have to post on a users wall when he is offline. I went through number of posting and checked the code written below seems ok and also not throwing error and complete successful yet I am unable to see posting on users wall. Pl help.
$facebook = new Facebook(
array(
'appId' => "446262598768110",
'secret' => "<REMOVED>",
)
);
$facebook->setAccessToken("<REMOVED>");
//create message with token gained before
echo " lets try posting";
$access_token = $facebook->getAccessToken();
$user_id = $facebook->getUser();
echo "\ndone3..... $access_token.-----.$user_id.----new\n";
$post = array(
'message' => 'This message is posted with access token - ' . date('Y-m-d H:i:s')
);
//and make the request
$res = $facebook->api("/me/feed", 'GET', $post); //have tried both Post and Get method but result remain same
offline access was removed quite a few months ago. also, you do have to "POST" to facebook graph, everytime you want to publish something.
without seeing the result of the facebook graph, it's kind of impossible to help you at all.
nevertheless: double check, that you're using the correct access token. you have to extend the short lived access tokens by your own (https://developers.facebook.com/docs/howtos/login/extending-tokens/), so that the access token itself is still valid when you want to post by cron-job.
if you're trying to post by using the app access token, you can't use "/me/feed" at all.
I have a Facebook app that I want to use to post on my customer's Facebook Page Walls on their behalf. I have it setup now so that when they authenticate my app I get the Access token, but when I go to post to the wall I am getting the following error: "OAuthException: Error validating access token: The session is invalid because the user logged out."
How can I post from my script without being logged in?
Here is my code:
include_once('fb-php-sdk/src/facebook.php');
$facebook = new Facebook(array(
'appId' => 'XXX',
'secret' => 'XXX',
));
try {
$page_id = '215133535279290'; //page id of the customer's facebook page
$args = array(
'access_token' => 'XXX', //access token received when user authenticated app
'message' => 'A test message'
);
$post_id = $facebook->api("/$page_id/feed","post",$args);
} catch (FacebookApiException $e) {
echo "Error:" . $e;
}
The new facebook API has what is called an extended access token (it replaces offline access: https://developers.facebook.com/roadmap/offline-access-removal/ I think) which I believe lasts upto 60 days (or something like that). To use it simply get the access token when the logs in through your website:
$token = $facebook->getAccessToken();
Save it to Db and use this token later:
$facebook = new Facebook();
$facebook->setAccessToken($accessTokenFromDB);
Then you should be able to continue as though the user is logged in.
As for the user being logged out part, make sure you are using the latest version of the API and not an old version and also make sure the stuff under the "Scenario 2: If you have been previously requesting offline_access - updated 4/30/2012" heading of the page I linked.
You could carry on using offline_access until 3rd of October, but then why if it's being turned off for real in 2 months time and would have to rewrite your code.
Get the publish_stream extended permission. Once you have this permission you can post feed stories using your app access token while the user is offline. There is no need for offline_access permissions or saving and using a user access token in this scenario.