Facebook test users (created for an app) are working different in some ways than normal users. Ie. they can't like fanpages, so you can't test if "create.edge" listener is setup correctly.
Is there a way to detect if user authenticated to app is test user? It would be useful to implement fake version of dialogs, that test user can't use (ie. liking a fanpage).
My research:
I have checked signed_request passed to app and it looks same for test users as for normal users.
I have checked graph.facebook.com/[test user id] and it also look normal.
You cannot check if user is a test user basing on his Graph API details. Similarly, you cannot check if user like’s a specific page. You can however check your page_id against user liked pages list. So in order to determine if given user_id is a regular or a test user, you’d have to check it against the application test user list:
https://graph.facebook.com/APP_ID/accounts/test-users?access_token=APP_ID|APP_SECRET
So the flow would be like this:
Authenticate user
Get his ./likes list
Find your page_id and exit successful
Get your APP ./accounts/test-users list
Find given user_id and exit successful
Exit with failure -- require user to like your page.
That’s one extra call, but you can safely cache results for performance gains, since test users cannot be converted to regular users. I’d advice to cache the "likes" check for some time as well, but YMMV.
Is Facebook user is test you can change name and password, else return error code (#200) You do not have sufficient permissions to perform this action
**My solution: **
public function isTestUser($facebook_uid){
FacebookSession::setDefaultApplication(config_item('APP_ID'), config_item('APP_SECRET'));
$session = FacebookSession::newAppSession();
try {
$session->validate();
} catch (FacebookRequestException $ex) {
// Session not valid, Graph API returned an exception with the reason.
return FALSE;
} catch (\Exception $ex) {
// Graph API returned info, but it may mismatch the current app or have expired.
return FALSE;
}
$request = new FacebookRequest(
$session,
'POST',
'/'.facebook_uid,
array(
'password' => 'password',
'name' => 'Test Username'
)
);
try {
$response = $request->execute();
} catch (FacebookRequestException $ex) {
// (#200) You do not have sufficient permissions to perform this action
// (#100) Invalid password
// (#100) Invalid name
return ($ex->getCode() == 100) ? TRUE : FALSE;
} catch (\Exception $ex) {
return FALSE;
}
/*
object(Facebook\GraphObject)#1714 (1) {
["backingData":protected]=>
array(1) {
["success"]=>
bool(true)
}
}
*/
$graphObject = $response->getGraphObject();
return ($graphObject) ? TRUE : FALSE;
}
Related
I have problem with authorization of my facebook application. When I run my application normally on my local web server process goes like this:
**Get facebook user->If user is not logged on -> Redirect user on facebook login page**
**Get facebook user->If user is logged on -> Redirect user to authorize my facebook application->everything goes right without problems**
When I host my application on facebook using iframe, second process is not working (user never get show the authorization window), and I get following exception:
Error validating access token: User xxxxxxx has not authorized application xxxxxxx.
I'm using CodeIgniter PHP framework, and this is my PHP code:
$this->load->library('facebook');
$user = null;
$user_profile = null;
$user = $this->facebook->getUser();
if ($user) {
try {
// Proceed knowing you have a logged in user who's authenticated.
$access_token = $this->facebook->getAccessToken();
$user_profile = $this->facebook->api($user);
}
catch (FacebookApiException $e) {
show_error(print_r($e, TRUE), 500);
}
}
else{
$data = array(
'redirect_uri' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx','scope'=>'email');
$access_token = $this->facebook->getAccessToken();
redirect($this->facebook->getLoginUrl($data));
}
$data['facebook']=$user_profile;
$this->load->view('templates/header');
$this->load->view('pages/prijavaKlasicnoFacebook', $data);
$this->load->view('templates/footer');
}
You can not load the OAuth dialog in an iframe – security reasons.
You have to load it into the top-most window instance – so no server-side redirect, but a client-side “redirect” using top.location.href = "…";
Get your script to output this JS snippet (including the correct login URL) inside an otherwise empty document.
You should also provide "Read Stream" and "Publish Data" in your scope.
My app is not loaded and I get the erro below in these two scenarios:
a) The first time I access my app after clearing cache & cookies, or from a PC I haven't used before, with any browser.
b) When USER A tries to access the app straight after USER B has logged out from the app (and Facebook), from the same PC and browser, without clearing cache or cookies.
However, when I press F5 to update the webpage, it is working properly.
This is the error I get on the log file:
{"readyState":4,"responseText":"Invalid access token","status":200,"statusText":"OK"}
User validation code:
require_once(dirname(__DIR__).'/lib/common/AppInfo.php');
require_once(dirname(__DIR__).'/sdk/src/facebook.php');
require_once(dirname(__DIR__).'/lib/logic/UsersLogic.php');
require_once(dirname(__DIR__).'/lib/common/Log.php');
if (substr(AppInfo::getUrl(), 0, 8) != 'https://' && $_SERVER['REMOTE_ADDR'] != '127.0.0.1') {
header('Location: https://'. $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
exit();
}
try {
$facebook = new Facebook(array(
'appId' => AppInfo::appID(),
'secret' => AppInfo::appSecret(),
));
$user_id = $facebook->getUser();
} catch (Exception $e) {
exit("Error getting facebook data");
}
if ($user_id) {
try {
$basic = $facebook->api('/me');
} catch (FacebookApiException $e) {
if (!$facebook->getUser()) {
exit("Invalid access token");
}
}
if($basic==null){
exit("Application not installed");
}
$user=UsersLogic::getUser($user_id);
if($user==null){
exit("User not registered in database");
}
}
else{
exit("No user logged");
}
Any ideas why does it happen? Perhaps I should force to request a new user access token? (how)
THANKS
This is totally expected - in the first scenario there are not cookies, no knowledge of who the user is, and hence no way of getting hold of a valid access token, and in the second scenario, logging out from Facebook (or de-authorizing your app) will cause any access tokens you have to be invalidated.
But that error, that is from the client side code right?
In that case, you need to wrap the code you're using with FB.getLoginStatus or similar so that you don't run it unless you actually have the needed access token.
Is there any way that when user authenticate my app through Enhanced Auth Dialog, and gets redirected to canvas page, my canvas page knows its his first time visit?
Your may get the user id from facebook after the user redirected to canvas page:
Here is the example:
require_once("facebook.php");
$config = array();
$config[‘appId’] = 'YOUR_APP_ID';
$config[‘secret’] = 'YOUR_APP_SECRET';
$config[‘fileUpload’] = false; // optional
$facebook = new Facebook($config);
$app->user_id = $facebook->getUser();
After you obtain the user_id, you may save it in your database so that you can know whether the user is first time visit.
The previous answer is correct and here is the code I use to check if they are a new user or a returning user. Then I insert them into the database if they are new.
// Get the app User ID
$user = $facebook->getUser();
$seeif = mysql_num_rows(mysql_query("SELECT id FROM users WHERE fbid='$user' LIMIT 1"));
if ( $seeif == "1" ) {
// already exists
} else {
// insert new user
mysql_query("INSERT INTO users (fbid) VALUES('$user' ) ")
or die(mysql_error());
}
While the previous answers are correct, this might be more useful to you in the long run building your application.
Remember this relies on you having an open database connection as well as the facebook php sdk
// this brings back more info print_r($user)
$user = $facebook->api('/me');
$exists = mysql_num_rows(mysql_query("SELECT id FROM users WHERE fbid='" . $user['id'] . "'));
if ( $exists > 0) {
// already exists
} else {
// insert new user
mysql_query("INSERT INTO users (fbid) VALUES('" . $user['id'] . "' ) ") or die(mysql_error());
// do something else (post to timeline?)
// look up facebook feed for more info on posting
try {
// Post Message to feed.
$facebook->api('/me/feed', 'POST', $msg);
} catch (FacebookApiException $e) {
error_log($e);
}
}
I want my application to publish photos, user has already registered my app with publish_stream permission and is currently disconnected from facebook.
Documentation https://developers.facebook.com/docs/publishing/ said :
To publish a 'photo' object you need
a valid access token
publish_stream permission
I tried a HTTP POST request :
https://graph.facebook.com/<USER_ID>/photos?access_token=<APPLICATION_ACCESS_TOKEN>
POST param : "url":"<link_to_some_picture>"
And i got an exception :
content={"error":{"message":"A user access token is required to request this resource.","type":"OAuthException","code":102}}
To publish photos on behalf of user i cannot pass a user access token... Why i can post links but not photos with my application access token?
Your title states that you are using an application access token - the error you are getting clearly states the problem. You need a user access token.
You'll need to extend your users access token in order to perform actions on his/her behalf when they are not connected to Facebook.
Here is a good resource for information about dealing with expired tokens and how to refresh them -
https://developers.facebook.com/docs/authentication/access-token-expiration/
When user registered your application then you can store the user's user access token after you can used that access token to post on behalf of user.When user come to your application next time you can update that access token.
You can use following function to get extended access token:
public function getExtendedAccessToken(){
try {
// need to circumvent json_decode by calling _oauthRequest
// directly, since response isn't JSON format.
$access_token_response =
$this->_oauthRequest(
$this->getUrl('graph', '/oauth/access_token'),
$params = array( 'client_id' => $this->getAppId(),
'client_secret' => $this->getApiSecret(),
'grant_type'=>'fb_exchange_token',
'fb_exchange_token'=>$this->getAccessToken(),
));
} catch (FacebookApiException $e) {
// most likely that user very recently revoked authorization.
// In any event, we don't have an access token, so say so.
return false;
}
if (empty($access_token_response)) {
return false;
}
$response_params = array();
parse_str($access_token_response, $response_params);
if (!isset($response_params['access_token'])) {
return false;
}
return $response_params['access_token'];
}
$fid = $row[1];
echo "fid = $fid\n";
$message =$row[2];
echo "msg = $message\n";
$friends = $facebook->api("/$user/friends?fields=id");
$args= array(
'app_id' => $facebook->getAppId(),
'to' => $fid,
'link' => 'http://www.facebook.com',
'message'=>$message,
);
$post_id = $facebook->api('/fid /feed', 'POST', $args);
var_dump($post_id);
I've a facebook application, which conncets to facebook via the PHP-SDK.
$facebook = new Facebook(array(
'appId' => FACEBOOK_APP_ID,
'secret' => FACEBOOK_SECRET_KEY,
));
$user = $facebook->getUser();
if ($user) {
try {
$user_profile = $facebook->api('/me');
} catch (FacebookApiException $e) {
error_log($e);
$user = null;
}
}
Everything is fine, I let the browser open and don't respond to my app. After a while I try to send a form in the app via ajax. It seems that the session is invalid? Facebook will authorize my app again load the ajax url into the browsers address bar and attach the new session param to that url and breaks the app.
Is there anything I could do to pretend facebook to "reload" or pass the ajax/form action to the browser address bar? Before every request is processed I check whether the user is still active or not, that might be the problem?
$user = $facebook->getUser();
if ($user != 0) {
if($this->userProfile == null){
try {
// Proceed knowing you have a logged in user who's authenticated.
$this->userProfile = $facebook->api('/me');
} catch (FacebookApiException $e) {
error_log($e);
$user = null;
}
}
}else{
$this->userProfile = null;
}
if ($this->userProfile != null) {
$filterChain->run();
} else {
$loginUrl = $facebook->getLoginUrl(
array('scope' => 'publish_stream','redirect_uri' => 'REDIRECT_URI'));
}
echo("<script> top.location.href='" . $loginUrl . "'</script>");
Should I use an other approch?
Thanks in advance!
You really shouldn't be processing ajax calls the same way as regular page fetches. Generally if something like an expired session happens within an ajax process you want to send an error code back to the main page and let it handle it at the top level.
I'm guessing that the info you send back from this ajax request gets immediately parsed as HTML? Which means that if you send back a <script>top.location=xxx</script> block, it gets executed and redirects the browser to the new location. Again that's probably not the best way to handle things, but it would still work if the redirect_uri were set appropriately (to the url of the page as a whole). Because the getLoginUrl() is called while within the ajax page, the redirect_uri is set to that url instead, so after the new authorization is completed that's where the browser is sent back to (at the top level now). So while probably not the best overall structure, a quick workaround would be to override the redirect_uri setting when you are within an ajax call, and make it point to the parent page instead of itself.