I am using the facebook php api to control the access to some parts of my webapp. Basically I am just checking if the user is logged into facebook and the user authorize the app (basic permission) every time the page is load and then printing things according to the state.
Something like, if($check_user_lo_npe) { echo 'Welcome!'; }, simple as that. Well, everything is working fine, until I realize that if the user deletes the app from their users settings in facebook, which means the token gets invalidated, I am still getting a true response from the function check_user_lo_npe even if I know the token is invalid because as I said, the user deleted the app. This is how I am checking the permissions:
function check_user_lo_npe() {
global $facebook;
global $data;
$fb_user_id = $facebook->getUser();
if ($fb_user_id) {
try {
if(!isset($_SESSION['fb_user_profile'])) {
$_SESSION['fb_user_profile'] = $facebook->api('/me');
$temparray = $facebook->api('/me/friends');
$_SESSION['fb_user_friends'] = count($temparray[data]);
}
$data->reg_user($_SESSION['fb_user_profile'],$_SESSION['fb_user_friends']);
return array(true,'');
} catch (FacebookApiException $e) {
$fb_user_id = NULL;
return array(false,$e->getMessage());
}
} else {
return array(false,'');
}
}
I need to realize when the user deletes the app so I can send them to the login screen again, the function is supposed to detect when there is an exception, but somehow I am not getting any... why?
Those $_SESSION variables are set by your app, not by the Facebook SDK right?
Without attempting to access the Facebook session you can't be sure if that session is still active/
If you need to check on each page whether there's still an active Facebook session or not, look at FB.GetLoginStatus() in the Javascript SDK, or make an API call to (for example) /me/permissions to check your access token is still valid
That said, it may be as easy to just have an exception handler which detects when an attempt to access Facebook's API fails, and have it send the user through the authentication flow at that point.
Your if ($fb_user_id) line is probably evaluating to false, which causes you to return array(false,''); in your else statement, never triggering an exception.
If you did get past the ID check, it looks like you are putting data into $_SESSION before they delete the app, and then not re-checking it. Once you have it in the $_SESSION, if you don't go back to Facebook to verify, there is no reason an exception would be thrown.
Related
The question is the same as title. I'm using the latest php-sdk (v3.1.1) to operate server-side authentication flow.
I have 2 tabs in Chrome, one is my Facebook page and the other is php test page. These 2 problems happen many times:
$facebook->getUser() still returns 0 even when I logged in.
$facebook->getUser() still returns an ID even when I logged out.
I have to do a work-around of this: try initiating a graph API request with provided access_token, and check if $response->error->type == "OAuthException" to ensure there's an active session or not.
Is there any way to use $facebook->getUser() "stably"? I've searched a lot through SO but not found best answer for php-sdk 3.1.1 yet.
Highly appreciate any helps. Thanks.
Login.
As per documentation example of FB SDK, getUser() returns userId even when you're logged out, but have cookies associated with FB account.
To detect is user logged in you should use
$user = $facebook->getUser();
//Check Access token
if ($user) {
try {
$user_profile = $facebook->api('/me');
} catch (FacebookApiException $e) {
$user = null;
}
}
if ($user) {
//logged-in
} else {
//not logged-in
}
To login in your app make user logs in in your app, not on neighbouring tab, by following this url (make sure that you're passing the scope based on intended actions performed by your app):
$loginUrl = $facebook->getLoginUrl(
'scope' => ...
);
Logout. Seems that your PHP server is storing some values of access tokens per session, so even when you're logged out in your browser, your server still have these tokens valid. Actually, I don't know, is it bug or feature, but they're not destroyed by Facebook after user logout.
To destroy these tokens I'm using these:
$facebook->destroySession();
I'm calling it every time when user logs-out by $facebook->getLogoutUrl();
I've got following code:
$fb = new Facebook(array('appid'=>APPID, 'appsecret'=>APPSECRET));
$user = $fb->getUser();
if($user)
{
try {
$me = $fb->api('/me');
}
catch(FacebookApiException $e) {
error_log($e);
enter code here
$user = null;
}
if($user) { blah blah blah
And it works properly if user is not logged in and if the user logs in, it works. But only if he click link from $fb->getLogoutUrl() and successfully logs out from facebook, my app still holds his data. I read that trying $fb->api('/me') should throw an exception if user is logged out but it isn't. Clearing the $_SESSION table helps but I don't think that is properly solution.
Any idea's?
I think this might be caused by facebook's extended access token (I am not sure) which basically gives the same as offline access (in fact replaces it: https://developers.facebook.com/roadmap/offline-access-removal/ ) but for 60 days.
So I think it is nothing to really worry about. I am unsure what you mean by:
Clearing the $_SESSION table helps but i don't think that is properly
solution.
Since I am unsure exactly what you are "clearing", you might be clearing the accessToken in which case, yes that will stop you from accessing the users info, although be aware it DOES not deauth your app. Logging in and out are two completely different things to auth and deauth. The /me url will normally only throw an exception if your n ot allowed to access, i.e. user has deauthed your app.
I think using destroySession after logout ($fb->destroySession()) will solve most of your problems by destroying the cookies on your side and resetting the user access.
I am pretty familiar with the Facebook SDK and API but I still find myself having a lot of trouble with it. Most of all, speed!
Each time I execute an 'api' call, it takes an additional second or two to return a response. I would therefore like to know what the most efficient and fastest way to detect whether a user is logged in via Facebook is. I am currently using:
// Get the User ID of the facebook user
$facebook_user_id = $this->facebook->getUser();
// If a facebook user exists, then try to get their information
if($facebook_user_id){
try{
// Get the facebook users details
$facebook_user_name = $this->facebook->api('/me','GET');
$this->facebook_logged_in = $facebook_user_id;
return $this->unique_id = $this->facebook_logged_in;
}catch(FacebookApiException $e){
error_log($e);
return false;
}
}else{
return false;
}
This works to a certain extent but it is awfully slow. I literally want to know whether the user is logged in and their session is valid. Is there another way to go about doing this? Why is it so slow?
In most all of facebook's PHP examples, they tend to use $uid = $facebook->getUser(); see
http://developers.facebook.com/docs/reference/php/facebook-getUser/
And then they check if the $uid is 0, then not logged in. if other than 0, then you have their facebook user id.
Looks like you're calling the /me command additionally when you really don't need to. Also to make the /me call quicker, specify the fields=Comma,List,Of,Fields,You,Need so the query can operate quicker. But as noted above, for just getting login status, check for 0 in $uid.
I'm using the PHP SDK for facebook connect.
Now, I can log people in fine using this:
# active session
$session = $facebook->getSession();
if(!empty($session)) {
# Active session, try getting the user id (getUser()) and user info (api->('/me'))
try{
$uid = $facebook->getUser();
$user = $facebook->api('/me');
} catch (Exception $e){}
if(!empty($user)){
GET USER DETAILS FROM DATABASE, SET SESSIONS FOR MY SITE ETC
} else {
die("There was an error.");
}
However, when I log out of my site (which is just a simple logout script destroying the sessions) and then try to log in again using the same facebook script, it triggers the error, indicating that $user is empty. This happens if I stay logged into facebook or someone else tries it and carries on triggering the error until I clear cookies.
There must be something that I am supposed to clear when I log out or before someone logs in with facebook. But the documentation for Facebook is laughably bad and the forum is a complete shambles.
Note, I do not want to log the user out of facebook, only my site. But I obviously cant have the user have to clear their cookies whenever they want to log back in again.
Any help?
In case anyone is searching for this (as the facebook documentation and forum are so absolutely terrible) I just changed the setcookie value to false when you set up your secret key etc.
This means that the user would have to log in again if they left your site, but only if you are not setting your own session/cookie values. So it works perfectly for what I needed.
I'm not sure if the php server side Facebook library validates sessions on load. So then I want to know if there is a best practice for insuring that I really do have a valid FB session and not some crackers altered $_COOKIE data.
$fb = new Facebook();
if( $fb->session_expires !== 0 && $fb->session_expires < time() ) {
die('bad and/or old session');
}
or is it better to test the users FB id?
$fb = new Facebook();
if( $fb->user ) {
die('no Facebook User Id given');
}
EDIT:
Ok, according to facebook "Your client library should perform all the necessary validation for you" by using the application secret to md5 all the params and validate the hash. So if you have a session - it is a valid FB generated one (although it can still be expired).
Suppose that you login to a connect app. Then you logout of FB. If you load another page on that connect app then there has not been any chance for the FB JS to change the cookies to state that you are actually logged out. And since the PHP library doesn't actually call FB to validate your session it also can't know to remove the bad values.
The result is that you have a valid set of cookies sent from FB that are no longer any good. So should you try to call an API method that requires a session then your app will throw a fatal error.
Call an API method $facebook->getUser() and that should check whether the user is valid.
https://github.com/facebook/facebook-php-sdk/blob/master/src/base_facebook.php#L508
As in the example provided in the SDK
// Get User ID
$user = $facebook->getUser();
// We may or may not have this data based on whether the user is logged in.
//
// If we have a $user id here, it means we know the user is logged into
// Facebook, but we don't know if the access token is valid. An access
// token is invalid if the user logged out of Facebook.
if ($user) {
try {
// Proceed knowing you have a logged in user who's authenticated.
$user_profile = $facebook->api('/me');
} catch (FacebookApiException $e) {
error_log($e);
$user = null;
}
}
A late answer but, currently Facebook PHP class have a getSession() method:
if ($facebook->getSession()) {
// Do stuff
}