According to this answer, a valid login token schema would consist of

  1. the username (U)
  2. the time of issuance (T) and
  3. secret key K owned by the server only

The suggestion then is to concatenate the values as following:

token = U+T+hmac("sha256", U+T, K)

Does this mean the server would have to split the token to validate it, take the username and the time, rebuild the hash (with the same key) and then compare the new build hash to the provided hash in the token? Isn't it a problem to sent the username and time in plain text? Wouldn't it make more sense to encrypt the userid and time as well (and decrypt it for validating the token)?

1 Answer 1


Say, you're user "bob". You log in with your password on 2014-07-30H12:00:00 and the server, using your scheme, sets your cookie token to:

enc("bob", K)+enc("2014-07-30H12:00:00", K)

However, bob is malicious. While his boss Alice is away from her desk, he checks her browser cookies and finds out her token:

enc("alice", K)+enc("2014-07-30H13:00:00", K)

Bob doesn't need to know the secret key K on the server, since the value of enc("alice", K) never changes, so all he needs to do in order to spoof being user "alice" at any time in the future is to change his own cookie to replace the output of enc("bob", K) with the output of enc("alice", K).

The scheme with the hmac suggested above is not vulnerable to this attack. The server's returned token is something like this:


Bob can try to change "bob" to "alice", but when the server performs the validation calculation, the calculated sha256 hash won't match, and it will be obvious that either the username or timestamp have been tampered with. Bob cannot possibly calculate the hash, since he doesn't know the secret key used by the server.

The validation operation of split() and hmac() are extremely fast and take microseconds to perform. They will probably be faster than decrypting the tokens. Obviously, you'd be sending the token over a safe channel, such as over https using a secure cookie, so there is little need to additionally encrypt the username and timestamp in addition to the hmac.

Edited to add:

Even if you use the following instead:

enc("bob"+"$"+"2014-07-30H12:00:00", K)

this is still not good enough. Getting encryption just right is extremely difficult and the chances are there will be weaknesses in your implementation (all tokens issued to "alice" will start the same way unless you do the right thing with randomness and initialization). Since the attacker will know both the plaintext and cryptotext, there is a number of attacks they can try to figure out what the value of K is, unless you use the right algorithm with correct initialization parameters.

Furthermore, all good crypto always incorporates hmac for integrity checking anyway, so by attempting to simplify the process you'll end up either weakening it, or making it more complicated and computationally intensive.

Just stick to the username+timestamp+hmac(sha256, username+timestamp, K) recommendation and transfer it to the client over a secure channel. It's a scheme that known to work well.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .