22

What would be the best practices for storing access tokens of another api for your users? In particular I'm developing an application with some friends that let's user log into Facebook to both authenticate to our internal REST api and make it able to fetch their friends (and other things).

I was thinking of generating a key and use it to encrypt the long-term access token for the user's Facebook account and possibly other sensitive information. As encryption scheme I'd use AES-256-CBC and the key would be sent to the client, which holds on to it (and refreshes it once in a while). But if I generate that key with any randomness in it, then the user can only use one client. As the other clients would need that key to decrypt the Facebook access token and other data. A solution would be generating the key from something unique during the Facebook log-in, but unfortunately the only such thing I can find is the userid, which I need to find the user's record in the database.

There are actually a lot of topics about this over on stackoverflow, but nothing answers to what I want. What I actually want is to encrypt the Facebook access token and other data using a key that only the client-side knows. The creation of those keys should only be possible when the user authenticates using the Facebook sdk or when the current key is supplied.

Any ideas?

Joren Van Severen
  • 329
  • 1
  • 2
  • 6

3 Answers3

14

The sum of what the client stores and what your server stores must be sufficient to recover the user-specific secret data (e.g. Facebook access token). What the client stores is, mostly, the user's password (the only permanent storage area on the client side is the user's brain, if we want to allow the user to use several distinct machines at will). If I understand correctly, you do not want your server to store the data "as is": in case your server is fully compromised, the user's secrets should still be safe (as much as is possible).

This points to password-based encryption. From the user's password is derived a symmetric key K which is used to symmetrically encrypt a bundle which contains the user's secrets, e.g. the Facebook account. Technically, this would look like this:

  • When the user registers, he chooses his password P and sends it to your server.
  • Your server generates a random salt value S and computes PBKDF2 over P and S, to produce 256 bits of output T. Let's call A the first 128 bits of T, and K the other 128-bit half.
  • The first half (A) is stored in the server's database; this will be used to authenticate users.
  • The second half (K) is not stored; this is the symmetric key for that user. User's secrets will be encrypted with K.
  • When the user logs in, he sends his name and P to your server (over HTTPS). Your server retrieves the salt S for that user (as stored in its database) and recomputes T (using P and S with PBKDF2). If the first half of the recomputed T matches the stored A, then the user is authenticated and the second half of T is K. The server can then decrypt the stored bundle and access the Facebook access token.

With this setup, the server never stores (on its disk or in its database) the cleartext Facebook access token, but it can access it when the user logs in; it is up to the server to remember (in RAM) the Facebook access token as long as it needs it.

Note that when the user changes his password, this also changes K (the server must also generates a new salt S, but even if the server mistakenly did not, K would still be changed); thus, the server must decrypt the stored bundle with the old K and encrypt it again with the new K when the password is changed. This is not hard to integrate because password-change interfaces customarily ask for the old password and the new password, so at that point the server has both.

Also note that when the password is forgotten, the bundle is lost. There is no recovery for that case. If the user forgets his own password, then you will have to do some password reset, which is akin to a new registration; and a new Facebook access token will have to be obtained.


In all of the above, we see that your server still sees the user's password. If your server is fully compromised and hijacked, then the attacker will be able to observe users' passwords and users' Facebook access tokens for all users who log in while the attacker controls the server. Preventing that is much harder. Arguably, if your server presents a Web interface only, where all "intelligence" on the client side is Javascript sent by your server, then it is impossible to do better than what the scheme above does, in that situation.

Tom Leek
  • 168,808
  • 28
  • 337
  • 475
  • 4
    The thing is, the user doesn't have a password for our system. Authentication happens through Facebook and asking for another password (besides the password facebook asks if they aren't logged in) seems overkill. – Joren Van Severen Sep 05 '13 at 15:30
  • 2
    This is great for typical password schemes, but we are talking about access tokens such as the ones seen in OAuth. Your app doesn't interact with the credentials; your users are redirected to the provider and then it's handled there. – Strawberry Jul 18 '18 at 06:37
3

Facebook Docs: Securing Graph API Requests provides a simple solution.

ma11hew28
  • 287
  • 1
  • 9
  • 3
    To anyone wanting the TL;DR version of this reply (which shouldn't be link-only as it is quite important), an OAuth provider can require the access token be signed with the application's access token secret to verify that the application which is sending the request via the token is indeed the one that generated the token and not someone who stole the token. This basically moves the problem to the provider rather than the consumer which is the correct place to put the responsibility. – apokryfos Oct 05 '16 at 08:14
  • @apokryfos This is only specific to FB right? What about other OAuth providers? Correct me if I am wrong, but I don't believe OAuth has this part of its specification. – Strawberry Jul 18 '18 at 06:38
  • 1
    @Strawberry The OAuth spec looks a bit weird to me [OAuth 1.0](https://tools.ietf.org/html/rfc5849#section-3.4) states *OAuth does not mandate a particular signature method, as each implementation can have its own unique requirements. Servers are free to implement and document their own custom methods.* and OAuth 2 uses bearer tokens mostly meaning that having the token is enough to authorise access so yes as far as I can see this is a Facebook only extension of that. – apokryfos Jul 18 '18 at 07:56
2

I was at the 10th ISC conference of security and cryptology last week and there I saw someone proposed a method for storing user-pass tokens using Neural Network. He's created a NN that learns user-pass tokens and updated itself using a fast NN learning method. It is a new method and promise security but needs lots of attention on learning.

UPDATE

The paper was in Farsi titled enter image description here it means User Access Control Using Neural Network and chaotic system

(stack doesn't support Farsi characters! I used image instead!!!)

sajjadG
  • 121
  • 4
  • Got any more information about that proposal? like a paper or title? – Joren Van Severen Sep 04 '13 at 13:44
  • @JorenVanSeveren It is in `Farsi` (aka Persian). check paper 197 on list of accepted papers here: http://iscisc13.yazd.ac.ir/index.php?module=htmlpages&func=display&pid=109 – sajjadG Sep 04 '13 at 13:53