Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

Assuming you already have a website that implements all of the standard login stuff, what is the correct and most secure way to allow users to automatically be logged in for a certain time period (let's say 30 days)? This time period should be strictly enforced; ie, I don't think a valid solution would be giving a cookie an expiration date and hoping the user's browser deletes it in a timely manner.

Details of the existing login system:

  • A user must enter a user name and password
  • The database stores usernames as well as strong_hash_function(password + user_specific_random_salt)
  • Login forms are loaded and submitted over SSL, as are all subsequent pages

There are many examples out there and many with obvious security flaws. Let's use PHP as the target language but the concepts should be applicable to any language.

share|improve this question
    
possible duplicate of Good session practices –  Bubby4j Nov 11 '10 at 22:33
    

5 Answers 5

up vote 18 down vote accepted

There are two parts to my answer:

First, assuming your threat model does not worry about exposure of client side cookies, you can generate and store a nonce on the server side, hash that with the username and other info (e.g. client ip, computername, timestamp, similar stuff), and send that in the cookie. The nonce should be stored in the database, together with expiry date, and both checked when the cookie comes back.
This should be a "rememberance" cookie only, NOT a session cookie - i.e. when you get that cookie without a session, reissue a new, regular session cookie. Also note that like the session cookie, this should be delivered only over https, and using the secure and httpOnly attributes, and of course have the cookie scoped properly etc.

Second, for users that were remembered, you should (probably, depending on sensitivity) invoke a reauthentication process for certain sensitive operations. That is, sometimes they would need to put their password in again anyway, but seldom, and only for sensitive operations. This is to prevent attacks such as CSRF and shared desktop exposure.

share|improve this answer
4  
See Amazon for an example of the second part! –  adamse Nov 19 '10 at 11:54
1  
@adamse, nice, I usually refer to LinkedIn. Amazon even better :) –  AviD Nov 19 '10 at 12:11
    
Only the hash of the nonce should be stored in the database. –  Jacco Nov 30 '12 at 0:44
    
@Jacco you need to store the expiry date, so you know till when it is valid. Assuming you want it to expire after a limited time... –  AviD Nov 30 '12 at 0:54
1  
I meant to say that, because the nonce is a password equivalent, instead of the nonce, only the hash of the nonce should be stored in the database. Offcourse you also need to store things like expiration date and/or userId, etc. –  Jacco Nov 30 '12 at 13:23

This article describes an approach that defends against cookie theft and guessing of session IDs:

  • A "remember me" cookie consists of the user ID, a token (big random number) and a sequence token (another big random number).
  • When a user presents the cookie, the database is searched for these three pieces of information.
    • If found, the sequence token is regenerated, stored in the database and sent to the user
    • If only the username and the token are found, it is presumed that someone else has stolen the cookie because the sequence token was already used. The system can then warn the user and/or delete all stored tokens from this user from the database.

As an additional security measure it is advised that critical actions like changing the login data or paying for things request the password, if the user was only authenticated with the "remember me" cookie.

The database table that contains the user id and tokens also contains the expiration date of the tokens. It could also also contain the user agent and IP address so an attacker has to replicate these as well. All tokens should only be stored as hashes because they basically work like passwords and would enable an attacker, who obtained to database, to login.

I have created a sample implementation for PHP.

share|improve this answer
1  
Please don't post an answer whose content is effectively just a link. At least summarize the approach from the article directly in your answer. If you'd like to get advice about this article, ask a question about it. –  Gilles Jan 4 '13 at 14:02
1  
Thanks. I've expanded my answer and retracted my question. Comments are welcome. –  chiborg Jan 4 '13 at 14:47
    
Good thing you expanded your answer, the link to the article is now broken. –  phq Apr 7 '13 at 23:06

A common approach would be to use a strong encryption algorithm to store a cookie containing the following information on the user's computer:

AES([Expiry date] + [random salt] + [Username] + [Password])

