How to get the best performance from facebook canvas authentication - php

Facebook document that you need to do the following for canvas login
Include facebook library
Instantiate class with App Id and secret
Check that the user has a valid session
If they do check also that you can get there user object by doing an api call /me
If they dont then process the login redirect
All this especially the Facebook calls can take quite some time to process
The example shows this in terms of code
http://github.com/facebook/php-sdk/blob/master/examples/example.php
And from what I read it seems required on every page. Because a user can logout / remove app / change permissions etc during the session
My question is what is the ideal way of doing the above in terms of performance gains, but still making sure that it conforms to the nuiances of facebook.
Facebook do give a session expire time which seems to be in GMT.
I code in PHP using the Zend Framework but I suppose the above relates to all languages.
Appreciate your help on this

Ian, store your user facebook credentials in the user related table (or whatever)
facebook_user_id
facebook_secret
facebook_token
make it come out like something like:
$user->facebook_session_array();
Then just pass that into your api class when you want to reuse it. There is nothing you can do to make the oauth process (on authentication) go any faster because it has to happen live.
Cache the living daylights out of anything and everything you bring back from facebook.. run some crons in the background to either insert that stuff to table or stamp it down on a drive. Your cron script should be able to handle potential rate limitations. I wrote some, but facebook is so slow, I think it was pointless.
Facebook is slow.. don't make your app wait for it in any way you can avoid it.

first of all you'll have to authorize a user via facebook api, if you like to work with data of this user. As a result of a successful authentication your application will receive an access_token and a expire_time. The value of expire time is expressed in seconds, not a timestamp in GMT.
Your application has the permission, to store the access_token and expire_time within it's own session handling, e.g. You'll need the access_token to make requests on behalf of the user to the facebook api. With the expire_time value (and the time you authorized the user) you can check the validity of your access_token before calling fb API methods... and in case it expired, you should reauthenticate.
You definitly do NOT need to reauthenticate on every page reload of that user.
If the user changes something on facebook (e.g., removes your application) then a call to the api might fail with an "OAuthException" error. Your application should be aware of such errors and handle them appropriate.

Related

Use PHP to access LinkedIn API without user login

I'm trying to automate a data pull from MY company page on linked in via the API. This will be a server side job with no user intervention.
I have credentials to log into linkedin and a REST API Application with keys as per:
https://developer.linkedin.com/documents/quick-start-guide
I want to be able to pull the contents of my wall nightly to aggregate it to my social media site.
Is there a way to obtain and store the Oauth token server side and not require or fake the client session piece?
Thanks!
Yes you can, but a token can expire so you need renew it when needed.
Here is an example: https://github.com/EJTH/SLinkedIn/blob/master/examples/reusing-tokens.php
If you run a cron then dont authorize, but handle exceptions to reset the token and force the user to renew it on the next login.
I don't believe there is because LinkedIn doesn't allow it.
I've run into the same problem and it seems there may be a way to keep it open longer, but it looks like LinkedIn explicitly bans automated actions in their terms of service. Simply put, I don't believe any automated action can be initiated except by a member.
This gets into more detail on their stance on automated requests:

php javascript facebook sdk access_token

I am using the stock SDK for php/javascript. Now the app I am building many parts of it, if a user approves the use and accepts the permissions acts as a layer on top of facebook. Where it is planned to have my App pretty much interact with it as if the user was logged on at the time.
Previously I was playing with the offline_access but I recently read that that permission is coming out of the api completely and soon enough any tokens already in existence will just convert to 60 day tokens. I know from what I read that I can renew the tokens on a daily basis if need be when a user logs into my app. But my two biggest questions that I can't figure out one way or another is.
How do I ensure I get the "long-lived" tokens, and with these tokens do I store them on my end and pass them through the api to FB or is facebook storing these and through the use of the api the way it is and I don't need to store them somewhere. I know currently when I login it generates a token and stores it in a php session but the session is usually only good for the duration of the user being on my app. Note this is also a desktop app, not an app within facebooks canvas.
If I have to store the tokens to use them, and the php sdk bases itself off of whats stored in a session do I recreate the session with the stored access token for the user or I dunno, Im confusing myself as I type this out, hopefully someone can shed some light on the subject for me.
Here you can find some help on how to handle the expired tokens,
https://developers.facebook.com/blog/post/2011/05/13/how-to--handle-expired-access-tokens/
And here more info on how to use the new method,
Facebook offline access step-by-step
All this matter always makes me doubt as well, but I have noticed that facebook usually keeps the token somewhere on the user end, probably a cookie, so that it will automatically connect. So I don't think that the token only lasts a session and I'd rather say you won't have too many problems with the depreciation of offline_access, though this might just be my personal opinion.

