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
}
Related
I'm putting a "Login with Facebook" option in a website and I managed to achieve it quite smoothly. I'm relying in facebook->getUser() method which, according to the documentation, returns the Facebook User ID of the current user, or 0 if there is no logged-in user.
However, after logging in, all subsequent calls to getUser() return the userId, even if I go manually to facebook and logout.
Seems like the userId is being cached or something. I can see many people with the same issue but still could't find a solution for this. How can I overcome this issue (the website is based in CodeIgniter and I'm referring to this tutorial)?
Copy paste from my website.
$user = $this->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.
$profile = null;
if($user)
{
try {
// Proceed knowing you have a logged in user who's authenticated.
$profile = $this->facebook->api('/me?fields=id,name,link,email');
} catch (FacebookApiException $e) {
error_log($e);
$user = null;
}
}
See how $user goes to null if the API doesn't respond? That's the key. If you don't go through that step, it wont work. getUser will sometimes return an ID even if the user recently logged out.
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.
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();
Is there a way to use the facebook connect api in a static way?
When we use the facebook php sdk the link or button to login to facebook is something like https://www.facebook.com/dialog/oauth..................
what I want is to eliminate the include of the php sdk on every page, because it will cause some extra processing and server load in peak times.
I want to make a session check to know if the user is logged in, by checking for exemple if his facebook user id and name are stored in the session, then if not, display a static login button. then after login with facebook he gets to facebook-login.php which will include the facebook php sdk and process his data and store them in the session, so that he remains logged without including the php sdk in each page.
the url structure that I get with $facebook->getLoginUrl() is:
https://www.facebook.com/dialog/oauth?client_id={MY_APP_KEY}&scope={PERMISSIONS}&redirect_uri={MY_SITE/facebook-login.php}&state={A_32_CHAR_CODE_LIKE_MD5_MAYBE}
The final question is: WHAT WOULD BE THE URL IN THE LOGIN BUTTON?
just load the sdk and do something like:
echo 'Connect to Facebook';
that url will always be valid for a logged out user
This is a good question. First, a user is logged into you app means that you have a valid access token for the user.
And there is no way to be sure that an access token is valid before making an API call with this access token. So if you want to make sure the user is still logged in on each page, you have to make an API call to Facebook on each of them. Kind of heavy, but there is no other solution.
What you can do is assume that the access token you have is valid and check only once a while (when you really need to be sure the user is logged in).
You can have different scenario :
you have no Facebook data about the user : the user is not logged in your app for sure.
you can read the user ID, but you may not have an access token for this user : the user may not be logged in.
you can read an access token, but it may not be valid (has expires or revoked by the user) : the user may not be logged in.
you have a valid access token : the user is logged in for sure.
You can read the user ID and the access token in the session. The session array looks like that :
[fb_148195765253871_access_token] => 14819576525...
[fb_148195765253871_user_id] => 1536397056
The number in the keys of the array (here 148195765253871) is your app ID.
So what you can do on each page is to check if those keys are set and if they are not, load the SDK and double-check (because the access can be store in some other places that the SDK is reading) :
if (isset($_SESSION['fb' . YOUR_APP_ID . 'access_token'])) {
// assume to user is logged in
// and keep going
} else {
require "facebook.php";
$facebook = new Facebook(array(
'appId' => YOUR_APP_ID,
'secret' => YOUR_APP_SECRET,
));
// Make an API call to be sure the user is logged in
// ie : that you have a valid access token
$user = $facebook->getUser(); // User ID
if ($user) {
try {
$user_profile = $facebook->api('/me');
} catch (FacebookApiException $e) {
$user = null;
}
}
if ($user) {
// The user is logged in for sure
} else {
// The user is not logged in for sure
// Make him log in
echo 'Login with Facebook';
}
}
Hope that helps !
The selected answer does not really answer the question.
If you would like to isolate all the Facebook code necessary for generating the getLoginUrl function call into a separate file you can do this easily by using meta refresh.
So in your header point the link "Login With Facebook" to "facebook_login.php". On this page include the necessary calls from the SDK for getLoginUrl and than add the following line of HTML.
<meta http-equiv="refresh" content="0;URL=<?=$helper->getLoginUrl(array('email', 'user_friends'));?>">
I tested this out multiple times and it works.
FYI using Facebook SDK 4.0.
I am using Facebook php-sdk in my iframe facebook app to get user login status.
Right after I sign out using facebook Account > Log out link, the session is not destroyed yet. I must wait a few minutes before old session expires, then my app will again get the correct login status.
I expect the facebook to kill itself and the session when user signs out. How do I manually kill the session?
Here is my code:
$initParams = array(
'appId' => $conf['app_id'],
'secret' => $conf['secret_api_key'],
'cookie' => TRUE,
);
$fb = new Facebook($initParams);
$fb->getSession(); // will return a session object eventhough user signed out!
SOLVED:
calling $fb->api('/me') will destroy the session if user has previously logged out.
I've changed my code as following:
if ($session)
{
try
{
$fbuid = $fb->getUser();
$me = $fb->api('/me');
}
catch(FacebookApiException $e){}
}
If the API call is unsuccessful, $session will be set to NULL. Very weird behavior, I don't explain everything that is going on here but it solved my problem of having residual session object not being updated via getSession() method.
I'm using $fb->getUser() and what I did was almost identical with yours.
if ($fb->getUser())
{
try
{
$me = $fb->api('/me');
}
catch(FacebookApiException $e){
**$fb->destroySession();**
}
}
I found that using only API to check whether FB is logged out or not sometimes is inconsistent, but with destroySession(), the session will surely be destroyed.
if you are using the javascript FB.INIT calls on the login page, then set status to false from true.
details about the status attribute :
http://developers.facebook.com/docs/reference/javascript/FB.init/
Try finding the formatData function somewhere at LoginWindow (AS3) and find this line:
vars.redirect_uri = FacebookURLDefaults.LOGIN_SUCCESS_URL
Change the value for http://www.facebook.com/ and logout from that html page when logged in.
This is a temporary solution to logout if you are developer, not the end user.
Facebook should disassociate the session from the account that the session belonged to. You can use Facebook::getUser() to check whether this was done:
if ($fb->getUser() === null) {
// User logged out
} else {
// User logged in
}
Try $facebook->setSession(null) or using javascript Logout
Logout does not work any way you do.
Try posting this link in your browser, after you log in to facebook.
https://www.facebook.com/logout.php
What happen? it takes you to your facebook. No logout at all.
What ever you do, check the function (depends on your API) handleLogout and check the output. In my case, it returns the entire facebook html page.
The only way I've managed to solve this problem was by clearing the session using the signed request to check the user id:
$facebook = Membership::getFacebookApp();
$signed_request = $facebook->getSignedRequest();
if(isset($_SESSION['facebook_id']) && $signed_request['user_id'] != (int)$_SESSION['facebook_id']){
$_SESSION = array();
}