4

I am designing a REST Api for a mobile application and have some worries over properly securing access to accounts.

I am writing the API server in nodeJS and it will primarily be consumed by a mobile client (although a web client may be added in the future)

There are 2 main side aspects I wish to incorporate in the auth process:

  1. Users ID is encoded in the token (to reduce stress on DB)
  2. User can have only 1 valid token at any one time (login nulls any previous token)

Here is my initial design (all endpoints are over SSL):

Login

  1. User POST's her username & password to '/login'
  2. Server verifies users exists and the password matches the bcrypt hash in the Db
  3. Server generates a uuid v4 for the user and stores this in Reds with the users ID as the key
  4. The users uuid and user ID are then encoded in a Json Web Token with an expiration time of 1 week
  5. The JWT is then sent back to the users as their authentication Token

Protected Route

  1. User sends GET request '/users/me' withe her token set as Authorization: Bearer header
  2. Server verifies the JWT and sends appropriate error responses if verification fails
  3. Server then queries the Redis store and verifies the uuid stored for the user matches the uuid encoded in the JWT
  4. If uuids match the users id is set to req.user and the request is processed, if not then error message is sent back

Does this look like a good authentication strategy or am I way off?

  • 3
    Secure from what? And from whom? Who is your threat? – Deer Hunter Mar 20 '14 at 12:38
  • May I ask why you chose to introduce a UUID and not just use the user ID directly, or would you be exposing "private" information? – bernhardw Mar 29 '14 at 11:33
  • My idea was to use the users ID as the Redis Key and the uuid as the value. On auth I use the ID to get the uuid stored in Redis and compare with the uuid stored in the JWT, if they don't math I know the JWT is old (or possibly faked) and shouldn't authenticate (as I want only one active JWT at any given time) – Ross J Mar 31 '14 at 10:15
6

I find two possible flaws.

UUIDs in general do not guarantee to be cryptographic random. Depending on implementation it may be possible to give a qualified guess about what other UUIDs have been generated by a generator, given some of the output. You need to use a suitable length of output from a cryptographic random number generator as session token.

Whenever you extend to a web client you need to secure against cross site request forgery, that is, any request that change data on the server needs to have a token that is not a cookie as part of the request, otherwise the request can come from another open web site on the users computer.

Another thing, if you want to reduce stress on the DB, you can store session information in process memory in Node. You only need the database for things that has to persist through a crash.

  • Not sure, but aren't JWT signed (hopefully with a key of suitable length and cryptographically random) so although they can be read, they cannot be self-generated or tampered with? In that case, one could even use a auto-incremented user ID directly, instead of a UUID. Of course only if they don't mind the leaking of private information. Thanks! – bernhardw Mar 29 '14 at 8:28
  • 1
    @bernhardw I must admit that I missed that "Json Web Token" is a standard, I simply assumed it to mean that the information would be contained in a JSON format. But if correctly implemented and correctly checked then yes, it would be secure. And this does pretty much make the UUID oblivious, as long as the content is unique (user id + time stamp would for instance suffice), and the HMAC key is strong and secret, the HMAC itself is amongst other things an excellent random number. – aaaaaaaaaaaa Mar 29 '14 at 9:58
  • To add a bit I picked to use a uuid to facilitate my need for 1 active JWT at a time (with the npm package uuid it was easy to implement) this worked for me at the time. Also with regards to the HMAC key being strong I am planning on using RSASSA using SHA-512 hash algorithm for signing the JWT – Ross J Mar 31 '14 at 10:38
  • @RossJ There is no reason to use asymmetric signature schemes for a simple authentication token since you don't need 3rd party verification. You should keep your security scheme as simple as possible (but not simpler). If you dabble in unnecessarily complex features you run a higher risk of introducing security holes through a bug or an oversight. – aaaaaaaaaaaa Mar 31 '14 at 14:28
  • About the UUID part: my understanding is that as long as you use a truly secure random when generating UUIDs, you are fine for this use case. While there might be a theoretic chance of duplicates, it is extremely low: en.wikipedia.org/wiki/… Keep in mind, the UUID would not be used for signing the JWT, it's just a way of invalidating a token server-side (in this case, by removing it from Redis). – Blacklight Apr 9 '15 at 8:00

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.