Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Added :acts_like_restful_authentication to help with the transition, …

…and a new crypto provider BCrypt
  • Loading branch information...
commit 387c12c1ae3594f49b5b9d85bef8c1dd68f66cf1 1 parent 2b85651
Ben Johnson yourewelcome authored
12 CHANGELOG.rdoc
Source Rendered
... ... @@ -1,11 +1,13 @@
1   -== 1.3.1 released 2008-11-20
  1 +== 1.3.1 released 2008-11-22
2 2
3   -* Fixed typo in acts_as_authentic config when passing the :scope option
  3 +* Fixed typo in acts_as_authentic config when passing the :scope option.
  4 +* Added :act_like_restful_authentication option for acts_as_authentic
  5 +* Added a new crypto provider: BCrypt, this is for the hardcore paranoid, or for those storing the nuclear launch codes in their apps
4 6
5   -== 1.3.0 released 2008-11-20
  7 +== 1.3.0 released 2008-11-21
6 8
7   -* 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.
8   -* 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.
  9 +* 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.
  10 +* 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.
9 11 * Got rid of simple delegator for the abstract controller, apparently this has performance issues.
10 12 * Cleaned up validations to assume ActiveRecord dirty attributes are present, I think this is a safe assumption.
11 13
1  lib/authlogic.rb
@@ -8,6 +8,7 @@
8 8
9 9 require File.dirname(__FILE__) + "/authlogic/crypto_providers/sha1"
10 10 require File.dirname(__FILE__) + "/authlogic/crypto_providers/sha512"
  11 +require File.dirname(__FILE__) + "/authlogic/crypto_providers/bcrypt"
11 12
12 13 if defined?(ActiveRecord)
13 14 require File.dirname(__FILE__) + "/authlogic/orm_adapters/active_record_adapter/acts_as_authentic"
49 lib/authlogic/crypto_providers/bcrypt.rb
... ... @@ -0,0 +1,49 @@
  1 +begin
  2 + require "bcrypt"
  3 +rescue LoadError
  4 +end
  5 +
  6 +module Authlogic
  7 + module CryptoProviders
  8 + # = Bcrypt
  9 + #
  10 + # 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
  11 + # 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
  12 + # password encrypted with a Sha algorithm. Keep in mind you are sacrificing performance by using this, generating a password takes exponentially longer than any
  13 + # of the Sha algorithms. I did some benchmarking to save you some time with your decision:
  14 + #
  15 + # require "bcrypt"
  16 + # require "digest"
  17 + # require "benchmark"
  18 + #
  19 + # Benchmark.bm do |x|
  20 + # x.report("BCrypt:") { BCrypt::Password.create("mypass") }
  21 + # x.report("Sha512:") { Digest::SHA512.hexdigest("mypass") }
  22 + # end
  23 + #
  24 + # user system total real
  25 + # BCrypt: 0.110000 0.000000 0.110000 ( 0.113493)
  26 + # Sha512: 0.010000 0.000000 0.010000 ( 0.000554)
  27 + #
  28 + # Decided BCrypt is for you? Just insall the bcrypt gem:
  29 + #
  30 + # gem install bcrypt-ruby
  31 + class Bcrypt
  32 + class << self
  33 + def cost
  34 + @cost ||= 10
  35 + end
  36 + attr_writer :cost
  37 +
  38 + def encrypt(pass)
  39 + BCrypt::Password.create(pass, :cost => cost)
  40 + end
  41 +
  42 + # 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.
  43 + def decrypt(crypted_pass)
  44 + BCrypt::Password.create(crypted_pass)
  45 + end
  46 + end
  47 + end
  48 + end
  49 +end
10 lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/config.rb
@@ -22,6 +22,12 @@ module ActsAsAuthentic
22 22 # * <tt>crypto_provider</tt> - default: Authlogic::CryptoProviders::Sha512,
23 23 # This is the class that provides your encryption. By default Authlogic provides its own crypto provider that uses Sha512 encrypton.
24 24 #
  25 + # * <tt>act_like_restful_authentication</tt> - default: false,
  26 + # 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
  27 + # 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
  28 + # 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
  29 + # checkout Authlogic::CryptoProviders::BCrypt.
  30 + #
25 31 # * <tt>login_field</tt> - default: :login, :username, or :email, depending on which column is present, if none are present defaults to :login
26 32 # The name of the field used for logging in. Only specify if you aren't using any of the defaults.
27 33 #
@@ -183,6 +189,10 @@ def acts_as_authentic_with_config(options = {})
183 189 options[:login_field_validates_uniqueness_of_options][:scope] ||= options[:scope]
184 190 options[:email_field_validates_uniqueness_of_options][:scope] ||= options[:scope]
185 191 end
  192 +
  193 + if options[:act_like_restful_authentication]
  194 + options[:crypto_provider] = CryptoProviders::Sha1
  195 + end
186 196
187 197 class_eval <<-"end_eval", __FILE__, __LINE__
188 198 def self.acts_as_authentic_config
13 lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/credentials.rb
@@ -66,13 +66,13 @@ def #{options[:password_field]}=(pass)
66 66 return if pass.blank?
67 67 @#{options[:password_field]} = pass
68 68 self.#{options[:password_salt_field]} = self.class.unique_token
69   - self.#{options[:crypted_password_field]} = #{options[:crypto_provider]}.encrypt(@#{options[:password_field]} + #{options[:password_salt_field]})
  69 + self.#{options[:crypted_password_field]} = #{options[:crypto_provider]}.encrypt(obfuscate_password(@#{options[:password_field]}))
70 70 end
71 71
72 72 def valid_#{options[:password_field]}?(attempted_password)
73 73 return false if attempted_password.blank? || #{options[:crypted_password_field]}.blank? || #{options[:password_salt_field]}.blank?
74 74 (#{options[:crypto_provider]}.respond_to?(:decrypt) && #{options[:crypto_provider]}.decrypt(#{options[:crypted_password_field]}) == attempted_password + #{options[:password_salt_field]}) ||
75   - (!#{options[:crypto_provider]}.respond_to?(:decrypt) && #{options[:crypto_provider]}.encrypt(attempted_password + #{options[:password_salt_field]}) == #{options[:crypted_password_field]})
  75 + (!#{options[:crypto_provider]}.respond_to?(:decrypt) && #{options[:crypto_provider]}.encrypt(obfuscate_password(attempted_password)) == #{options[:crypted_password_field]})
76 76 end
77 77
78 78 def reset_#{options[:password_field]}
@@ -87,6 +87,15 @@ def reset_#{options[:password_field]}!
87 87 save_without_session_maintenance(false)
88 88 end
89 89 alias_method :randomize_password!, :reset_password!
  90 +
  91 + private
  92 + def obfuscate_password(raw_password)
  93 + if #{options[:act_like_restful_authentication].inspect}
  94 + [REST_AUTH_SITE_KEY, raw_password, #{options[:password_salt_field]}, REST_AUTH_SITE_KEY].join("--")
  95 + else
  96 + raw_password + #{options[:password_salt_field]}
  97 + end
  98 + end
90 99 end_eval
91 100 end
92 101 end

0 comments on commit 387c12c

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