Getting Rails 3.1 has_secure_password to work with OmniAuth

I am moving the project from Rails 3 to 3.1. My authentication system was easily switched to the new has_secure_password in ActiveRecord. The only problem I encountered is that I also use OmniAuth and I have a system installed, so if a user signs up using one of the OmniAuth providers, the account does not need a password. I can't seem to override the password_digest validations settings with has_secure_password. In any case, to disable these checks and write my own, or will I just have to use my old hand-written bcrypt functions from my version of the Rails 3 site?

+8
source share
2 answers

In the end, I returned to using custom methods. However, after that, I realized that I had to use the before_validation callback to check the conditions, and then, if they match, set password_digest to something simple, like "0". Thus, the digest will never be empty, but at the same time, it should never be checked as the correct password, forcing them to enter through OmniAuth.

Feel free to correct me if I am wrong.

+5
source share
Scott, your idea is correct. I struggled with this problem to no avail. I tried to override 'has_secure_password' and it just won't work. No matter where I pasted the code.

Instead, I have the following:

class User < ActiveRecord::Base has_secure_password validates_presence_of :password, :on => :create, :if => :password_required # Associations has_many :authentications # Callbacks before_validation :no_password_omniauth # Gets set to true if the caller is trying to authenticate with omniauth. @called_omniauth = false # Build new omniauth users def apply_omniauth(omniauth) authentications.build( :provider => omniauth['provider'], :uid => omniauth['uid']) self.first_name = omniauth['user_info']['first_name'] if self.first_name.blank? self.last_name = omniauth['user_info']['last_name'] if self.last_name.blank? self.email = omniauth['user_info']['email'] if omniauth['user_info']['email'] && self.email.blank? @called_omniauth = true end def password_required return false if @called_omniauth == true (authentications.empty? || !password.blank?) end private def no_password_omniauth self.password_digest = 0 unless password_required end end 

The apply_omniauth method is called from the controller when someone tries to authenticate or register.

Thanks for the idea you nailed.

+4
source share

All Articles