Google Apps and OAuth best practices

I am working on integrating Google Apps into my PHP app. I have already a login system that assigns a session ID to a user (after entering username and password), which gets stored in the database when the user is logged in. Session ID's become invalid after a certain time of inactivity (configurable by the user, can be 5 minutes, 15, 60...). That session ID is passed in the url to check if a user is still logged in. When logging out, the session ID is removed from the database.
I let people log in with Google by storing their Google ID in the database, when they log in, I request an access token, query the userinfo, see if the google ID is in the database and if so, assign a session ID to this user. Since I want to be able to query other API's I also store the access token json in the database. When a user logs out, the access token is also removed from the database.
This works, my users are able to log in using their Google account and I can query the API's using the stored access_token, however some things feel clunky of make me feel uncertain about my workflow:
If you force_approval you get a refresh_token, I feel like I should be using this refresh token to get a new access token, instead of removing the old one from the database and entering a new one when the user logs in again. On the other hand, when logging in, I do not know who it is yet, so I don't know which refresh token to use. Maybe I'm misunderstanding what the refresh token is for. Also, I don't really want to force approval every time, so I can't even use the refresh_token in that case.
As said before, users can determine how long their session will last, however, the google access_token always expires after 3600 seconds. It'd be really stupid if users would work an hour on the system and after that the Google API's suddenly fail, forcing them to log in again. The Google OAuth playground shows a checkbox "Auto-refresh token before it expires", but I'm not seeing how to do this. Do I have to use the refresh token here? Or simply request a new token in the background (if I'm not forcing approval)?
At the moment, I'm using the userinfo query (https://www.googleapis.com/oauth2/v2/userinfo) to find the user id, but I can also use the tokeninfo (https://www.googleapis.com/oauth2/v1/tokeninfo). Tokeninfo is not listed in the oauth playground, but the result does show how long the token remains valid (however, I can also calculate this myself). Is one preferable over the other?
I'm storing the entire json object in the database (access_token, id_token, expires_in and token_type) but I feel my app will still work perfectly if I only store the access_token (only problem I foresee is if the expires_in time changes). Do I need to store the id_token for example?
I find the Google documentation (at developers.google.com) sometimes very lacking, if anyone knows any other good sources of information, I'm interested in them as well.
I think it might help if you took a look at the lastest OpenID Connect Specs where concepts like the userinfo endpoint come from. OpenID connect is built on top of OAuth 2. There's quite a lot in there, but it's still probably worth a look. This blog article is also very good (as are others in the same blog).
Unfortunately, I don't think Google's implementation is currently up to date with the latest spec draft so it will probably be a moving target for some time. These things have changed a lot over the past year.
I agree with your first point that you should be obtaining a new access token each time you authenticate a user, rather than refreshing an old one. You don't know who the user is until they have logged in and granted you an access token. In general, the lifespan of an access token is not linked to the user's session. Once issued, your application could theoretically use it to access resources independently of the user's presence. If you want to carry on accessing the resource beyond the token expiry time, then you need to submit the refresh token at that point to obtain a new access token. I'm afraid I don't know what the "auto-refresh" feature is for.
I believe Google's tokeninfo is analogous to the check_id endpoint of OpenID connect, but accepts either an access token or an id token, rather than just the latter. Note that the expiry times of the two may differ. You would typically be able to retrieve more detailed user data from the userinfo endpoint than from check_id, which would normally return the bare user_id.
You shouldn't need to store the id_token. It is a bit like a record of the user's authentication by the authorization server. The access token is what your application will be interested in maintaining once you have validated the user identity.

Facebook Authentication Implementation

I'm working on a project which will use facebook authentication completely (no custom authentication implementation exists). Project uses PHP for server-side scripting. I looked around for implementing fast and secure authentication mechanism but i cannot find any detailed description about this subject. Facebook's documents are weak and does only provide basic information.
Which authentication method would be appropriate? There's a Javascript SDK and PHP SDK. As i understand, i have to use Javascript SDK for login, then using PHP SDK i will check my database for verifying credentials. But using Graph API with PHP SDK is slow. Is there a better way to validate session?
Will i need to check session server-side (PHP-SDK) on every request?
What I end up doing for my apps is pretty simple and relatively fast compared to any other method I've seen.
Check the signed_request if exists, parse it if it does. If it doesn't, set the $login flag to 1 in PHP
I check the user's session / cookie to see if the user was previously authenticated by the app (will come back to this later. If it is empty, set $login to 1.
If the login flag is set to 1, send the user to the installation url.
The user installs the app and is sent to a connector page. This page serves the purpose of getting an access_token and generating a session / cookie for the user. This means you won't likely need to check this access_token's validity for the life of the user's session. offline_access also creates new opportunities. You can store the access_token in your db as well.
Whenever you have a call that goes out to Facebook, check the exceptions, if you hit an authentication exception, clear the user's session and cookie. Next time it will force them to update their access_token, even if this process is invisible to the user.
I've done this on my apps, in most cases means I don't have to make queries to FB to see the validity of the access_token nor do I have to constantly get it on each page view. Our goal was to reduce latency on our apps, but Facebook was the biggest source of latency, doing this has cut it down considerably.
Answering my own question:
I used Javascript SDK for checking facebook authentication is available.
If fb authentication is OK and my application does not authenticated, i present user with a prefilled registration form of facebook.
If fb authentication isn't OK i present a facebook login button.
Registration Plugin authorizes my application and i call my fblogin.php to check this information using PHP SDK. When PHP SDK validates authorization, it stores this information on a session variable. So there's no need to check fb authentication on every request.
Login button does the same as Registration Plugin. These methods share same server-side functionality but their representation is different.
In order to catch facebook logout status, i used Javascript SDK to validate facebook authentication on every request. If user is logged out, my js code calls fblogout.php and current session is destroyed. There's a flaw on this method. If a user does not logout from my website explicitly, an attacker could do anything on behalf of user only disabling js on the same machine.
I cannot find a better solution with fast response time.
You can use one or the other or both.
You can use PHP SDK to generate the relevant URL's to send people to. And just wack that on a link.
Or you can use Javascript to make the Facebook Default login button.
After that you can use one or the other to maintain and verify the session.
I generally use PHP to do he grunt work with oAuth keys and use JavaScript SDK to make the nice Facebook buttons and some minor less important graph calls for session monitoring.
Anything that involves any heavy or multiple graph calls I push to PHP.
But there is flexibility there to do what you want. You don't have to use JavaScript SDK for login.
It's up to you if you want to verify every page load or not.
I tend to use the Javascript SDK to handle it and like Berk if the session is dead. Call a page redirect to a logout script.
As of the latest versions, PHP and JS SDK are now both able to access the same user session (login with JS or PHP [instead of having to do both]). Check out this blog post for a more detailed explanation and an example.
If you're worried about security, perhaps you could set the session cookie to expire sooner with session_set_cookie_params().
First, just remind you that you will need to save not only access_token, but ideally, you would like to save the user's facebook uid alongside with access token. This because typically, you will need to include the uid alongside with access token in your API call.
Second, from Facebook Documentation
Note: If the application has not requested offline_access permission,
the access token is time-bounded. Time-bounded access token also get
invalidated when the user logs out of Facebook. If the application has
obtained offline_access permission from the user, the access token
does not have an expiry. However it gets invalidated whenever the user
changes his/her password.
Third, the purpose of having access_token and uid, is to perform an API call, right? Start from there. Do the authentification, if only the access_token is (somehow) become invalid. How to check whether its valid or not then? Well, you can use cURL (Reference) or Proxy Library(but you may need to modify it lil bit, since it originally was written for CI) to make an API call as a validation proccess. Sample (*sigh, using my Proxy Library)...
// Suppose we are try to publish a status from our fb app
// $access_token hold the user access_token, which you saved into your database
// $uid hold the user facebook uid, which you saved into your database
$proxy = new Proxy;
// This is equal with perform regular HTTP POST request with cURL
$api_call = $proxy->http('post','https://graph.facebook.com/'.$uid.'/feed', array('access_token' => $access_token,'message' => 'foo'));
// Now we can validate...
// If the API success, it will be returned a post id, with json format
// if not, it will be outputing json like...
// "{"error":{"type":"OAuthException","message":"Invalid OAuth access token."}}"
// so...
$result = (array) json_decode($api_call);
if(array_key_exists('error', $result))
{
// Here you can perform an oAuth authentification, to get fresh access_token and update your database
// ...
// After it done, process the previous api call with valid access_token
$proxy->http('post','https://graph.facebook.com/'.$uid.'/feed', array('access_token' => $access_token,'message' => 'foo'));
}
The Facebook Connect documentation is rather limited. It doesn't really tell you what it is doing, only how to do it. I personally don't use either SDK. I have built my own framework for my development projects.
Both SDKs as well as the JavaScript in the tutorial are, IMO, fairly outdated.
If you want to stick to one of the FB SDKs here is my suggestion. Use the JS SDK only if your Graph API queries and the like are sent to a PHP backend via Ajax. Otherwise stick with the PHP SDK.
Introduction
Facebook uses oAuth v2. They describe two different methods of flow... Server side and client side. This would be implemented just the same as any other application authenticating against an oAuth v2 service. They both do the same thing. The only difference may be you can use 'code' as a request_type to get an authorization code for obtaining a token in the future.
Authentication
As far as FB Connect is concerned ll your script needs to to is make sure you have an auth token or auth code whenever you require authentication. If you don't have that then you need to get it. You can use the presence of an auth code or token as a condition for which FB button to show (login or logout).
Redirect the user to oAuth for authentication. Facebook has their oAuth implementation bundled in to their dialog API. More information on the oAuth Dialog here: http://developers.facebook.com/docs/reference/dialogs/oauth/
You can use the optional state parameter for something such as CSRF protection. It retains it's value after the process and is sent with the callback as a GET parameter.
Application Interaction
Basically you're going to write your application the same way you normally would. The differences would be:
Your user database no longer stores a password, just the FB UID. Also, according to the FB Dev ToS you really can't store any user information. If you want to store user information you need to get it from the user. You can populate this information for them with FB information, you just need them to submit it.
Your registration method won't have a form frontend posting to it any longer. It will be called when an authenticated user does not have an entry in the DB.
API Interaction
If you went with code instead of token you need to request a token by sending code. This is done with the Graph API oauth. This part is not documented at all other than in their authentication tutorial. http://developers.facebook.com/docs/authentication/
With your access token, whichever method you may have used to obtain it. You can now query the Graph API however you desire. This will return a JSON encoded object.
Conclusion
As far as a fast and secure implementation goes, the Facebook PHP SDK does the job. It handles everything I covered here, including the CSRF. How to go about learning it, I have yet to find decent documentation on it. Everything is either old or the writer doesn't really know and is going off of other tutorials.
Your best bet is to dig deep in those libraries and figure out how it works for yourself. Do some trial and error, experiment.
The way I learned was by writing my own framework for it. I suggest you do the same. You can extend the Facebook SDK classes if you like. It's really limited, but it gives you all you need. I took my most commonly used API calls and placed them in as well. I now have a very quick and simple end result that is driven from my library.
I think you don't need to implement SDKs.
1, You need to get permission from the user, to access his/her data. So you need to redirect them to Facebook. It is few (3-5) line of code in php.
https://graph.facebook.com/oauth/authorize?
client_id=YOUR_APP_ID&scope=email&redirect_uri=APP_URL
2, When the user arrive back to your site, come with $_GET['code']
http://YOUR_URL?code=A_CODE_GENERATED_BY_SERVER
3, You have to decode this code via Facebook get request, and get the access_token.
https://graph.facebook.com/oauth/access_token?
client_id=YOUR_APP_ID&redirect_uri=YOUR_URL&
client_secret=YOUR_APP_SECRET&code=THE_CODE_FROM_ABOVE
3, After you have the access_token just run a /me?access_token GET request as often you need, to check the user is still there.
4, You can store the Facebook ID.
I think this is the fastest way. As far as I know the javascript sdk uses pop-up, what is blocked in most browsers.
This flow is detailed enough here: http://developers.facebook.com/docs/authentication/

