I recently had a need for a login system that needed a ‘remember me’ function. After hours of looking through countless blogs, I came to the conclusion that either (1) people don’t use a remember me function with custom authentication systems for Rails, or (2) they don’t talk about it. In this article, I outline a simple remember me system using the cookie variable in Rails that will tack on to most custom authentication systems.

Using the cookie functions in Rails is pretty straightforward. It’s used with the ActionController and is quite simple to use. Most people use sessions for authentication, which is a good idea. Sessions, unlike cookies, automatically save your content as encrypted strings using the browsers cookies. ActionController#cookie provides a method for saving information in the browser, but you need to hash the content yourself if need be.

However, if a user selects the remember me option when logging in, we would like to have the session expiration set to be a longer period, like 30 days. Unfortunately, this is quite difficult to do if you don’t want to change the expiration of ALL sessions.

My site already uses sessions for authentication, and I’m going to leave that be. In fact, I’m not going to change anything about the session variable at all. This way, I can add this remember function to almost any authentication system I use in the future very easily.

When a user is authenticated and has selected the “remember me” option, I do two things:

- create a cookie that stores (plain text) the user’s id (you can use name, email, etc. but I prefer the id because it says nothing about the user to anyone trying to get information)

- create a second cookie with an hashed string of some other information about the user( name, email, address )
[sourcecode language="ruby"]if params[:rememberMe]
userId = (@user.id).to_s
cookies[:remember_me_id] = { :value => userId, :expires => 30.days.from_now }
userCode = Digest::SHA1.hexdigest( @user.email )[4,18]
cookies[:remember_me_code] = { :value => userCode, :expires => 30.days.from_now }
end[/sourcecode]
For the hashing of the second piece of information, use a hash such as SHA1 or MD5. We can use these two cookies to authenticate a user when they return after a session has expired.
[sourcecode language="ruby"]if ( cookies[:remember_me] and cookies[:remember_me] and User.find( cookies[:remember_me]) and Digest::SHA1.hexdigest( User.find( cookies[:remember_me] ).email )[4,18] == cookies[:remember_me_code] )
@u = User.find( cookies[:remember_me_id] )
session['user'] = @u.id
end[/sourcecode]
Just work that into your :before_filter for your authentication system, and you’re all set. Make sure you delete the variables when someone logs out:
[sourcecode language="ruby"]if cookies[:remember_me_id] then cookies.delete :remember_me_id end
if cookies[:remember_me_code] then cookies.delete :remember_me_code end[/sourcecode]
****Edit: make sure to have “require ‘digest/sha1′” at the top of any page where you are using the SHA1 hash.