That would allow the user to invalidate the cookie (if it was compromised) by simply changing their password. Encrypting it allows the site operator to verify that it has not been tampered with (extending the expiry date, for example), as well as protecting the clear text password from compromise. Including the password means that an attacker who gains access to the AES key can still not "mint" tokens to authenticate as arbitrary users.

The downside is then that the site has to protect an AES key.

An alternative approach would simply be to add two fields to your user database, for a cookie value (long/strong/randomly generated value), and an associated expiry date. Any user presenting that cookie would be authenticated, up to the expiry date. One would just need to make sure on the server side that operations such as changing a password removes any "remember me" cookies stored in the database.

Advantages of this approach are that there is no encryption key to manage (or worry about rolling over), and that there is no possibility of the user's password being compromised. Disadvantages are that you need additional storage for your users.

On the further plus side, this approach allows you to provide different "remember me" tokens on different devices (a la Google Account manager), simply by storing the tokens in a separate table and allowing more than one entry per user. This then makes it possible to track where each is used from, and invalidate them individually.

share|improve this answer
2  
This answer is not correct. Encrypting does not allow a site operator to verify that it has not been tampered with. This is a fundamental and basic confusion about the distinction between confidentiality vs authenticity/integrity. –  D.W. Jan 8 '11 at 1:58
1  
-1 You are proposing to transfer the end users password over the wire and store it on his harddisk? No, don't do that, it is absolutely wrong even though you use AES encryption. If an attacker can obtain a cookie, you're giving him unlimited attempts at obtaining the end users password in plaintext, i.e. getting of the most security-critical pieces of information. I assume you mean a hash of the password inside the AES (which isn't clear from your writing), and even that is not ideal. –  Jesper Mortensen Apr 25 '11 at 21:17
    
@D.W. Encrypting DOES allow a site operator to verify that it has not been tampered with. If the decryption results in garbage, it has been tampered with. If it results in valid data, it has not been tampered with. –  Rogan Dawes Aug 16 '11 at 18:42
    
@Jesper There is an insignificant difference between storing an AES encrypted version of the password, and a hashed version of the password. In both cases, the attacker can attempt to brute force a random AES key. Adding the additional step of then brute forcing the hashed password does not really add all that much, given how easy passwords are to brute force these days. At least a suitably long AES key should keep them busy for a while. –  Rogan Dawes Aug 16 '11 at 18:46
1  
@Rogan, you are wrong. Using cryptography properly is more subtle than you may realize. –  D.W. Aug 16 '11 at 18:54

You don't have to depend on the browser to delete the cookie, you have the site check the expiration date on the cookie.

In fact, for this to be secure, I'd say that's probably what you're going to have to do anyway, because you would want to set the expiration date as a part of the cookie value and encrypt it rather than rely on the plain-text expiration property of the cookie itself.

And you would really want to either mark the cookie as secure, and use a secondary cookie for the duration of an individual session, or protect the entire session (not just the login process) with SSL to prevent the cookie from being stolen off the wire and used by an unauthorized party.

share|improve this answer

That's an interesting question. I'll start off by saying that I'm not sure it can be done without some weakening of the security of the application, but then depending on the site that may be considered worth the trade-off.

So one approach could be

The session state database will need to record the time that a token is set and the duration that it should be remembered so that it can compare the token presented.

When the user logs in to the application they have a check-box which allows them to stay logged in (ideally with a range of time periods for the user to select)

When the session token is set, that time period is used as the cookie expiry. On subsequent visits the cookie will be presented to the application, and the server will need to check whether it is still valid (ie the expiry period for the remember me function hasn't been hit). If the token is still valid, the user is treated as authenticated, if not then the token is cleared and the user is redirected to the login screen.

Problems with this approach. Shared browsers would mean that the unauthorised access is possible.

Also anyone that can get access to the cookie (either through a vulnerability in the site, a browser issue or through malware planted on the machine) will be able to get unauthorised access to the site. One common suggestion for mitigating this is trying to tie the cookie to a source IP address (encrypted or stored on the server of course) which is checked when the user presents the cookie, however this causes problems with large corporate environments where a user may come from a number of IP addresses, and also may be susceptible to spoofing.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.