Skip to content
Browse files

Added :acts_like_restful_authentication to help with the transition, …

…and a new crypto provider BCrypt
  • Loading branch information...
1 parent 2b85651 commit 387c12c1ae3594f49b5b9d85bef8c1dd68f66cf1 @binarylogic binarylogic committed Nov 22, 2008
View
12 CHANGELOG.rdoc
@@ -1,11 +1,13 @@
-== 1.3.1 released 2008-11-20
+== 1.3.1 released 2008-11-22
-* Fixed typo in acts_as_authentic config when passing the :scope option
+* Fixed typo in acts_as_authentic config when passing the :scope option.
+* Added :act_like_restful_authentication option for acts_as_authentic
+* Added a new crypto provider: BCrypt, this is for the hardcore paranoid, or for those storing the nuclear launch codes in their apps
-== 1.3.0 released 2008-11-20
+== 1.3.0 released 2008-11-21
-* BREAKS BACKWARDS COMPATIBILITY: changed the confirm_password field to password_confirmation for acts_as_authentic, since the rails validates_confirmation_of handles creating this attribute.
-* BREAKS BACKWARDS COMPATIBILITY: Cleaned up all of the validation configuration for acts_as_authentic, as well as the documentation that goes with it, you can accomplish the same things as before, but this is much more flexible and much more organized.
+* BREAKS BACKWARDS COMPATIBILITY: changed the confirm_password field to password_confirmation for acts_as_authentic, since the rails validates_confirmation_of handles creating this attribute and there is no option to change the name of this.
+* BREAKS BACKWARDS COMPATIBILITY: Cleaned up all of the validation configuration for acts_as_authentic, as well as the documentation that goes with it, you can accomplish the same things as before, but this is much more flexible and much more organized. This is mainly for those implementing i18n support. Instead of :whatever_message, its now :login_field_validates_length_of_options => {:message => "your i18n friendly message"}. As a side note, with the new i18n support in rails I would not be surprised if this is already done for you since Authlogic uses the ActiveRecord validation methods.
* Got rid of simple delegator for the abstract controller, apparently this has performance issues.
* Cleaned up validations to assume ActiveRecord dirty attributes are present, I think this is a safe assumption.
View
1 lib/authlogic.rb
@@ -8,6 +8,7 @@
require File.dirname(__FILE__) + "/authlogic/crypto_providers/sha1"
require File.dirname(__FILE__) + "/authlogic/crypto_providers/sha512"
+require File.dirname(__FILE__) + "/authlogic/crypto_providers/bcrypt"
if defined?(ActiveRecord)
require File.dirname(__FILE__) + "/authlogic/orm_adapters/active_record_adapter/acts_as_authentic"
View
49 lib/authlogic/crypto_providers/bcrypt.rb
@@ -0,0 +1,49 @@
+begin
+ require "bcrypt"
+rescue LoadError
+end
+
+module Authlogic
+ module CryptoProviders
+ # = Bcrypt
+ #
+ # For most apps Sha512 is plenty secure, but if you are building an app that stores the nuclear launch codes you might want to consier BCrypt. This is an extremely
+ # secure hashing algorithm, mainly because it is slow. A brute force attack on a BCrypt encrypted password would take much longer than a brute force attack on a
+ # password encrypted with a Sha algorithm. Keep in mind you are sacrificing performance by using this, generating a password takes exponentially longer than any
+ # of the Sha algorithms. I did some benchmarking to save you some time with your decision:
+ #
+ # require "bcrypt"
+ # require "digest"
+ # require "benchmark"
+ #
+ # Benchmark.bm do |x|
+ # x.report("BCrypt:") { BCrypt::Password.create("mypass") }
+ # x.report("Sha512:") { Digest::SHA512.hexdigest("mypass") }
+ # end
+ #
+ # user system total real
+ # BCrypt: 0.110000 0.000000 0.110000 ( 0.113493)
+ # Sha512: 0.010000 0.000000 0.010000 ( 0.000554)
+ #
+ # Decided BCrypt is for you? Just insall the bcrypt gem:
+ #
+ # gem install bcrypt-ruby
+ class Bcrypt
+ class << self
+ def cost
+ @cost ||= 10
+ end
+ attr_writer :cost
+
+ def encrypt(pass)
+ BCrypt::Password.create(pass, :cost => cost)
+ end
+
+ # This does not actually decrypt the password, BCrypt is *not* reversible. The way the bcrypt library is set up requires us to do it this way.
+ def decrypt(crypted_pass)
+ BCrypt::Password.create(crypted_pass)
+ end
+ end
+ end
+ end
+end
View
10 lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/config.rb
@@ -22,6 +22,12 @@ module ActsAsAuthentic
# * <tt>crypto_provider</tt> - default: Authlogic::CryptoProviders::Sha512,
# This is the class that provides your encryption. By default Authlogic provides its own crypto provider that uses Sha512 encrypton.
#
+ # * <tt>act_like_restful_authentication</tt> - default: false,
+ # If you are migrating from restful_authentication you will want to set this to true, this way your users will still be able to log in and it will seems as
+ # if nothing has changed. If you don't do this none of your users will be able to log in. If you are starting a new project I do not recommend enabling this
+ # as the password encryption algorithm used in restful_authentication (Sha1) is not as secure as the one used in authlogic (Sha512). IF you REALLY want to be secure
+ # checkout Authlogic::CryptoProviders::BCrypt.
+ #
# * <tt>login_field</tt> - default: :login, :username, or :email, depending on which column is present, if none are present defaults to :login
# The name of the field used for logging in. Only specify if you aren't using any of the defaults.
#
@@ -183,6 +189,10 @@ def acts_as_authentic_with_config(options = {})
options[:login_field_validates_uniqueness_of_options][:scope] ||= options[:scope]
options[:email_field_validates_uniqueness_of_options][:scope] ||= options[:scope]
end
+
+ if options[:act_like_restful_authentication]
+ options[:crypto_provider] = CryptoProviders::Sha1
+ end
class_eval <<-"end_eval", __FILE__, __LINE__
def self.acts_as_authentic_config
View
13 lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/credentials.rb
@@ -66,13 +66,13 @@ def #{options[:password_field]}=(pass)
return if pass.blank?
@#{options[:password_field]} = pass
self.#{options[:password_salt_field]} = self.class.unique_token
- self.#{options[:crypted_password_field]} = #{options[:crypto_provider]}.encrypt(@#{options[:password_field]} + #{options[:password_salt_field]})
+ self.#{options[:crypted_password_field]} = #{options[:crypto_provider]}.encrypt(obfuscate_password(@#{options[:password_field]}))
end
def valid_#{options[:password_field]}?(attempted_password)
return false if attempted_password.blank? || #{options[:crypted_password_field]}.blank? || #{options[:password_salt_field]}.blank?
(#{options[:crypto_provider]}.respond_to?(:decrypt) && #{options[:crypto_provider]}.decrypt(#{options[:crypted_password_field]}) == attempted_password + #{options[:password_salt_field]}) ||
- (!#{options[:crypto_provider]}.respond_to?(:decrypt) && #{options[:crypto_provider]}.encrypt(attempted_password + #{options[:password_salt_field]}) == #{options[:crypted_password_field]})
+ (!#{options[:crypto_provider]}.respond_to?(:decrypt) && #{options[:crypto_provider]}.encrypt(obfuscate_password(attempted_password)) == #{options[:crypted_password_field]})
end
def reset_#{options[:password_field]}
@@ -87,6 +87,15 @@ def reset_#{options[:password_field]}!
save_without_session_maintenance(false)
end
alias_method :randomize_password!, :reset_password!
+
+ private
+ def obfuscate_password(raw_password)
+ if #{options[:act_like_restful_authentication].inspect}
+ [REST_AUTH_SITE_KEY, raw_password, #{options[:password_salt_field]}, REST_AUTH_SITE_KEY].join("--")
+ else
+ raw_password + #{options[:password_salt_field]}
+ end
+ end
end_eval
end
end

0 comments on commit 387c12c

Please sign in to comment.
Something went wrong with that request. Please try again.