Rails, authlogic and password history
Posted under: Behind the Scenes
vendorrisk.com client sites use the excellent Authlogic gem to handle user sessions. As mentioned in the previous blog article, we recently added the ability for site admins to declare that users cannot use a password they’ve used in the past.
After a bit of Googling, I didn’t see any solutions out there for dealing with this issue, so we rolled our own. Here’s how we went about it. Note that we’re assuming you already have Authlogic integrated into the app with “User” being the model authenticated, although changing to another model should be self-explanatory.
Database migration
create_table "old_passwords" do |t| t.integer "user_id", :null => false t.string "password_salt", :null => false t.string "crypted_password", :null => false t.timestamps end
OldPassword model
class OldPassword < ActiveRecord::Base belongs_to :user end
User model (relevant snippets only)
class User < ActiveRecord::Base
acts_as_authentic
has_many :old_passwords
validates_presence_of :password, :on => :create
validate :password_meets_requirements
after_create :create_password_history
after_update :update_password_history
def password_meets_requirements
return true if password.blank?
# do other password-specific validations here, if any
if not new_record? and already_used?(password)
errors.add_to_base("Password cannot be one you have used in the past")
end
end
def already_used?(password)
old_passwords.each do |old|
return true if Authlogic::CryptoProviders::Sha512.matches?(old.crypted_password, password + old.password_salt)
end
return false
end
def create_password_history
old_passwords.create(:crypted_password => crypted_password, :password_salt => password_salt)
end
def update_password_history
create_password_history if password_changed?
end
end
Explanation
When a user record is first created, there is no need to validate their selected password because there are no past entries to check it against. For new users, we just add their password to the historical table, which is accomplished with the after_create callback.
When a user record is being updated, it gets a little more complex. If the password is blank, then the validation passes because the user’s password is not being changed; otherwise, the new password is checked against the old passwords for the user. If a match is found, an error message is created and the user record will not be updated. If the new password does not match any old passwords, then validation succeeds and the new password is added to the historical table in the after_update callback. The password_changed? method is provided by Authlogic.
Hope this helps. In short, there’s two functions being done: 1) adding the user’s encrypted password to a database table when they enter a new password and 2) querying that table when they attempt to change their password.
One Comment to “Rails, authlogic and password history”
Leave a Reply

Sweet! I was just in the process of coding this myself when I ran across your implementation. You just saved me a couple of hours!