diff --git a/CHANGELOG.rdoc b/CHANGELOG.rdoc index ee00a483..45d681de 100644 --- a/CHANGELOG.rdoc +++ b/CHANGELOG.rdoc @@ -1,4 +1,19 @@ -== 1.1.rc1 +== 1.1.0 (to be released) + +* enhancements + * Allow to set cookie domain for the remember token. (by github.com/mantas) + * Added navigational formats to specify when it should return a 302 and when a 401. + * Added authenticate(scope) support in routes (by github.com/wildchild) + * Added after_update_path_for to registrations controller (by github.com/thedelchop) + * Added anybody_signed_in? helper (by github.com/SSDany) + +* bug fix + * confirmation_required? is properly honored on active? calls. (by github.com/paulrosania) + +* deprecations + * bcrypt is now the default encryptor + +== 1.1.rc * enhancements * Rails 3 compatibility. @@ -17,10 +32,6 @@ * Allow :unlock_strategy to be :none and add :lock_strategy which can be :failed_attempts or none. Setting those values to :none means that you want to handle lock and unlocking by yourself. * No need to append ?unauthenticated=true in URLs anymore since Flash was moved to a middleware in Rails 3. * :activatable is included by default in your models. - * Allow to set cookie domain for the remember token. (by github.com/mantas) - * Added navigational formats to specify when it should return a 302 and when a 401. - * Added authenticate(scope) support in routes (by github.com/wildchild) - * Added after_update_path_for to registrations controller (by github.com/thedelchop) * bug fix * Fix a bug with STI. diff --git a/Rakefile b/Rakefile index 08c45278..5e793cc8 100644 --- a/Rakefile +++ b/Rakefile @@ -46,6 +46,7 @@ begin s.files = FileList["[A-Z]*", "{app,config,lib}/**/*"] s.extra_rdoc_files = FileList["[A-Z]*"] - %w(Gemfile Rakefile) s.add_dependency("warden", "~> 0.10.5") + s.add_dependency("bcrypt-ruby", "~> 2.1.2") end Jeweler::GemcutterTasks.new diff --git a/lib/devise.rb b/lib/devise.rb index f6a85439..ebf56a81 100644 --- a/lib/devise.rb +++ b/lib/devise.rb @@ -97,7 +97,7 @@ module Devise # Used to define the password encryption algorithm. mattr_accessor :encryptor - @@encryptor = :sha1 + @@encryptor = nil # Store scopes mappings. mattr_accessor :mappings diff --git a/lib/devise/encryptors/authlogic_sha512.rb b/lib/devise/encryptors/authlogic_sha512.rb index 9c4be984..c8482974 100644 --- a/lib/devise/encryptors/authlogic_sha512.rb +++ b/lib/devise/encryptors/authlogic_sha512.rb @@ -7,7 +7,6 @@ module Devise # Warning: it uses Devise's stretches configuration to port Authlogic's one. Should be set to 20 in the initializer to silumate # the default behavior. class AuthlogicSha512 < Base - # Gererates a default password digest based on salt, pepper and the # incoming password. def self.digest(password, stretches, salt, pepper) @@ -15,7 +14,6 @@ module Devise stretches.times { digest = Digest::SHA512.hexdigest(digest) } digest end - end end end \ No newline at end of file diff --git a/lib/devise/encryptors/bcrypt.rb b/lib/devise/encryptors/bcrypt.rb index b8a9a101..46b40136 100644 --- a/lib/devise/encryptors/bcrypt.rb +++ b/lib/devise/encryptors/bcrypt.rb @@ -5,7 +5,6 @@ module Devise # = BCrypt # Uses the BCrypt hash algorithm to encrypt passwords. class Bcrypt < Base - # Gererates a default password digest based on stretches, salt, pepper and the # incoming password. We don't strech it ourselves since BCrypt does so internally. def self.digest(password, stretches, salt, pepper) @@ -15,7 +14,6 @@ module Devise def self.salt ::BCrypt::Engine.generate_salt end - end end end diff --git a/lib/devise/encryptors/clearance_sha1.rb b/lib/devise/encryptors/clearance_sha1.rb index dbe396b9..33d39fb9 100644 --- a/lib/devise/encryptors/clearance_sha1.rb +++ b/lib/devise/encryptors/clearance_sha1.rb @@ -7,13 +7,11 @@ module Devise # Warning: it uses Devise's pepper to port the concept of REST_AUTH_SITE_KEY # Warning: it uses Devise's stretches configuration to port the concept of REST_AUTH_DIGEST_STRETCHES class ClearanceSha1 < Base - # Gererates a default password digest based on salt, pepper and the # incoming password. def self.digest(password, stretches, salt, pepper) Digest::SHA1.hexdigest("--#{salt}--#{password}--") end - end end end \ No newline at end of file diff --git a/lib/devise/encryptors/sha1.rb b/lib/devise/encryptors/sha1.rb index ecc0968f..3dad6b1b 100644 --- a/lib/devise/encryptors/sha1.rb +++ b/lib/devise/encryptors/sha1.rb @@ -5,7 +5,6 @@ module Devise # = Sha1 # Uses the Sha1 hash algorithm to encrypt passwords. class Sha1 < Base - # Gererates a default password digest based on stretches, salt, pepper and the # incoming password. def self.digest(password, stretches, salt, pepper) @@ -14,14 +13,13 @@ module Devise digest end - private + private - # Generate a SHA1 digest joining args. Generated token is something like - # --arg1--arg2--arg3--argN-- - def self.secure_digest(*tokens) - ::Digest::SHA1.hexdigest('--' << tokens.flatten.join('--') << '--') - end - + # Generate a SHA1 digest joining args. Generated token is something like + # --arg1--arg2--arg3--argN-- + def self.secure_digest(*tokens) + ::Digest::SHA1.hexdigest('--' << tokens.flatten.join('--') << '--') + end end end end \ No newline at end of file diff --git a/lib/devise/encryptors/sha512.rb b/lib/devise/encryptors/sha512.rb index 769389b9..ed8724d7 100644 --- a/lib/devise/encryptors/sha512.rb +++ b/lib/devise/encryptors/sha512.rb @@ -5,7 +5,6 @@ module Devise # = Sha512 # Uses the Sha512 hash algorithm to encrypt passwords. class Sha512 < Base - # Gererates a default password digest based on salt, pepper and the # incoming password. def self.digest(password, stretches, salt, pepper) @@ -14,14 +13,13 @@ module Devise digest end - private + private - # Generate a Sha512 digest joining args. Generated token is something like - # --arg1--arg2--arg3--argN-- - def self.secure_digest(*tokens) - ::Digest::SHA512.hexdigest('--' << tokens.flatten.join('--') << '--') - end - + # Generate a Sha512 digest joining args. Generated token is something like + # --arg1--arg2--arg3--argN-- + def self.secure_digest(*tokens) + ::Digest::SHA512.hexdigest('--' << tokens.flatten.join('--') << '--') + end end end end \ No newline at end of file diff --git a/lib/devise/rails.rb b/lib/devise/rails.rb index 244861a3..3fd90072 100644 --- a/lib/devise/rails.rb +++ b/lib/devise/rails.rb @@ -16,24 +16,29 @@ module Devise # Force routes to be loaded if we are doing any eager load. config.before_eager_load { |app| app.reload_routes! } + config.after_initialize do + Devise.encryptor ||= begin + warn "[WARNING] config.encryptor is not set in your config/initializers/devise.rb. " \ + "Devise will then set it to :bcrypt. If you were using the previous default " \ + "encryptor, please add config.encryptor = :sha1 to your configuration file." + :bcrypt + end + end + config.after_initialize do flash = [:unauthenticated, :unconfirmed, :invalid, :invalid_token, :timeout, :inactive, :locked] translations = begin - I18n.available_locales - I18n.backend.send(:translations) + I18n.t("devise.sessions", :raise => true).keys rescue Exception => e # Do not care if something fails {} end - translations.each do |locale, translations| - keys = flash & (translations[:devise][:sessions].keys) rescue [] + keys = flash & translations - if keys.any? - ActiveSupport::Deprecation.warn "The following I18n messages in 'devise.sessions' " << - "for locale '#{locale}' are deprecated: #{keys.to_sentence}. Please move them to " << - "'devise.failure' instead." - end + if keys.any? + ActiveSupport::Deprecation.warn "The following I18n messages in 'devise.sessions' " \ + "are deprecated: #{keys.to_sentence}. Please move them to 'devise.failure' instead." end end end diff --git a/lib/generators/devise_install/devise_install_generator.rb b/lib/generators/devise_install/devise_install_generator.rb index dc0e8b16..597633c8 100644 --- a/lib/generators/devise_install/devise_install_generator.rb +++ b/lib/generators/devise_install/devise_install_generator.rb @@ -1,3 +1,5 @@ +require 'active_support/secure_random' + class DeviseInstallGenerator < Rails::Generators::Base desc "Creates a Devise initializer and copy locale files to your application." diff --git a/lib/generators/devise_install/templates/devise.rb b/lib/generators/devise_install/templates/devise.rb index 2f13e4d4..b4f97696 100644 --- a/lib/generators/devise_install/templates/devise.rb +++ b/lib/generators/devise_install/templates/devise.rb @@ -27,19 +27,18 @@ Devise.setup do |config| # config.http_authentication_realm = "Application" # ==> Configuration for :database_authenticatable - # Invoke `rake secret` and use the printed value to setup a pepper to generate - # the encrypted password. By default no pepper is used. - # config.pepper = "rake secret output" + # For bcrypt, this is the cost for hashing the password and defaults to 10. If + # using other encryptors, it sets how many times you want the password re-encrypted. + config.stretches = 10 - # Configure how many times you want the password re-encrypted. Default is 10. - # config.stretches = 10 - - # Define which will be the encryption algorithm. Supported algorithms are :sha1 - # (default), :sha512 and :bcrypt. Devise also supports encryptors from others - # authentication tools as :clearance_sha1, :authlogic_sha512 (then you should set - # stretches above to 20 for default behavior) and :restful_authentication_sha1 + # Define which will be the encryption algorithm. Devise also supports encryptors + # from others authentication tools as :clearance_sha1, :authlogic_sha512 (then + # you should set stretches above to 20 for default behavior) and :restful_authentication_sha1 # (then you should set stretches to 10, and copy REST_AUTH_SITE_KEY to pepper) - # config.encryptor = :sha1 + config.encryptor = :bcrypt + + # Setup a pepper to generate the encrypted password. + config.pepper = <%= ActiveSupport::SecureRandom.hex(64).inspect %> # ==> Configuration for :confirmable # The time you want to give your user to confirm his account. During this time diff --git a/test/models/database_authenticatable_test.rb b/test/models/database_authenticatable_test.rb index 57676ee6..8446931c 100644 --- a/test/models/database_authenticatable_test.rb +++ b/test/models/database_authenticatable_test.rb @@ -3,10 +3,22 @@ require 'digest/sha1' class DatabaseAuthenticatableTest < ActiveSupport::TestCase - def encrypt_password(user, pepper=User.pepper, stretches=User.stretches, encryptor=::Devise::Encryptors::Sha1) + def encrypt_password(user, pepper=User.pepper, stretches=User.stretches, encryptor=User.encryptor_class) encryptor.digest('123456', stretches, user.password_salt, pepper) end + def swap_with_encryptor(klass, encryptor, options={}) + klass.instance_variable_set(:@encryptor_class, nil) + + swap klass, options.merge(:encryptor => encryptor) do + begin + yield + ensure + klass.instance_variable_set(:@encryptor_class, nil) + end + end + end + test 'should respond to password and password confirmation' do user = new_user assert user.respond_to?(:password) @@ -28,8 +40,10 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase end test 'should generate a base64 hash using SecureRandom for password salt' do - ActiveSupport::SecureRandom.expects(:base64).with(15).returns('friendly_token') - assert_equal 'friendly_token', new_user.password_salt + swap_with_encryptor User, :sha1 do + ActiveSupport::SecureRandom.expects(:base64).with(15).returns('friendly_token') + assert_equal 'friendly_token', new_user.password_salt + end end test 'should not generate salt if password is blank' do @@ -71,24 +85,10 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase end end - test 'should fallback to devise stretches default configuration' do - swap Devise, :stretches => 1 do - user = new_user - assert_equal encrypt_password(user, nil, 1), user.encrypted_password - assert_not_equal encrypt_password(user, nil, 2), user.encrypted_password - end - end - test 'should respect encryptor configuration' do - User.instance_variable_set(:@encryptor_class, nil) - - swap Devise, :encryptor => :sha512 do - begin - user = create_user - assert_equal user.encrypted_password, encrypt_password(user, User.pepper, User.stretches, ::Devise::Encryptors::Sha512) - ensure - User.instance_variable_set(:@encryptor_class, nil) - end + swap_with_encryptor User, :sha512 do + user = create_user + assert_equal user.encrypted_password, encrypt_password(user, User.pepper, User.stretches, ::Devise::Encryptors::Sha512) end end