-
Notifications
You must be signed in to change notification settings - Fork 5.5k
How To: Create a custom encryptor
When working with a legacy database where a non-supported password encryption method is used, you can implement a custom encryptor by loading the following in an initializer. (That means it goes in config/initializers/md5_encryptor.rb
for example).
module Devise
module Encryptors
class Md5 < Base
def self.digest(password, stretches, salt, pepper)
str = [password, salt].flatten.compact.join
Digest::MD5.hexdigest(str)
end
end
end
end
The above will authenticate using non-salted MD5-hashed passwords (a terrible idea, but such are legacy apps). You can then set this as your encryptor in config/initializers/devise.rb
:
config.encryptor = :md5
If you do not want this as an initializer, but in lib/md5.rb for instance, add this to your users' class. require File.dirname(__FILE__) + '/../../lib/md5_encryptor'
See also: http://www.markrichman.com/2010/11/22/rails-devise-datamapper-authentication/
Additionally, I had to add the following to my user model in order to be able to log in. Supposedly there is a more elegant way, but I did not get devise_for ... :encryptor => :md5
to work. nor devise :encryptor => :md5
. Maybe this is because I do not have a password salt.
+++ b/app/models/user.rb + # debt: we should not need to do this, but seems like setting :encryptor => :md5 on the devise or devise_for + # does not do anything. Maybe because we don't use a salt. So this works for now. + def valid_password?(password) + return false if encrypted_password.blank? + Devise.secure_compare(Devise::Encryptors::Md5.digest(password, nil, nil, nil), self.encrypted_password) + end
And how I tested it.
+++ b/spec/models/user_spec.rb + describe "devise valid_password?" do + it "should use our hashing mechanism, not the default bcrypt" do + Factory(:member).valid_password?('blahblah').should be_true + end + end