Every resource I find (I, II, III) about how to implement in a secure way the typical "remember me" login feature, recommends storing a user identifier and an associated unique token in the cookie, and then the hashed token associated to the user in the database. This way we are safe of:
- User impersonation. Should we store
remember_me_user_id=93
in the cookie, it would be quite possibly to log in as admin crafting a cookie withremember_me_user_id=1
. Adding the unique token to the cookie prevents from that. - Timing attack. The user identifier is used to look up the user, so the time elapsed is indifferent because it is searching but not authenticating. Should we look up by the unique token, the time information could be used to craft a valid token character by character.
- Rainbow attack. The token is stored hashed in the database, so if the table information gets compromised it is useless.
But what about if we just store the user identifier in a cookie signed using a server secret? As far as I see, it prevents from the very same kind of attacks:
- User impersonation. The cookie is signed, so an attacker can't craft another valid one without the server side secret.
- Timing attack. The cookie is signed, so the attacker can't create it step by step.
- Rainbow attack. No token stored in the database, no worries.
And, as far as I see, it has the same dangers that the cookie with the token:
- You have to trust that the browser will expire the token when the time arrives. Solution: Timestamp the cookie and compare the time in the server.
- XSS attack. Solution: Mark the cookie as
http_only
. - Eavesdropping. Solution: Mark the cookie as
secure
and usehttps
. - Having a long lived cookie which is able to authenticate a user is very dangerous. Mitigation: 1) Refresh the cookie and token at every X requests in a server token based solution (it will still last all the period if the user does not come back). 2) Refresh the cookie and extend its timestamp at every X requests in any of both solutions (then you are "remembering" for a shorter period if the user doesn't come back).
Is my rationing correct or am I missing something?