4

I was just wondering if this would be a reasonable way to write a custom authentication method for a RESTful API. It seems moderately secure, but perhaps I'm way wrong here.

1) Email and Password are sent over HTTPS to my server.

2) Server stores the email, and runs the password through a SHA512 hash with a 256 bit random salt. The hashed and salted password is stored in the database.

So now we have:

email = email@example.com

password = OHqhuewQclakufEjUbZMbowJKEGcvEBz,51c6a3cb58e10754f76e334de064a9dede7875141e1ce0233e3ff14fd7be98a4d5b8fc1c5ab871cb3b1d6b0c9f8073bc3558308511fc4fd6bd049aed5e58a9a4

3) Generate a random token with a lifetime (very random and large), store it the database, and then link that random token to that specific authenticated user.

4) I send the token back to the client through HTTPS (web, Android, or iOS), whereby it's stored in cookies or SharedPrefs or what have you.

5) Now, the client sends the token with every request. The server can then check the cached token value with the one it's receiving each time to make sure that the server always knows who's making requests.

Does this seem reasonable and secure? The issue I think that arises here is if the tokens database ever becomes compromised. Is there perhaps anyway to toughen that one part up?

4

Seems reasonable if step 5 is also done via HTTPS. As for what to do if you suspect the tokens have been compromised, you could store an ExpirationDate for each token and force users to reauthenticate after the token has expired. Upon suspecting a breach, just expire all the tokens immediately.

  • Oh, sorry just one more question. Should the token be truly random, or should I base it on the user ID? – Kris Dec 14 '15 at 18:25
  • You are already linking the token to a user in the tokens table so it doesn't matter. Completely random is fine. For example, your Tokens table might have fields of: Token, UserID, CreatedDate, ExpirationDate. When you verify the token is valid, you'd be able to get the UserID. – TTT Dec 14 '15 at 18:30
  • It could be based on the user id, but hash it. Otherwise any user could deduce the tokens for other users. – ThoriumBR Dec 14 '15 at 18:32
1

Your token idea is fine but the password hashing is horrible. You're using a fast hash, the salt helps a bit but that's sill insecure; you should use a slow hashing function especially designed for passwords like bcrypt.

Most web frameworks provide ready-to-use authentication functions that use the most secure methods available, so don't reinvent the wheel and instead rely on widely used well-tested code. Not using a framework yet? Think about using one, it'll save you quite a lot of time.

  • Hm, you seem to be correct. Other than iterating many times using SHA512 (which isn't testing that well), Blowfish is the way to go. Alright, I'll go with bcrypt. Thanks – Kris Dec 14 '15 at 21:54
  • 1
    @Although I agree with this answer, I'm not sure if it matters for this application. If someone hacked into the DB and got a dump of the hashes, then whatever the API tokens are protecting would already have been compromised, which means it wouldn't be necessary for an attacker to obtain the passwords. Unless their goal was simply to get the passwords in the first place for attempting to match them on other sites. Presumably though whatever the API is protecting is more valuable than the passwords... (OP will have to decide this.) – TTT Dec 14 '15 at 23:13
0
  1. As André Borie already stated: Please use a hashing algorithm designed for passwords. Be aware that the passwords you are storing are not yours. They're very sensitive information provided by the user. You can advise the user to not reuse the password but it's wrong to assume that they will comply with it. Furthermore they will blame you if your service got compromised and the passwords get cracked.

  2. Consider encapsulating the authentication in an extra service which is separated from your API. This can help to reduce the attack surface.

  3. You can encapsulate the storage of the salt in another system which is not reachable from other hosts. There you create a service which outputs a salt for a given user id or any other information which is unique for an account. If your database is dumped, the salts are not part of it which makes the cracking almost impossible. In order to get access to the salt, an attacker would need to have code execution privileges and the authentication information for your service. (Assuming the attacker already knows that you are using external salts)

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.