Facebook PHP SDK access token randomly expiring, how to seamlessly refresh without load time costs - facebook

I am using the PHP SDK on my website. I have developed a registration form and login form.
The facebook login link is generated, the user clicks and authorises the app. They are redirected to my site and have an access token.
I can use API call such as $this->facebook->api('/me/');
I put the call within a try statement and catch any exceptions.
It works perfectly.
The problem is that randomly my access token will expire, as such the api all cannot complete and the exception is caught. I don't know why this is, but what i want to do is seamlessly refresh the access token.. i.e get a new one and continue the users session on the site seamlessly.
What i thus do is save their location in a session, redirect the user to the facebook login page in the catch statement, and then on successfully re-logging in the user redirecting back to where they were.
This works, but there is a problem.
Having this:
try
{
$me = $CI->facebook->api('/me');
}
catch(FacebookApiException $e)
{
//redirect to fb login lin
}
on every page essentially doubles the page load time of every page on the site - the Facebook PHP SDK is inherently slow.
Instead of 1 second page loads, they are taking 2-3 seconds. I have benchmarked it, and it is because of this try/catch..
What can i do? HOw can i maintain/refresh an access key for an authorised user without huge load time costs to my users?

EDIT : The solution that I am suggesting uses direct OAuth 2.0 calls for Authentication using PHP and later PHP SDK for rest of the Facebook API calls.
Initially acquire an access_token by following the steps from Facebook Developer Documentation.
At Step 6, you will have an access_token with a longer validity of 90 days.
Now, once you have acquired an extended access_token, you can make the PHP SDK use the same by calling Facebook::setAccessToken
Store the Facebook object in $_SESSION for making api calls from other pages.
Furthermore, you can go ahead and save this extended access_token persistently(in a Database). This will eliminate the Facebook communication for logging in process altogether. However make sure that you have taken necessary security precautions for safe-guarding the access_token(for obvious reasons) and your privacy policy states the same.

Related

Facebook manual logout

I have .net web site which designed for working as standalone application. Due to one issue I was made to perform login flow to Facebook manually instead of calling FB.login(from FB javascript sdk). And because of this I am not able to call FB.logout (because in this case another issue appears).
Facebook support advised me this:
"In this case, you should manually clear the user's logged in session, by clearing any stored cookies, or removing any access tokens or user information stored on our end. You can refer to this page for more information on building login/logout flows manually: https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/#logout"
I didn't get this answer. How to realize manually logout workflow?
And I didn't find any examples.
You can check what the PHP SDK’s getLogoutUrl method does here, https://github.com/facebook/php-graph-sdk/blob/5d0c4865e80e231d48a4571841bd018828fe58e1/src/Facebook/Helpers/FacebookRedirectLoginHelper.php#L156
Basically it just calls https://www.facebook.com/logout.php with two parameters:
next is the redirect URI the user should be redirected back to after logout; it needs to be within your app domain
access_token is the valid user access token for the current user of your app

Facebook: Refreshing long-lived access token automatically

I'm storing long-lived access tokens for users of my application that have associated their Facebook accounts to it. Since the demise of the offline_access tokens, these long-lived tokens have an expiry date of "about 60 days." However, they can refresh themselves when the user interacts with Facebook. According to the documentation:
These tokens will be refreshed once per day when the person using your app makes a request to Facebook's servers. If no requests are made, the token will expire after about 60 days and the person will have to go through the login flow again to get a new token.
What I'd like to know is what constitutes making a request to Facebook's servers. Does the user have to log in to the Facebook website, mobile app, or use a Like button somewhere? Or does my application making a request on behalf of the user count as well?
Also, when the tokens are refreshed, are they refreshed for another 60 days? Or are they refreshed for a smaller duration?
I wasn't able to find these specific answers in the documentation or in other questions asked here, so thanks in advance to anyone who might have more details.
Every time you use Facebook SDK so it makes any Graph API call, tokens will be refreshed. You can see this in their source code, in AccessTokenManager there is function extendAccessTokenIfNeeded(), and that function is called inside GraphRequest in function executeConnectionAndWait().
You can also manually refresh tokens by calling:
AccessToken.refreshCurrentAccessTokenAsync();
I found one exception to this. Only sso tokens can be refreshed, which means if user logged in to your app via facebook app. If user logged in via browser, token will remain the same.
The previous line to the one you pasted is important:
Native mobile applications using Facebook's SDKs will get long-lived access tokens, good for about 60 days
The section you pulled out refers only to iOS and Android apps using the Facebook SDK - the SDK makes an API call to extend the token, which will only work from the SDK and for tokens produced by the native mobile SDKs-
Other apps (e.g websites, apps on facebook.com) need to use the login flows documented elsewhere in the documentation and require the user to be logged into Facebook in their browser

How to logout from facebook or destroy an active session using php?

I have an application which asks for a registration through facebook but before a user can proceed to the registration, the system should first determine if there is an active session. If a user is logged in to facebook, it should then automatically logout for a fresh start.
But here is where I'm stuck. The SDKs only let the user log out from facebook if he is connected to your app. It uses the app's access token. But what if he is still not registered to your app? Their log out means to log out from your app, and not really from facebook.
My requirement :
1. How can i log out from facebook.
2. How can i clear the browser cookies?
Not on a specific app but the whole facebook session.
[from comments] But to use the getLogoutUrl() function, the user has to be connected to your app. What I need is to logout from the whole facebook and not just from the app
If the user is connected to your app, then the URL provided by the getLogoutUrl method does that – log the user out of your app (web-app) and out of facebook.com.
If the user is not connected to your app however, you don’t have an active user access token – and then logging out of Facebook is not possible. The obvious reason being that if it was, every website that I visit could log me out of Facebook in a “drive-by” manner – without me actively wanting that, so people would get annoyed quite quickly.
If a user is logged in to facebook, it should then automatically logout for a fresh start.
If this is a security consideration, then you are in fact looking for re-authentication, which can be done using the auth_type parameter, quote from docs:
In apps where security is very important, you may want to double-check someone's identity - perhaps before they make a purchase within the app, or use it to access some sensitive personal data.
To prevent situations where a user could leave a device logged in or man-in-the-middle hijacking of the user session, re-authentication forces a person to re-enter their Facebook password before they can continue to use your app.
Be aware to use the server-side Auth flow though – because in the client-side flow, using the JS SDK, there is a bug that allows the user to bypass re-entering his password by simply closing the popup, which is still open: https://developers.facebook.com/bugs/248632218597467 (Has been assigned Priority: High, but received still nothing more than a “we will follow up” response yet.)
Use the logout.php url.
https://developers.facebook.com/docs/reference/php/facebook-getLogoutUrl/
Basically,
http://facebook.com/logout.php?next=YOUR_NEXT_URL_FOR_LOGOUT&access_token=USER_TOKEN
1) logging out from facebook by using
facebook=>getLogoutUrl();
2) clearing the session by using :
$facebook->destroySession();
example:
Log Out
logout.php page codes as follow:
<?php
require 'facebook.php';
$facebook->destroySession();
header( "location:index.php" );
?>

Detect if the user is logged out of Facebook

I have a Node.js web application that uses Facebook OAuth 2.0 to register/login/logout users using everyauth.
I enabled the deprecation of offline access on my Facebook application so now I receive tokens that expire after ~two months, or when the user changes her password, or when she removes the application, BUT not when she logs out of Facebook
My application is embedded in an iframe into multiple websites and is used to push updates to the user's Facebook timeline.
Say I have my application installed on site A and site B. If the user X logs in my application on A, he is logged into my application on B as well because the iframe preserves the session.
Problem
If the user X logs out of Facebook, anyone else using the same computer on sites that have my application installed is going to push updates on behalf of X.
Is there a way to determine if X is still logged into Facebook before pushing an update?
In other words, I need something similar to Facebook's JavaScript SDK FB.getLoginStatus but on the server side in Node.js. The best thing would be a Graph API call, but I can't find an appropriate URL for it.
IMPERFECT SOLUTION:
In the end, I went with #NitzanTomer's solution described in the comments. I used the JavaScript SDK and its FB.getLoginStatus method to check if the current user of my application is still logged in on Facebook. This is far from ideal: it works in my case because I'm running JavaScript code in an iframe, thus being relatively protected from attacks by the same-origin policy.
You can you use FB.getLoginStatus to check whether the user is connected to Facebook or not:
https://developers.facebook.com/docs/reference/javascript/FB.getLoginStatus/
getLoginStaus function is not there in facebook-node-sdk by amachang but what you can use is the getLoginStatusUrl function: facebook-node-sdk
The user is logged in if returned value is the url you assign to ok_session property. You cannot be sure of the permissions granted to your app though

Can't Logout of my Facebook OAuth Session without logging User Out of Facebook

Per the SDK, I am using the logout.php with redirect:
https://www.facebook.com/logout.php?confirm=1&next={SOME URL}&access_token={ACCESSTOKEN}
It is logging me out fine, but it's also logging the user out of facebook. Isn't there a way of logging out of my OAuth session without logging out of facebook?
Yes, I ran into this same issue myself. Dont do logout.php or JS SDK's FB.logout(). Rather call the Graph API with an HTTP Delete command to me/permissions. That will kill the access token, remove the app from the user's app listing and maintain their browser's cookie for facebook. You can call it either server side or client side. Here's the client side Javascript SDK way:
FB.api("me/permissions","delete", function(response){/*do something if you want*/})
This is one of the many annoying things about developing on the Facebook platform. The only way to log out via a browser session is to use their javascript logout function or the redirect like you tried but either will also log the user out of Facebook which is very annoying from a users perspective. The problem is you can't access the cookie they set for your app to delete it due to cross-domain restrictions so you are stuck with the limited options Facebook provides. If you are not prompting for offline_access, you could just forget the users access token and it will expire after an hour. Although the problem still exists that the cookie is still set for within that hour.