2

I write back-end code for mobile applications. I am needing to write the code for authentication and the simplest yet secure solution I can think of is:

  • When user signs in, device sends username and password to server
  • If credentials are valid server returns token
  • User sends token with every request

Details about token

  • In Java I can create token as UUID (which is created using SecureRandom under the hood)
  • I write this token into DB in users table in user row
  • On every mobile application request I make SELECT ... FROM users WHERE token = ? and check if current user is allowed to perform operation
  • Periodically I change token in users table to expire previous token

Is it good enough?

It seems secure, but I'm not a security expert so I thought I'd ask here. I haven't seen this solution before and I am wondering why.

  • Someone would complain about performance because of hitting DB every time but in real application every request generates a lot of SQL queries so one more shouldn't be a problem.
  • Someone could complain about UUID, but as far as I know in Java UUIDs are presumed impossible to guess because of the implementation of SecureRandom.

Is this solution secure or are there any holes I couldn't see?

guest
  • 121
  • 2
  • 2
    That seems like the right general approach. I will be the person who complains about UUID: they are not meant to be used as secrets. Why not just use `SecureRandom` directly and avoid the hassle of trying to guess whether UUID is random or not? – Mike Ounsworth Sep 18 '18 at 13:44
  • 1
    Seems like a duplicate of https://security.stackexchange.com/q/190526/113999 and https://security.stackexchange.com/q/157270/113999. – nbering Sep 18 '18 at 13:45
  • What if I have multiple devices I want to have logged in? Besides that I'll just echo what Mike Ounsworth said, just use `SecureRandom` directly. – AndrolGenhald Sep 18 '18 at 13:47
  • 1
    I've already expressed the opinion in the past that the UUID specification is not trying to solve security problems. It's trying to solve the problem of collisions on randomly generated values. So for a UUID implementation to be completely unguessable, it would have to sacrifice some of it's ability to avoid collisions. – nbering Sep 18 '18 at 13:48
  • 1
    Are you checking that the value supplied as a token is actually a token? For instance, could someone malicious change it to `' or 1=1 --` and get an SQL injection? The token is user provided data in the comparison step, even if it comes from your application which is running on someone else's device. – Matthew Sep 18 '18 at 13:53
  • One token would be shared between all user devices. – guest Sep 19 '18 at 06:23

1 Answers1

2

I have one main concern with your setup: You should hash the UUID tokens! Otherwise, if your database leaks all accounts will be exposed. Given the amount of entropy in a securely generated UUID, a simple hash function as SHA-256 will do the job.

A few minor points.

Using a UUID as an authentication is not wrong from a security perspective, as long as you are 100% sure that it uses a secure random source (and the Javadoc seems to agree with you on that). To make the code more explicit, personally I would generate the token directly from the random source without mixing in any UUID. But that is mostly to make the code cleaner.

Make sure that you are using a version 4 UUID. The other versions are not random!

Also, I would keep the tokens in a separate table and not in the users table. But that is more about database normalisation than it is about security.

You should think about when you expire tokens. If you have some kind of log out feature, the token should expire when the user log out. In the same way, if the user is logged out when the app is closed, the token should expire when the app is closed.

Anders
  • 64,406
  • 24
  • 178
  • 215
  • This token will be shared between user devices, so I can't expire token on user log out, because it would log out him from another device. – guest Sep 18 '18 at 14:00
  • 3
    @guest That sounds like a bad approach. You should have one token per session (i.e. user + device combo), and not one token per user. – Anders Sep 18 '18 at 14:04
  • Why is it bad idea? It is similar approach to old school cookie authentication I believe. – guest Sep 19 '18 at 06:14
  • 1
    @guest It's not good for cookies either. You can't log out individual devices. You can't check that requests seems to come from the actual device that is logged in. If something bad happends, it's harder to locate the breach. And you are forced into a situation where you can never change the token without having the user log in again on all devices. – Anders Sep 19 '18 at 06:26