mirror of
https://github.com/heartcombo/devise.git
synced 2022-11-09 12:18:31 -05:00
Split out BCrypt hashing to make it reusable
This logic is generic and reusable -- hash a secret; and take an unhashed secret and compare it to a hashed secret. This breaks this out to make it reusable in other places. Specifically, we use this in our own token auth at Bonobos that we plan to split out as a Devise extension. This will make that possible without copy & pasting this code.
This commit is contained in:
parent
a29fee1644
commit
a8769933d1
3 changed files with 29 additions and 16 deletions
22
lib/devise/encryptor.rb
Normal file
22
lib/devise/encryptor.rb
Normal file
|
@ -0,0 +1,22 @@
|
|||
require 'bcrypt'
|
||||
|
||||
module Devise
|
||||
module Encryptor
|
||||
def self.digest(klass, password)
|
||||
if klass.pepper.present?
|
||||
password = "#{password}#{klass.pepper}"
|
||||
end
|
||||
::BCrypt::Password.create(password, cost: klass.stretches).to_s
|
||||
end
|
||||
|
||||
def self.compare(klass, encrypted_password, password)
|
||||
return false if encrypted_password.blank?
|
||||
bcrypt = ::BCrypt::Password.new(encrypted_password)
|
||||
if klass.pepper.present?
|
||||
password = "#{password}#{klass.pepper}"
|
||||
end
|
||||
password = ::BCrypt::Engine.hash_secret(password, bcrypt.salt)
|
||||
Devise.secure_compare(password, encrypted_password)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,13 +1,10 @@
|
|||
require 'devise/strategies/database_authenticatable'
|
||||
require 'bcrypt'
|
||||
require 'devise/encryptor'
|
||||
|
||||
module Devise
|
||||
# Digests the password using bcrypt.
|
||||
def self.bcrypt(klass, password)
|
||||
if klass.pepper.present?
|
||||
password = "#{password}#{klass.pepper}"
|
||||
end
|
||||
::BCrypt::Password.create(password, cost: klass.stretches).to_s
|
||||
ActiveSupport::Deprecation.warn "Devise.bcrypt is deprecated; use Devise::Encryptor.digest instead"
|
||||
Devise::Encryptor.digest(klass, password)
|
||||
end
|
||||
|
||||
module Models
|
||||
|
@ -47,13 +44,7 @@ module Devise
|
|||
|
||||
# Verifies whether a password (ie from sign in) is the user password.
|
||||
def valid_password?(password)
|
||||
return false if encrypted_password.blank?
|
||||
bcrypt = ::BCrypt::Password.new(encrypted_password)
|
||||
if self.class.pepper.present?
|
||||
password = "#{password}#{self.class.pepper}"
|
||||
end
|
||||
password = ::BCrypt::Engine.hash_secret(password, bcrypt.salt)
|
||||
Devise.secure_compare(password, encrypted_password)
|
||||
Devise::Encryptor.compare(self.class, encrypted_password, password)
|
||||
end
|
||||
|
||||
# Set password and password confirmation to nil
|
||||
|
@ -151,7 +142,7 @@ module Devise
|
|||
# See https://github.com/plataformatec/devise-encryptable for examples
|
||||
# of other encryption engines.
|
||||
def password_digest(password)
|
||||
Devise.bcrypt(self.class, password)
|
||||
Devise::Encryptor.digest(self.class, password)
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
|
|
|
@ -14,11 +14,11 @@ class DeviseTest < ActiveSupport::TestCase
|
|||
test 'bcrypt on the class' do
|
||||
password = "super secret"
|
||||
klass = Struct.new(:pepper, :stretches).new("blahblah", 2)
|
||||
hash = Devise.bcrypt(klass, password)
|
||||
hash = Devise::Encryptor.digest(klass, password)
|
||||
assert_equal ::BCrypt::Password.create(hash), hash
|
||||
|
||||
klass = Struct.new(:pepper, :stretches).new("bla", 2)
|
||||
hash = Devise.bcrypt(klass, password)
|
||||
hash = Devise::Encryptor.digest(klass, password)
|
||||
assert_not_equal ::BCrypt::Password.new(hash), hash
|
||||
end
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue