The blog has moved!
If you are interested in reading new posts, the new URL to bookmark is http://blog.valeriogheri.com/
This post is the natural follow-up of my post “How to build and test your Rest API with Node.js, Express and Mocha”.
Here I’ll show you a possible solution to the problem of authenticating your API users via Facebook, accessing some user’s basic info like name, profile pic and email and using the given Facebook access token to secure all your API endpoints.
This is quite a common scenario nowadays yet I couldn’t find many useful source of information. So I went ahead and asked a question on StackOverflow (http://stackoverflow.com/questions/15602667/possible-approach-to-secure-a-rest-api-endpoints-using-facebook-oauth). The solution described below is heavily inspired by the answer given by user Tommy Crush, so thanks Tommy!
The logical steps are:
Login via Facebook on your app (either mobile or web) and obtain the Facebook Access Token
Pass the Facebook Access Token to the server (over SSL for the android app, and for the web app just have it redirect to an API endpoint after FB login)
Check the given Facebook Access Token to make sure it is valid by making a graph call to the /me endpoint. Parse the response to get user id and email and cross-reference this with existing users to see if it’s a new or old one.
Now create a random token, store it and associate it to the user id and give the API token back to the requesting app. If you need Facebook for anything other than login, store it too in your DB and associate it with the new api_access_token and your user_id.
For every call hereafter, send the api_access_token to authenticate it. If you need the fb_access_token for getting more info, say retrieveing the list of your user’s friends, you can do so by retrieving it from the DB.
The code shown below is taken from my current project ShopWithMe available on GitHub (https://github.com/vgheri/ShopWithMe) and uses a Node.js + Express.js + MongoDB with mongoose technology stack.
I’ll go into details starting of points 3 and 5. Points 1, 2 and 4 should not be a issue.
Step 3: Verify facebook access token
To verify if the given token is valid we need to make a call to the /me endpoint of the Facebook Graph API located at the URL https://graph.facebook.com/me?access_token=$fb_access_token
The result, if token is valid, is a JSON blob containing the user’s information accessible using this token.
This blob should, at its minimum, look like the following:
"name": "XXX XXX",
Otherwise should we have an error response, that’s the JSON blob we’ll get back:
As a hint, if you want to try this on the browser, just go to https://developers.facebook.com/tools/explorer/?method=GET&path=me being logged in with Facebook on your browser. Obtain the Facebook Access Token and then point your browser to the URL https://graph.facebook.com/me?access_token=$fb_access_token , where $fb_access_token is the token you just obtained. You should see a JSON object containing your info if all went well (why shouldn’t it? J)
Point 5 is about securing your API endpoints, making sure that only authenticated users can access the data and authorize the request.
Express.js has a nice and easy way to allow a developer to play with the request pipeline, all that is needed is adding a function in the route declaration.
Let’s see how:
In the file where I defined my routes, I just need to update the routes I want to secure, simply modifying them like this:
app.get(‘/api/profiles/:userId’, authorisationPolicy, handlers.account.getAccount);
As it should be clear, I just added a function called authorisationPolicy to the route declaration that inside the pipeline is processed ahead of the handlers.account.getAccount function .
Let’s see into detail this authorisationPolicy function:
This function executes its authentication policy and if everything is fine, it calls the Express.js next() function, which takes care of executing the next stage in the pipeline.
If otherwise the request should not be authorized, we can send back an error response.
In conclusion what we have seen is a simple yet effective way to integrate Facebook login into your HTTP API and to secure your endpoints.
The key here is to use the Facebook token to identify your users and then to issue your own API tokens to secure your endpoints.