This web application will have a database table with columns uniqueid (64-bit int autoincrement field; key), token (64-byte binary field), and an accountid.
After logging in with "Remember Me" checked, a random token will be generated. Then the SHA-512 hash of this token will be inserted into the database and the generated uniqueid retrieved. A cookie that contains the uniqueid and unhashed token is sent to the client.
Every time a user visits the page with the cookie, the cookie's uniqueid and its token's SHA-512 hash with be checked against the database. If there is a row that matches the uniqueid, and that row's token hash matches the token hash, log in the user with the row's accountid. After every authentication attempt made by the cookie, delete the row that uses the old uniqueid and, if the authentication was successful, generate a new random token. Then the SHA-512 hash of this token will be inserted into the database and the generated uniqueid retrieved. A cookie that contains the uniqueid and unhashed token is sent to the successfully authenticated client.
I will be using the techniques described here as well. All failed cookie authentications will have the cookies set to blank values and expiration date set to sometime in the past.
I believe this method would address a few concerns regarding cookies. Namely:
The token in the database is hashed so that as long as an attacker does not have write access to the database, he/she will not be able to forge cookies of all users.
Unique IDs are used instead of a user's account name because login credentials should never be stored in a cookie.
A random token is generated every time the cookie is authenticated so that if an attacker steals a cookie, it will only be valid until the user next logs in rather than for the entire time the user is remembered.
Cookies will be difficult to sniff because my entire application uses HTTPS.
I can further enhance security by allowing the user to specify how long he/she wants to be remembered for. The expiration date will be stored in the same database table that stores uniqueid and tokens. Every time a new cookie is created, this expiration will be sent with the cookie. If a user tries logging in with a cookie that the server deems expired but the client still holds, the log in will be denied.
I believe this solution is reasonably secure, but are there any pitfalls or things that I have overlooked when I designed this method?
Sources:
Don't store account name in cookies and use new unique id after every authentication