After I authenticate a user in API how should I make sure they don't have access for too long

I am working on builing an API and application section on a social network so it will be something like myspace, facebook, hi5, friendster, netlog, and many other's have application section, they all use a REST server method and most of them will issue a api key and secret to each application developed. The person who builds the app will pass the api key and a user signature that is created with a hashing algorithm based on the user's ID who is using the app and the apps' API key. The applications code should set a cookie with some information like user id and signature and time. So on my server end the REST part should I just build the signature the same way the app does, check to make sure they are the same, if they are I send the correct data back. My concern is, how do I make sure a developer does not set a user's cookie to keep them authenticated for a long time, should I compare the time the users signature was created and if it is like a day old then I will send a bad response back from the REST?
When a user first add's an application from my main site, I will load the application site into an iframe and I will pass in user ID and other fields where I include the iframe so the application can use GET to initially get the information it needs to set it's cookie.
If you can help on this issue I would appreciate it, does it sound like I am in the right direction so far?
BTW I am using PHp/MySQL
I would store the token & user identifier that you pass back via the API in a database with a timestamp. When the user checks in via API to authenticate, check that timestamp and see if it is too old. If it is then pass back something like FALSE which would trigger some other command to make them re-authenticate into your system, which in turn would generate a new api token for the user to use.
Store a time() value in a session and every time the user does something check that time value to see if it's been longer than X minutes.

Categories