Facebook login API: avoid user hijacking - facebook

I am using FB js SDK to allow logging in on my platform. A user permits the needed access and I save his ID in my DB. The data is sent to my server via AJAX. Since the login is with FB, I can identify the user only by his ID.
Now, lets say I know someones FB ID and I know he has an account on my platform. In runtime, I can place his ID in the auth request and obtain a legit session of that user. How could that be avoided?

First of all, those are App Scoped IDs, it is very unlikely that someone would know the ID of a user who authorized your App, because it´s not the "real" ID.
That being said, you can (and should) send the User Token to the server and confirm the ID by calling the /me endpoint with that Token. You should also use appsecret_proof for API calls, more information can be found in the docs: https://developers.facebook.com/docs/graph-api/securing-requests

Related

Facebook login to existing user database, and access tokens

Trying to add facebook login to an existing login system on a project I am working on. Built with angular, using the FB JS SDK. This is primarily to allow frictionless login, and not currently that fussed about using the access tokens to make further calls with the FB API.
So as a new user, they hit the FB login, accept permissions etc, and it fires me back an access token etc. The new user is created in my DB, along with the accesstoken, FB userid, etc.
How do I now authenticate the user with the userid and accesstoken now stored in my DB? As far as I can see, the access token changes on virtually every page load / request, so next time the user hits the FB login, or I check the FB login status the only constant thing I have is the userid.
Have done various reading on SO and FB docs eg:
https://developers.facebook.com/docs/facebook-login/web
https://developers.facebook.com/docs/facebook-login/multiple-providers
https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow#checktoken
How should a Facebook user access token be consumed on the server-side?
... although that has only served to confuse things further.
I imagine I would take that stored accesstoken then check its validity, however due to the various instances of access tokens expiring and being invalidated, this also seems like an incomplete solution.
So my question: How do I securely authenticate my FB users with their counterpart user in my own DB?
The Facebook login request returns user id + short lived access token (client side).
Use the server side Facebook SDK to check the validity of the access token (will return user_id and app_id fields if valid).
You can trust the user_id field returned from the Facebook API to check against your existing user database.

Is redirect to Facebook needed when the access token has expired?

