keep 2 auth methods for encryption in rails

class User < ApplicationRecord #...some code here ... has_secure_password validations: false def password=(unencrypted_password) if unencrypted_password.nil? self.password_digest = nil elsif !unencrypted_password.empty? set_encrypted_passwords(unencrypted_password) end end # Because we have some old legacy users in the database, we need to # override #authenticate method for checking if a password is valid. alias_method :old_authentication, :authenticate def authenticate(unencrypted_password) begin old_authentication(unencrypted_password) rescue BCrypt::Errors::InvalidHash auth_with_sha(unencrypted_password) end end private def set_encrypted_passwords(unencrypted_password) @password = unencrypted_password cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine.cost # While keep both encryption methods it will save both password hash for old and new versions self.password_digest = BCrypt::Password.create(unencrypted_password, cost: cost) self.old_password = Digest::SHA512.hexdigest(unencrypted_password) end def auth_with_sha(unencrypted_password) stretches = 20 digest = "" stretches.times{digest = Digest::SHA512.hexdigest(unencrypted_password)} if digest == self.old_password cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine.cost self.password_digest = BCrypt::Password.create(unencrypted_password, cost: cost) self.save return true else # If not BCryt password and not old Authlogic SHA512 password Dosn't my user return false end end end
I had to improve a system that had already been created using SHA512 without salt for saving password. I wanted to improve the method, because using only SHA512 without even a salt part, was really insecure.

I couldn't just change all the password field from the table with the new method because there is an old API that is still using the database with the SHA512 method to check authentication so, while we are migrating to the new API with the new encryption I had to keep both encryption methods.

In Rails, to use BCrypt is necessary to use a gem that handles all authentication and provides methods as: has_secure_password and authenticate, the only thing I had to do was add the field password_digest in the table to save the password hash.

I created the password_digest field and the table already had the other field that I called by aliasing "old_password". Thus, I needed to find the way to save the hash for the new encryption method and the old one, that's why I overwrote the password= method. When it receive a new password it will encrypt it by both methods and will save the hash in each field respectively.

Later, I just overwrote the authenticate method to make sure that if the user is an old user then it could authenticate using the SHA512 method and save the new encrypted hash with Bcrypt in my new field password_digest.

That's all, I could keep both methods while we finish the migration and, at the end, I just going to remove the column "old_password" from the table and return the methods to work normally.

Be the first to comment

You can use [html][/html], [css][/css], [php][/php] and more to embed the code. Urls are automatically hyperlinked. Line breaks and paragraphs are automatically generated.