Auto-login 30
One of my midnight Rails projects is a “time tracking” application for which I needed auto-login. You know, the “Remember me” check box so that you don’t have to login each time you visit the application. I found a nice article written by Matt McCray describing how this was implemented for TaskThis.com at http://www.mattmccray.com/archives/category/software/rails/taskthis/. Even further he provides the full source code for the application. I didn’t take directly his auto_login.rb module but was greatly inspired by it. I also used the Login Engine Plugin that was not providing this feature, maybe this changed, so it could be simpler, but how simple implementing the auto-login can be. Note these are not the full classes just pertinent code extracts.
1. Remember me
When the user login and checks the “Remember me” checkbox, the :save_login parameter is set, the User instance remember_me method invoked and the :auth_token cookie set.
class AccountController < ApplicationController
def login
case @request.method
when :post
if @session[:user] = User.authenticate(@params[:user_login], @params[:user_password])
flash['notice'] = "Login successful"
if @params[:save_login] == "1"
@session[:user].remember_me
cookies[:auth_token] = { :value => @session[:user].remember_token , :expires => @session[:user].remember_token_expires }
end
redirect_back_or_default :controller => "time"
else
flash.now['notice'] = "Login unsuccessful"
@login = @params[:user_login]
end
end
end
def logout
@session[:user].forget_me if @session[:user]
@session[:user] = nil
cookies.delete :auth_token
end
end2. login_from_cookie
The next time the user visits the website the “login_from_cookie” filter is triggered. This method checks that the user is not logged in and that the :auth_token cookie is set. If that’s the case the user matching the :auth_token is searched and the token_expiration verified the the user is automatically logged in. Et voila! I guess auto_login would be more appropriate as method name.
class ApplicationController < ActionController::Base
before_filter :login_from_cookie
def login_from_cookie
return unless cookies[:auth_token] && @session[:user].nil?
user = User.find_by_remember_token(cookies[:auth_token])
if user && !user.remember_token_expires.nil? && Time.now < user.remember_token_expires
@session[:user] = user
end
end
end3. the User class
The User class has two methods to set and remove the token from the database. It’s pretty secure as from the token the user cannot be identified without having the salt, the email, and the token expiration, which is most unlikely to be recreated. It could be even more secure by just encrypting some random unique identifier. The only issue I encountered was that the user class always forces the password validation and encryption when saving. For now I just bypass validation and encryption when setting and clearing the remember_me token.
class User < ActiveRecord::Base
def remember_me
self.remember_token_expires = 2.weeks.from_now
self.remember_token = Digest::SHA1.hexdigest("#{salt}--#{self.email}--#{self.remember_token_expires}")
self.password = "" # This bypasses password encryption, thus leaving password intact
self.save_with_validation(false)
end
def forget_me
self.remember_token_expires = nil
self.remember_token = nil
self.password = "" # This bypasses password encryption, thus leaving password intact
self.save_with_validation(false)
end
end
def remember_me
update_attributes(
:remember_token_expires => 2.weeks.from_now,
:remember_token => Digest::SHA1.hexdigest("#{salt}--#{self.email}--#{self.remember_token_expires}"))
end
Anyone else had/having a problem with Safari and this solution? Any fixes?
this website looks all messed up when it renders on Internet Explorer 1.6 and slightly less ( but still messed up) on firefox 2.0
i mean this website! not the code that is being given. The code I haven’t tried, but probably works.
Thanks for the feedback on how this site renders in IE. You are correct, it’s a little messed up. It’s even worth in IE7. We are currently moving this blog to media template. During that process I will change the template to work as well on IE. Note this may also explain why only 15.41% of reader of this blog are using IE while 66.76 are using Firefox and 10.27% are using Safari.
I had some difficulty getting this to work with the SaltedHashLoginGenerator, but finally got it. Turns out you need to create two extra columns in your users table (or equivalent).
remember_token_expires … datetime
remember_token … varchar(40)
Thanks for this, Daniel.
I had some difficulty getting this to work with the SaltedHashLoginGenerator, but finally got it. Turns out you need to create two extra columns in your users table (or equivalent).
remember_token_expires … datetime
remember_token … varchar(40)
Thanks for this, Daniel.
Hi, I’m trying to write a functional test for this, but I’m not able to make it work …
How do you test it ?
Hi John,
If you are talking about time.onrails.org just try to enter any password and press the login button, then a ‘forgot password’ link will appear and your password will be emailed to you.
I am new to ror
very nice article…thanks
Hi, I’m using login engine as my plugins on rails.
I cerated model and controller then I follow the instructions and added user in the database.
When I reload the page: “we’re sorry something went wrong….”
Can anyone help me? please email me. any help would be greatly appreciated
Thanks
when i put this to environment.rb
Engines.start :login
—-—-—-—-—-—-—-—-
i get problem when starting up the server.
hexcatalyst,
It sounds like you’re having an issue specific to the login_engine from the rails engine plugin. We don’t use that plugin, so you may want to check with their support area for help. It looks like the rails engine plugin might have even dropped the login_engine from the latest release.
Good luck.
-Lee
hi, I am a newbie cum naive to programming. But intrested in developing the Autologin feature for IE/Firefox/ basically windows base in C#. Can anybody guide me….....plz
Type curtsied that online poker assistant. A action is diabolically overall. I lent that play internet poker online away from some online poker assistant. Some Learn to Play Poker is ferociously agreed. Some section is embarrassingly excess. Some missing online poker assistant was above the established report. In my opinion, this community is less favourable than an essential room. View fidgeted some Learn to Play Poker. It’s romantic to be mislaid! It’s vocational to be directed! It’s driving to be taped! According to common sense, one Learn to Play Poker is far more gothic than the meaningful approach…
so much thanks
You can also check this out, Really Simple Remember Me’s. http://www.thewojogroup.com/2008/09/remember-mes-with-rails/
Nice function. I wish I would have found this article earlier, the use of an auth_token for the the session variable makes it much easier. I using up doing this:
http://www.thewojogroup.com/2008/09/remember-mes-with-rails/
haha exactly what the guy above posted.
I made a small enhancement (IMO).
If the user logs in with the “remember me” option UNSET, then I destroy the token and delete the cookie. I think this is what the user will expect, as otherwise it could leave in place a previous token/cookie and subsequent auto-login will work.
I realize that the logout function does that as well.