Let's suppose there is a website which wants to post on Facebook in the users' name. First, when the user is linked to Facebook, he will have an access token and read access so he can log in with Facebook to the website, for instance. On a given event, the user will have write access on Facebook with the access token.
After a while, the Facebook access token expires (as it seems, but if there is a way to create Facebook access tokens which will never expire I would be glad to hear about), so on the website whenever a post to Facebook is about to be made, a request has to be sent to Facebook to check the validity of the access token. If the access token is invalid, then a redirect is needed to Facebook where a new access token is generated, then Facebook redirects back to the page.
I think there are no permanent Facebook access tokens. If there are permanent Facebook access tokens, how can one create them?
If a Facebook access token expires, is there any other solution to the problem than redirecting to Facebook for access token generation and redirecting back?
EDIT:
Here: https://developers.facebook.com/docs/opengraph/howtos/publishing-with-app-token/
I have read the section with the title of "Making API Calls to Publish with an App Access Token".
It states that I need the user's FacebookID and the publish_action privilege granted by the user to be able to post in their name on Facebook. However, I am puzzled about the way I can get the user's FacebookID and how the user grants the website publish_action privilege. Also, this section mentions that
"You will be unable to retrieve information about the status update post with the given ID using the app access token. Instead, you should use a user access token for such purposes."
I do not really understand what information is impossible to be retrieved with this possibility. I do not really understand the cause of inferiority of this strategy compared to the strategy with access tokens.
The short answer is yes, you have to redirect to Facebook (or use the Javascript SDK) to get FB to give you a new access token. If the user is already logged in to Facebook and hasn't deleted your application, then the process will be mostly invisible to your user.
You can, however, extend the length of time you're allowed to use your access token from 1-2 hours to a much longer period (I can't find the time reference, but I seem to remember it being a 3-6 month period). You can read about that process in the Access Tokens Documentation.
edit
First, you have to understand the difference between an App access token and a User access token. An app access token is a very simple token that facebook uses to verify that your app is making a request that you intended it to make. Your app access token consists of your app id and your app secret as a string and separated by a | character. This token doesn't grant you access to any user information, and isn't really usable for a whole lot of things (it's basically used for the authentication methods to ensure that when you request the token, the request is coming from you and not some 3rd party masquerading as you). Though, like you found above - you can also use it to make posts to the user's feed, providing they gave you access.
A user access token identifies an actual user, and their session, to your application. The user access token typically lasts a couple of hours and then expires. You can exchange this token for an extended access token which as I stated above, I believe to last for several months.
A user token (either the temporal 1-2 hour version, or the extended version) allows you to access the FB graph API as the user to which the user belongs. So, using these tokens you can access the user's friend list, photos, likes, interests, etc (presuming you requested permission to do so upon application install). You can check which permissions you have by using the user access token and making a request to /me/permissions on the graph api.
The Javascript SDK is unique, as it doesn't require you to redirect your user away from your application. The JS SDK allows you to use a pop-up to allow the user to authenticate with facebook, install your application, or to allow (or deny) permissions that you are requesting.
The FB.login method takes 2 parameters. Parameter 1 is the callback which is executed after the user responds to your authentication prompt (either by accepting or rejecting your application install request). Parameter 2 is for options which are passed as a javascript object, the only one of which you care about here is the scope parameter. The scope parameter is the way you ask for extended permissions (such as publish_action) so in order to acquire the publish stream permission from a user you use code that looks like this
<script type="text/javascript">
FB.login(function(response)
{
//check to see if they accepted or rejected, and do something
}, { scope: "publish_action });
</script>
Once the user accepts, any subsequent calls to the FB JS SDK will automatically include your user's access token, you don't have to manage it yourself. You can make calls to the graph API on behalf of the user without having to explicitly specify the user's user id - you can just reference them as me. So, for example, you could publish to your user's feed via the JS SDK like so:
<script type="text/javascript">
FB.api('/me/feed', 'post', { message: 'test!' }, function(response)
{
//do things
});
</script>
However, if you'd rather make calls to the Graph API from your server on behalf of the user to publish to their feed (or your needs require you to do so), you'll have to store the user's FB User ID along with your user data so you can access it later. That User ID is available in the argument that is passed to the FB.login callback (response.authResponse.userID). Once you store that, you'll be able to make Graph API calls on behalf of your user from your server simply by POSTing to /<user_id>/feed with the appropriate data:
$ curl -d "message=test&access_token=<app_access_token>" /<user_id>/feed
Finally, re-authenticating your user. THE FB JS SDK exposes 3 methods for authentication.
FB.getAuthResponse
FB.getLoginStatus
FB.login
The primary difference between FB.getAuthResponse and FB.getLoginStatus is that getAuthResponse waits for a response from Facebook before any further javascript is called (it's blocking, or synchronous). FB.getLoginStatus will allow other javascript to run and will call your supplied callback when it gets a response, allowing you to do other things while you wait for a response. Either of these methods can be used to determine if your user is currently logged in to Facebook and if the user has your application installed. You can then use FB.login (if they're not logged in to FB, or not users of your app) to prompt them to login, or install, so you can access their information. Both of these methods pass you back the user's access token if they're installed and have authorized your app (response.authResponse.accessToken).
FB.login does a check for the login status of the user, but it always will pop up a login/install dialog, regardless of the status (and if they're logged in/installed, it will hide the pop-up immediately). The FB.login method is also used if you need to request additional permissions from the user (Say you just get a "vanilla" install at first, and then later the user says they want you to post to their feed. When they initiate that option, you can then request the extended permission from them). In order to utilize that functionality, you use FB.login just as you would if they were a new user, except you add the extended permissions that you want/need in the scope property of the options variable you pass as the 2nd argument.
tl;dr
Use FB.getAuthResponse or FB.getLoginStatus to determine if your user is logged in and has your application installed. These methods can also be used to fetch new access tokens as your user is using your application.
Use FB.login to get new/unauthenticated users to install your application.
Once your user logs in, fetch their user id and store it your database somewhere. This can be used to post on their behalf with your app access token once you acquire the publish_action permission from the user
If you want to store a long-lived user access token to access the user's profile and other information, later, use the link above for exchanging your user access token for an extended access token. This is a server-side process, and you can store the resulting access token in your database with the user's other credentials.
Sorry this so long and wordy - I just wanted to provide you with some solid information about access tokens, how they're used, and how to use the JS SDK to maintain them. Hope this helps.

NodeJS Confirm Facebook Credentials

In this scenario I have an app in which:
The user is to log in using Facebook Single Sign On (SSO) on a mobile device (iOS in this case).
The returned Facebook credentials are then sent to a NodeJS server (using the same Facebook App Key) and need to be validated as truly being that users Facebook credentials before they are associated to a program based account.
The Problem:
Given access to everything returned by Facebook as the result of authentication, how can this data be used to confirm that authorization with Facebook?
There are two things you can do:
Facebook will generally pass you a signed request which you can check with a basic SHA2 hash. If the hash is correct, you can assume the user was really authenticated using facebook.
Facebook will generally also pass you a (short lived) access token which you can exchange for a longer lived access token using the graph api. Upon this exchange completing you are as sure you can be that the user is who he says he is.
https://graph.facebook.com/me?access_token=TOKENGOESHERE
If a user is returned, and their ID is what the client claims, they are most likely who they say they are.

Facebook API - Authentication similar to Hootsuite

I need to implement a system to retrieve information from a user of facebook independently of the user being logged into facebook.
I have user access token in my database but every time the user needs to login on facebook.
My question is how the authentication of Hootsuite (hootsuite.com) works because there it is not necessary.Just logging in the Hootsuite is possible to recover all data from facebook.
What you are talking about (If I understand you correctly) is a breech of privacy in the eyes of Facebook. A user has to be interacting with an application in order for it to retrieve information about the user.
Facebook's API access works by means of an access_token that is specific to the user and the application that requested it. access_token's have a limited time frame that they are valid, after that the application would have to request a new one or request an extension on that token. In either case, the user would have to be interacting with the application, and therefore logged into Facebook, when such a request is made.
I'm unfamiliar with the website you referred to but it is not in the scope of this site to reverse engineer some one else's application.

Facebook Javascript API: matching a login to a user

When using the Javascript API login, it returns to the page with a number of parameters, like the access token, the user ID, and other details. If I wanted to associate a user in my database with this Facebook user, which would be the piece of data I want to store to be able to look it up later for authentication?
In other words, which token should I store, so that next time the user logs in, I can look in the database for this token and authenticate the user?
I would use the UID, but it seems easy to spoof another UID and impersonate someone else.
Thanks!
Client side spoofing is not your concern. If you are displaying FB content based upon FB authentication, then FB is responsible for the integrity of that process.
If you are using this info server side, then you need to follow the OAuth 2.0 flow which is not spoofable (to my knowledge) because you are going directly to FB for authentication.
You can't mix the two flows because you leave yourself vulnerable to attacks.
And to answer your other question, yes, you should link your DB to the UID because the access_token will change.
You can validate the fb access token with the fb js sdk. So you can take the fb-uid as save. The tokens you get from fb are only valid for a limited time, so you shouldn't save them.
UPDATE:
Regarding the saveness of the fb-uid: Your PHP script gets a signed request from facebook. That request is signed with your app's secret so that no one else can read that data. The request contains a fb-session for the current user (including the uid) and an access token.