Structure of a facebook app with minimal api calls - php

I read all the articles on FB regarding PHP login, JS login, Canvas app login, but something remains unclear to me. How does one keep a user logged in after the initial login in JavaScript? You receive a signed_request (which you can use to authenticate the user ONCE (on initial load of a canvas app and on login, right?), let's say you use that information to verify the user server-side. Ok, so far.. But what about subsequent page loads?
Basically my question is this.. Can I use the PHP FB SDK to verify a user is authenticated on each page load without an API call? How? Is there a way to do it that is compatible with canvas?
The reason I don't want any API calls is because I hit the limit once and my app went down for an entire night. Don't want that again...
A workaround I'm thinking of is to store the user token (which I want to anyway) and use that in a session/cookie to authenticate the user on every page load in PHP, but I'm not sure if this is the best approach, because: Using my own session/cookie would allow a user to stay logged in even if they are not logged in FB. Also, I presume FB wouldn't allow this for a canvas app.
I found these relevant questions, but the information is from 2011: PHP: Using Facebook OAuth with less API calls
Facebook Login: How to combine JavaScript with PHP SDK?

The workaround you mentioned is the right way of doing it. Saving tokens, using and updating them as they become expired - the way most companies stick to.
Only in cases of new users or expired tokens the OAuth should be used. The API you use is not important. You can actually retreive authentication through JavaScript and pass it to PHP for further usage.
Cheers.

Related

Facebook Login with JS SDK and PHP SDK. Is it safe to pass access_token in form?

I am doing a login with facebook on my website.
Unlike most logins I see....my users may already be signed up and later want to connect to their facebook. If they jump the gun and click 'login with facebook' when they already have an account on the website, they may end up creating a new account...which we don't want.
Instead, I have it set up so they login with facebook...and upon returning, check to see if the fbID or the fb email exists in the current db. If not...then present them with a login screen to login normally. At that time they will connect the two accounts. I have been researching for this quite some time and I am very surprised I don't see this method posted everywhere on the web. Seems logical to me.
To be clear, I use the FB JS SDK, to do the login with facebook popup. Then after the redirect, I use the FB PHP SDK to obtain the fb user ID and the users info from facebook.
Ok...so...one issue I have been having, is that after logging in with facebook...and then getting redirected back to a normal login screen, the facebook authentication is GONE when submitting normally. In order to finish connecting the two accounts in a secure manner, I would like to authenticate the user a second time before updating the database with their facebook ID.
In an effort to do this....I have decided to obtain the fb access_token with the first login, and then populate the normal login with the access_token. Then upon submitting normally, I can use the access_token to gain the user info with the php sdk and store the fb ID in my db.
However, is this safe? Passing the access_token in a form? Also...I noticed there was a way to obtain the "code" key, and use that to later obtain the access_token and the user_info. However, I am not sure how to obtain the "code" when using the fb JS sdk login.
Any thoughts on this would be greatly appreciated. I hope I was clear.
Thanks
You should never transfer the access_token between client and server. When somebody gets hold if it, they can perform actions for the user under your Apps name.
I'm not sure I understand what you mean with "the facebook authentication is GONE when submitting normally".
Have you read the guides on using Authentication with the PHP SDK? You can find them here: https://developers.facebook.com/docs/php/gettingstarted/4.0.0#authentication
Using the FacebookJavaScriptLoginHelper you can easily get the information from the logged-in user, using JS, to your servers.
For the JS SDK: https://developers.facebook.com/docs/javascript/quickstart/v2.1#login

Registration and Login best practise

I'm fairly new to facebook development, but have experience with PHP and JavaScript.
I've been reading through the SDK documentation and various articles regarding facebook integration but have found that a couple of fundamental questions are still open in my head!
I am trying to achieve the following:
Create a website that uses facebook only for registration and login
Use PHP to store facebook user id of registered users in a database on my app server, along with some limited app specific info for those users. All 'generic' info (email address, etc.) should be retreived from facebook.
when a user logs in, get a combination of database records for that user, and facebook stuff.
What I've achieved so far:
I have used the registration plugin to display a register button to unregistered users, and a login button for users who are logged out when they land on the page. I hide the login button using javascript and jquery if the user is already logged in.
I also have a page which receives a registered user and interprets the signed_request, adding the user's id to the users table in my database.
Where my confusion arises:
I want to use the Javascript SDK for user authentication (as it's really easy) - this is obviously done asynchronously on the client side.
Having said that, once a user has logged in using the JS SDK, I need to get some data from my database. I am happy to do this via an AJAX request, BUT that would require passing the facebook user id as part of that request. Surely this could be easily spoofed/changed by a savvy user & they could hence login to my application as someone else?
Question:
How do I securely pass information about a user who has logged in using the JS API to my server?
If the answer is "you can't" then why bother authenticating with the JS API? Is that just for apps that are really light touch?
Thanks in advance for any help!
The simple answer is, you use cookies. This Facebook blog post has a clear example of how to implement a client-side login and expose that data to the server.
Take a look at signed requests: https://developers.facebook.com/docs/authentication/signed_request/
It gives you a nice little primer on how signed requests work and how you can/should use them. If I understand your question correctly, this should answer your question as to why/how you can provide an extra layer of security. Send a signed request that only your application with its own app_secret can decode.

Codeigniter/Facebook SDK logic about login

Ok guys I'm creating an application in CodeIgniter that utilizes the Facebook SDK, both PHP and JS. It will be a user platform will people earn rewards etc. for sharing. What I'm confused about is the authentication for my application. So when a user comes to my site and logs in, do they need to authenticate every time? Can I store credentials? Should I only log them in with facebook. I guess to me it seems like they have to authenticate every time. How would you suggest integrating the authentication into the login process? I want to make calls like gathering info etc. but I want them to just authenticate one time and that's it.
I'm using calls like this from the sparks facebook SDK
$user_profile = $this->facebook->api('/me');
which basically works when the oAuth happens. how can I make this happen with out making them click through to facebook every time?
You can combine it with the login process, that seems to be a better choice for your needs. You can store the non-expiring offline access token returned by facebook and save it into the database
P.S. They are deprecating the offline access token but you can use it for now. After deprecation, you can probably get an extended access token which is valid for 6 months)

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/

PHP: Using Facebook OAuth with less API calls

My goal is to use Facebook Login on a website with as few api calls as possible. I don't want to use any server-sided facebook api call on sites that don't interact with facebook at all. That means I only want to use api calls for logging in and publishing things. However I don't want to use Facebooks offline_access permission flag.
Here are some thoughts:
Use own sessions for the site instead of relying on Facebook sessions. So a user stays logged in even if the Facebook session token is expired. Otherwise the user will be logged out as soon as the token is expired and needs to click login again to get a new token or Facebooks JS SDK will auto-login but this still isn't perfect because the user will see the page in "logged-out state" and it will refresh as soon as the JS SDK got a new token. No-JS users have to click the Login button again.
Cache Facebook user data in database or memcache. Use Facebook API Subscription to keep the database updated. -> No need to ask the API for changes in the user's Facebook profile.
Problem:
While using own sessions the Facebook session token might be expired when trying to publish sth. on Facebook. So you have to abort the current script and get a new token by redirecting the user to Facebook or using the JS SDK. Then continue the script. This is pain.
My thought on how to solve the problem:
Instead of publishing things on Facebook using PHP you can also do this in Javascript. If the token is expired just get a new one using JS which does not require the page to be reloaded nor the page to be redirected to Facebook. However I want to support users with disabled Javascript and then this is not possible.
In my opinion the only useful approach is to use own sessions with cached user data and keep the people logged in even if the Facebook token is expired. But redirect them to Facebook and back as soon as Facebook interaction is required. This way the user won't see the page in "logged-out state", no Javascript is required and the user will be only redirected to Facebook Login if it's really needed. For Javascript users the Facebook JS SDK will renew the token (which is then stored in a cookie) without the user noticing this as the user is still logged in (using the own session handling).
What do you think? Is there another (better?) approach to do this? My last point quite seems doable but isn't there an easier way? Thanks.
I had this exact same issue when creating an authentication system for my website. Like Elad Lachmi said, you can run FB.login on each page load - but this will cause a quick popup flash (gets very annoying).
My solution actually ended up requiring me to use offline_access. It seems that there is just no other appropriate way to keep the user logged in if they leave your site for a couple of hours.
Here's the (potential) catch:
Log the user in via Facebook without offline access
On each page, use jQuery to write an iframe to a specially formed URL which uses FB.getLoginStatus, and set it to refresh every 15 minutes
This combination should, every 15 minutes, fetch the most up-to-date user session ID from Facebook. It will cause it to be updated when it is close to expiration.
Please note that I haven't tried this, and it may be against the Facebook ToS. But it is really the only solution without using offline_access if you want to keep a user logged in for more than 2 hours without requiring them to refresh a page.

Categories