4

When implementing Facebook login using oAuth2 (the Javascript version), I receive an access token back from the Facebook auth server. So far so good.

The problem I have is that I want to implement a RESTful back end, where the user needs to authenticate on every request for accessing a back end resource, using a server generated token. What happens is that when using the standard login on my website (email + password), this token gets generated on the server by my own application and is then sent to the front end where it is stored (all transactions happen over https).

So I thought about using the access token that I receive from Facebook to store it in my back end, if the user wants to log in using Facebook. This way, every RESTful request to the back end could be checked against this token.

The problem however, is that the back end cannot check if the token received from the client is a valid Facebook access token (this is a Javascript client application, heavily relying on Ajax for all server communication). Even though I can write Javascript to only send the access token to the back end on successful authentication with the FB server, this process is not reliable as the Javascript is not protected.

My question is:

How can I safely store a token in my back end, after the user authenticated with Facebook?

Please note that I am creating a Javascript application using Backbone.

  • See "Inspecting access tokens" at developers.facebook.com/docs/facebook-login/… – Kris Vandermotten Jun 16 '14 at 13:57
  • Thanks, but it's not really the core of my problem. What I need is to send an access token to my back end on every request, because the user's resources on my own server are only accessible when the tokens match. In short, I want to use the oAuth2 access token to use it as a token for accessing resources in my own application as well. Hope that is clear. – Trace Jun 16 '14 at 14:05
  • Yes it is, so let me explain. When the user sends a request to your backend, they include a token. When that token is a Facebook token, you can ask Facebook who the user is (or if you don't care, simply ask Facebook to verify the token). Obviously, this verification step is performed by the backend, not by the JavaScript app. Resources in the server should not be stored by access token of course, because those change, but by user id. You obtain the user id by calling the API. See developers.facebook.com/docs/graph-api/reference/v2.0/user – Kris Vandermotten Jun 16 '14 at 14:11
  • Ooh okay. So if I correctly understand your suggestion; I send the FB token to the back end with Ajax and let PHP handle a second check with the FB auth server? I was in that case thinking about sending FB token + user id to the back end using Ajax, and double check if they match at the server with PHP in that case (double check between my server and the FB server). Instead of doing the check every time, I will temporarily store the token with Redis/MySQL. Any objections? – Trace Jun 16 '14 at 14:22
  • Your backend must not trust your front end. The backend must make the call to Facebook to verify the token and obtain the user id from it. Never trust the client. So there is no point in sending the user id from the client to the server, the server must ignore it anyway. Of course, for performance, your server can cache FB answers. – Kris Vandermotten Jun 16 '14 at 14:28
3

Edit: I changed the workflow for the login. If a user would have multiple third party accounts, and each account uses a different email address, then the email address is not a valid identifier. Now I'm using local userId.

enter image description here

1) When the user wants to log in using a third party access such as Facebook or Google, then the client requests an access token with Javascript to the auth server of this party. When the resource owner (user) is authenticated, the userId (and other related data) is returned in the response, together with the access token. This token is stored at the client in the form of a persistent time-limited cookie (eg 60 mins);

2) The client sends an Ajax request to the Zwoop server, sending the 3rd party (FB / Google), the 3rd party userId, and the access token with a POST request;

3) The Zwoop server receives the Ajax request, and sends a request (with PHP) to the 3rd party auth server (based on the the one defined in the ajax request) to get the 3rd party userId, based on the access token (that was received from the ajax request). When the userId’s match is successful, the Zwoop server has verified that the client has sent the correct credentials.

This approach makes that the oauth2 access token functions like a password, and is verified in the back end against the third party's Auth server. No malicious user should be able to simulate the same combination of credentials and the communication happens over SSL (no eavesdropping);

4) After the userId - token match verification was done at the server, the local userId can be retrieved and returned to the client. The local userId is the userId that Zwoop defines. For all further requests for resources to the Zwoop back end, we use local userId rather than the third party userId, this is why we retrieve it in this step.

The token can now be saved in MySQL and the Zwoop userId + token can be cached in Redis / memcached.

5) The Zwoop local userId is resent to the client. We use the local userId for further requests to the back end. We only use the third party userId in case we need access to specific third party resources (eg. Facebook newsfeed, calendar, etc...). If the authentication fails, then the userId will not be sent;

Further RESTful requests can now be made, whereas the oAuth access token (client) is matched against the cached token (server), to identify if the user has permission to access certain resources in our own application; When the cookie or access token expired, the client will request a new one, and the same procedure repeats itself.

  • In step 1, use a session token, not a persistent one. In step two, you talk about sending a user's email. Where do you get it, and why do you need it? In step 3, you don't necessarily get an email adres back from Facebook, you do get a user id though. – Kris Vandermotten Jun 16 '14 at 17:44
  • Thanks, but I don't use a session on the server because of the RESTful api. I just want to keep the user logged in until either the cookie or the access token expires. I get the email from the FB server when the user allows email access. I use it to identify the user record in my own database, because the Facebook userId doesn't correspond to the userId's in my own database. The only commong identifier that I see is the email address. Then I can store and cache the access token + userId of my own application. – Trace Jun 17 '14 at 6:21
  • A session token just means a non-persistent one, it doesn't imply a session on the server. When a Facebook user logs in for the very first time, just create an internal user and remember the mapping between Facebook user id and internal user id. After that, for a second or later login, you have the mapping. – Kris Vandermotten Jun 17 '14 at 18:15
  • Good idea. When I started to investigate about a way to merge accounts, I became aware that I need to create a local user and map that local userId to whatever 3rd party accounts that I have. Why I wanted to use a persistent cookie is because when the user closes the browser by accident, he would need to authenticate every time again (if eg. he would want to use my internal login system with email + password). Therefore I thought that saving user + token with expiry of eg. 60 minutes would be a good idea. Your opinion? – Trace Jun 18 '14 at 10:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.