Possible approach to secure a Rest API endpoints using Facebook OAuth
api, facebook, oauth, rest
Solution
I think the better solution would be this:
- Login via Facebook
- Pass the Facebook AccessToken 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 `fb_access_token` given, make sure its valid. Get `user_id`,`email` and cross-reference this with existing users to see if its a new or old one.
- Now, create a random, separate `api_access_token` that you give back to the webapp and android app. If you need Facebook for anything other than login, store that `fb_access_token` and in your DB associate it with the new `api_access_token` and your `user_id`.
- For every call hereafter, send `api_access_token` to authenticate it. If you need the `fb_access_token` for getting more info, you can do so by retrieving it from the DB.
In summary: Whenever you can, avoid passing the `fb_access_token`. If the `api_access_token` is compromised, you have more control to see who the attacker is, what they're doing etc than if they were to get ahold of the `fb_access_token`. You also have more control over settings an expiration date, extending `fb_access_token`s, etc
Just make sure whenever you pass a access_token of any sort via HTTP, use SSL.
Problem
I've been reading a lot about the topic but all I find are obsolete or partial answers, which don't really help me that much and actually just confused me more. I'm writing a Rest API (Node+Express+MongoDB) that is accessed by a web app (hosted on the same domain than the API) and an Android app. I want the API to be accessed only by my applications and only by authorized users. I also want the users to be able to signup and login only using their Facebook account, and I need to be able to access some basic info like name, profile pic and email. A possible scenario that I have in mind is: - The user logs-in on the web app using Facebook, the app is granted permission to access the user Facebook information and receives an access token. - The web app asks the API to confirm that this user is actually registered on our system, sending the email and the token received by Facebook. - The API verifies that the user exists, it stores into the DB (or Redis) the username, the token and a timestamp and then goes back to the client app. - Each time the client app hits one of the API endpoint, it will have to provide the username and the token, other than other info. - The API each time verifies that the provided pair username/token matches the most recent pair username/token stored into the DB (using the timestamp to order), and that no more than 1 hour has passed since we stored these info (again using the timestamp). If that's the case, the API will process the request, otherwise will issue a 401 Unauthorized response. Does this make sense? Does this approach have any macroscopic security hole that I'm missing? One problem I see using MongoDB to store these info is that the collection will quickly become bloated with old tokens. In this sense I think it would be best to use Redis with an expire policy of 1 hour so that old info will be automatically removed by Redis.