I have a situation in which I cannot use a server-side session, but must allow users to log in, and for their logged in state to be persistent between queries.
As with anything that involves crypto of any kind, I know how easy it is to make a mistake and just wanted some extra pairs of eyes to look over what I am proposing.
u = the unique, numerical user id s = a global server-side secret composed of a long, random, alpha-numeric string, 64 characters or more
Upon login, I propose to set two cookies on the client.
- The User ID: u
- The Authentication Token: hash(u + s)
Upon subsequent requests, the server will use the given value of u and the known, secret value of s to calculate and compare against the given authentication token. If they match, this must be a valid user, right?
An attacker cannot generate an authentication token without knowing the secret, and so cannot generate a token for someone else's user account.
If I make the cookies relatively short-lived, an hour perhaps, and provide cookie-destroying logout functionality, even shared computers would be relatively secure.
The global secret s could be changed (perhaps by a daily cron-job) to protect against a long term brute-force on a known hash/userID pair.
Does this sound ok?
In reading that through again, I realise the introduction of a timestamp would be very helpful. So a third cookie with the timestamp, and the hash would need to include the timestamp, the userID and the secret. Then a TTL could be set on the authentication token, and cookie expiry (which is not a remotely secure revocation method anyway) would no longer matter.