authlogic 3.8.0 → 4.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. checksums.yaml +7 -0
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +28 -0
  3. data/.github/ISSUE_TEMPLATE/feature_proposal.md +32 -0
  4. data/.github/triage.md +86 -0
  5. data/.gitignore +4 -3
  6. data/.rubocop.yml +109 -9
  7. data/.rubocop_todo.yml +38 -355
  8. data/.travis.yml +11 -35
  9. data/CHANGELOG.md +345 -2
  10. data/CONTRIBUTING.md +45 -14
  11. data/Gemfile +3 -2
  12. data/README.md +244 -90
  13. data/Rakefile +10 -10
  14. data/UPGRADING.md +22 -0
  15. data/authlogic.gemspec +34 -21
  16. data/doc/use_normal_rails_validation.md +82 -0
  17. data/gemfiles/Gemfile.rails-4.2.x +6 -0
  18. data/{test/gemfiles → gemfiles}/Gemfile.rails-5.1.x +2 -2
  19. data/{test/gemfiles → gemfiles}/Gemfile.rails-5.2.x +2 -2
  20. data/lib/authlogic/acts_as_authentic/base.rb +36 -24
  21. data/lib/authlogic/acts_as_authentic/email.rb +65 -31
  22. data/lib/authlogic/acts_as_authentic/logged_in_status.rb +14 -9
  23. data/lib/authlogic/acts_as_authentic/login.rb +61 -45
  24. data/lib/authlogic/acts_as_authentic/magic_columns.rb +6 -6
  25. data/lib/authlogic/acts_as_authentic/password.rb +267 -146
  26. data/lib/authlogic/acts_as_authentic/perishable_token.rb +24 -19
  27. data/lib/authlogic/acts_as_authentic/persistence_token.rb +10 -15
  28. data/lib/authlogic/acts_as_authentic/queries/find_with_case.rb +67 -0
  29. data/lib/authlogic/acts_as_authentic/restful_authentication.rb +50 -14
  30. data/lib/authlogic/acts_as_authentic/session_maintenance.rb +88 -60
  31. data/lib/authlogic/acts_as_authentic/single_access_token.rb +23 -11
  32. data/lib/authlogic/acts_as_authentic/validations_scope.rb +9 -6
  33. data/lib/authlogic/authenticates_many/association.rb +7 -7
  34. data/lib/authlogic/authenticates_many/base.rb +37 -21
  35. data/lib/authlogic/config.rb +21 -10
  36. data/lib/authlogic/controller_adapters/abstract_adapter.rb +38 -11
  37. data/lib/authlogic/controller_adapters/rack_adapter.rb +9 -5
  38. data/lib/authlogic/controller_adapters/rails_adapter.rb +12 -7
  39. data/lib/authlogic/controller_adapters/sinatra_adapter.rb +2 -2
  40. data/lib/authlogic/crypto_providers/aes256.rb +37 -32
  41. data/lib/authlogic/crypto_providers/bcrypt.rb +21 -15
  42. data/lib/authlogic/crypto_providers/md5.rb +4 -2
  43. data/lib/authlogic/crypto_providers/scrypt.rb +22 -17
  44. data/lib/authlogic/crypto_providers/sha1.rb +11 -5
  45. data/lib/authlogic/crypto_providers/sha256.rb +13 -9
  46. data/lib/authlogic/crypto_providers/sha512.rb +0 -21
  47. data/lib/authlogic/crypto_providers/wordpress.rb +32 -3
  48. data/lib/authlogic/crypto_providers.rb +91 -0
  49. data/lib/authlogic/i18n.rb +26 -19
  50. data/lib/authlogic/random.rb +10 -28
  51. data/lib/authlogic/regex.rb +59 -28
  52. data/lib/authlogic/session/activation.rb +10 -7
  53. data/lib/authlogic/session/active_record_trickery.rb +13 -9
  54. data/lib/authlogic/session/base.rb +15 -4
  55. data/lib/authlogic/session/brute_force_protection.rb +40 -33
  56. data/lib/authlogic/session/callbacks.rb +94 -46
  57. data/lib/authlogic/session/cookies.rb +130 -45
  58. data/lib/authlogic/session/existence.rb +21 -11
  59. data/lib/authlogic/session/foundation.rb +64 -14
  60. data/lib/authlogic/session/http_auth.rb +35 -28
  61. data/lib/authlogic/session/id.rb +9 -4
  62. data/lib/authlogic/session/klass.rb +15 -12
  63. data/lib/authlogic/session/magic_columns.rb +58 -55
  64. data/lib/authlogic/session/magic_states.rb +25 -19
  65. data/lib/authlogic/session/params.rb +42 -28
  66. data/lib/authlogic/session/password.rb +130 -120
  67. data/lib/authlogic/session/perishable_token.rb +5 -4
  68. data/lib/authlogic/session/persistence.rb +18 -12
  69. data/lib/authlogic/session/priority_record.rb +15 -12
  70. data/lib/authlogic/session/scopes.rb +51 -32
  71. data/lib/authlogic/session/session.rb +38 -28
  72. data/lib/authlogic/session/timeout.rb +13 -13
  73. data/lib/authlogic/session/unauthorized_record.rb +18 -13
  74. data/lib/authlogic/session/validation.rb +9 -9
  75. data/lib/authlogic/test_case/mock_controller.rb +5 -4
  76. data/lib/authlogic/test_case/mock_cookie_jar.rb +47 -3
  77. data/lib/authlogic/test_case/mock_request.rb +6 -3
  78. data/lib/authlogic/test_case/rails_request_adapter.rb +3 -2
  79. data/lib/authlogic/test_case.rb +70 -2
  80. data/lib/authlogic/version.rb +21 -0
  81. data/lib/authlogic.rb +51 -49
  82. data/test/acts_as_authentic_test/base_test.rb +3 -1
  83. data/test/acts_as_authentic_test/email_test.rb +43 -42
  84. data/test/acts_as_authentic_test/logged_in_status_test.rb +6 -4
  85. data/test/acts_as_authentic_test/login_test.rb +77 -80
  86. data/test/acts_as_authentic_test/magic_columns_test.rb +3 -1
  87. data/test/acts_as_authentic_test/password_test.rb +51 -37
  88. data/test/acts_as_authentic_test/perishable_token_test.rb +13 -5
  89. data/test/acts_as_authentic_test/persistence_token_test.rb +7 -1
  90. data/test/acts_as_authentic_test/restful_authentication_test.rb +14 -3
  91. data/test/acts_as_authentic_test/session_maintenance_test.rb +69 -15
  92. data/test/acts_as_authentic_test/single_access_test.rb +3 -1
  93. data/test/adapter_test.rb +23 -0
  94. data/test/authenticates_many_test.rb +3 -1
  95. data/test/config_test.rb +11 -9
  96. data/test/crypto_provider_test/aes256_test.rb +3 -1
  97. data/test/crypto_provider_test/bcrypt_test.rb +3 -1
  98. data/test/crypto_provider_test/scrypt_test.rb +3 -1
  99. data/test/crypto_provider_test/sha1_test.rb +3 -1
  100. data/test/crypto_provider_test/sha256_test.rb +3 -1
  101. data/test/crypto_provider_test/sha512_test.rb +3 -1
  102. data/test/crypto_provider_test/wordpress_test.rb +26 -0
  103. data/test/fixtures/companies.yml +2 -2
  104. data/test/fixtures/employees.yml +1 -1
  105. data/test/i18n_test.rb +6 -4
  106. data/test/libs/affiliate.rb +2 -0
  107. data/test/libs/company.rb +4 -2
  108. data/test/libs/employee.rb +2 -0
  109. data/test/libs/employee_session.rb +2 -0
  110. data/test/libs/ldaper.rb +2 -0
  111. data/test/libs/project.rb +2 -0
  112. data/test/libs/user.rb +2 -0
  113. data/test/libs/user_session.rb +4 -2
  114. data/test/random_test.rb +10 -38
  115. data/test/session_test/activation_test.rb +3 -1
  116. data/test/session_test/active_record_trickery_test.rb +7 -4
  117. data/test/session_test/brute_force_protection_test.rb +11 -9
  118. data/test/session_test/callbacks_test.rb +12 -4
  119. data/test/session_test/cookies_test.rb +48 -5
  120. data/test/session_test/existence_test.rb +18 -5
  121. data/test/session_test/foundation_test.rb +19 -1
  122. data/test/session_test/http_auth_test.rb +11 -7
  123. data/test/session_test/id_test.rb +3 -1
  124. data/test/session_test/klass_test.rb +3 -1
  125. data/test/session_test/magic_columns_test.rb +13 -13
  126. data/test/session_test/magic_states_test.rb +3 -1
  127. data/test/session_test/params_test.rb +13 -5
  128. data/test/session_test/password_test.rb +10 -8
  129. data/test/session_test/perishability_test.rb +3 -1
  130. data/test/session_test/persistence_test.rb +4 -1
  131. data/test/session_test/scopes_test.rb +16 -8
  132. data/test/session_test/session_test.rb +6 -4
  133. data/test/session_test/timeout_test.rb +4 -2
  134. data/test/session_test/unauthorized_record_test.rb +4 -2
  135. data/test/session_test/validation_test.rb +3 -1
  136. data/test/test_helper.rb +84 -45
  137. metadata +87 -73
  138. data/.github/ISSUE_TEMPLATE.md +0 -13
  139. data/test/gemfiles/Gemfile.rails-3.2.x +0 -7
  140. data/test/gemfiles/Gemfile.rails-4.0.x +0 -7
  141. data/test/gemfiles/Gemfile.rails-4.1.x +0 -7
  142. data/test/gemfiles/Gemfile.rails-4.2.x +0 -7
  143. data/test/gemfiles/Gemfile.rails-5.0.x +0 -6
@@ -3,7 +3,7 @@ module Authlogic
3
3
  # to an account, you want to make sure only users that belong to that account can
4
4
  # actually login into that account. Simple, just do:
5
5
  #
6
- # class Account < ActiveRecord::Base
6
+ # class Account < ApplicationRecord
7
7
  # authenticates_many :user_sessions
8
8
  # end
9
9
  #
@@ -17,8 +17,16 @@ module Authlogic
17
17
  # Checkout the authenticates_many method for a list of options.
18
18
  # You may also want to checkout Authlogic::ActsAsAuthentic::Scope to scope your model.
19
19
  module AuthenticatesMany
20
+ # These methods become class methods of ::ActiveRecord::Base.
20
21
  module Base
21
- # Allows you set essentially set up a relationship with your sessions. See module
22
+ DPR_AUTH_MANY = <<~EOS.freeze
23
+ authenticates_many is deprecated without replacement. Let us know
24
+ if you would like to take over maintenance of this feature as a separate
25
+ gem. If no one volunteers to extract and maintain a new gem, then this
26
+ feature will simply be deleted.
27
+ EOS
28
+
29
+ # Allows you to set up a relationship with your sessions. See module
22
30
  # definition above for more details.
23
31
  #
24
32
  # === Options
@@ -26,37 +34,45 @@ module Authlogic
26
34
  # * <tt>session_class:</tt> default: "#{name}Session",
27
35
  # This is the related session class.
28
36
  #
29
- # * <tt>relationship_name:</tt> default: options[:session_class].klass_name.underscore.pluralize,
30
- # This is the name of the relationship you want to use to scope everything. For
31
- # example an Account has many Users. There should be a relationship called :users
32
- # that you defined with a has_many. The reason we use the relationship is so you
33
- # don't have to repeat yourself. The relationship could have all kinds of custom
34
- # options. So instead of repeating yourself we essentially use the scope that the
37
+ # * <tt>relationship_name:</tt>
38
+ # default: options[:session_class].klass_name.underscore.pluralize,
39
+ # This is the name of the relationship you want to use to scope
40
+ # everything. For example an Account has many Users. There should be a
41
+ # relationship called :users that you defined with a has_many. The
42
+ # reason we use the relationship is so you don't have to repeat
43
+ # yourself. The relationship could have all kinds of custom options. So
44
+ # instead of repeating yourself we essentially use the scope that the
35
45
  # relationship creates.
36
46
  #
37
47
  # * <tt>find_options:</tt> default: nil,
38
- # By default the find options are created from the relationship you specify with
39
- # :relationship_name. But if you want to override this and manually specify
40
- # find_options you can do it here. Specify options just as you would in
41
- # ActiveRecord::Base.find.
48
+ # By default the find options are created from the relationship you
49
+ # specify with :relationship_name. But if you want to override this and
50
+ # manually specify find_options you can do it here. Specify options just
51
+ # as you would in ActiveRecord::Base.find.
42
52
  #
43
53
  # * <tt>scope_cookies:</tt> default: false
44
- # By the nature of cookies they scope themselves if you are using subdomains to
45
- # access accounts. If you aren't using subdomains you need to have separate
46
- # cookies for each account, assuming a user is logging into more than one account.
47
- # Authlogic can take care of this for you by prefixing the name of the cookie and
48
- # session with the model id. Because it affects both cookies names and session keys,
49
- # the name `scope_cookies` is misleading. Perhaps simply `scope` or `scoped`
54
+ # By the nature of cookies they scope themselves if you are using
55
+ # subdomains to access accounts. If you aren't using subdomains you need
56
+ # to have separate cookies for each account, assuming a user is logging
57
+ # into more than one account. Authlogic can take care of this for you by
58
+ # prefixing the name of the cookie and session with the model id.
59
+ # Because it affects both cookies names and session keys, the name
60
+ # `scope_cookies` is misleading. Perhaps simply `scope` or `scoped`
50
61
  # would have been better.
51
62
  def authenticates_many(name, options = {})
63
+ ::ActiveSupport::Deprecation.warn(DPR_AUTH_MANY)
52
64
  options[:session_class] ||= name.to_s.classify.constantize
53
65
  options[:relationship_name] ||= options[:session_class].klass_name.underscore.pluralize
54
- class_eval <<-"end_eval", __FILE__, __LINE__
66
+ class_eval <<-EOS, __FILE__, __LINE__ + 1
55
67
  def #{name}
56
68
  find_options = #{options[:find_options].inspect} || #{options[:relationship_name]}.where(nil)
57
- @#{name} ||= Authlogic::AuthenticatesMany::Association.new(#{options[:session_class]}, find_options, #{options[:scope_cookies] ? "self.class.model_name.name.underscore + '_' + self.send(self.class.primary_key).to_s" : "nil"})
69
+ @#{name} ||= Authlogic::AuthenticatesMany::Association.new(
70
+ #{options[:session_class]},
71
+ find_options,
72
+ #{options[:scope_cookies] ? "self.class.model_name.name.underscore + '_' + self.send(self.class.primary_key).to_s" : 'nil'}
73
+ )
58
74
  end
59
- end_eval
75
+ EOS
60
76
  end
61
77
  end
62
78
 
@@ -1,6 +1,11 @@
1
- # encoding: utf-8
2
1
  module Authlogic
3
2
  module Config
3
+ E_USE_NORMAL_RAILS_VALIDATION = <<~EOS.freeze
4
+ This Authlogic configuration option (%s) is deprecated. Use normal
5
+ ActiveRecord validation instead. Detailed instructions:
6
+ https://github.com/binarylogic/authlogic/blob/master/doc/use_normal_rails_validation.md
7
+ EOS
8
+
4
9
  def self.extended(klass)
5
10
  klass.class_eval do
6
11
  class_attribute :acts_as_authentic_config
@@ -10,15 +15,21 @@ module Authlogic
10
15
 
11
16
  private
12
17
 
13
- # This is a one-liner method to write a config setting, read the config
14
- # setting, and also set a default value for the setting.
15
- def rw_config(key, value, default_value = nil)
16
- if value.nil?
17
- acts_as_authentic_config.include?(key) ? acts_as_authentic_config[key] : default_value
18
- else
19
- self.acts_as_authentic_config = acts_as_authentic_config.merge(key => value)
20
- value
21
- end
18
+ def deprecate_authlogic_config(method_name)
19
+ ::ActiveSupport::Deprecation.warn(
20
+ format(E_USE_NORMAL_RAILS_VALIDATION, method_name)
21
+ )
22
+ end
23
+
24
+ # This is a one-liner method to write a config setting, read the config
25
+ # setting, and also set a default value for the setting.
26
+ def rw_config(key, value, default_value = nil)
27
+ if value.nil?
28
+ acts_as_authentic_config.include?(key) ? acts_as_authentic_config[key] : default_value
29
+ else
30
+ self.acts_as_authentic_config = acts_as_authentic_config.merge(key => value)
31
+ value
22
32
  end
33
+ end
23
34
  end
24
35
  end
@@ -3,16 +3,19 @@ module Authlogic
3
3
  # Allows you to use Authlogic in any framework you want, not just rails. See the RailsAdapter
4
4
  # for an example of how to adapt Authlogic to work with your framework.
5
5
  class AbstractAdapter
6
+ E_COOKIE_DOMAIN_ADAPTER = "The cookie_domain method has not been " \
7
+ "implemented by the controller adapter".freeze
8
+
6
9
  attr_accessor :controller
7
10
 
8
11
  def initialize(controller)
9
12
  self.controller = controller
10
13
  end
11
14
 
12
- def authenticate_with_http_basic(&block)
15
+ def authenticate_with_http_basic
13
16
  @auth = Rack::Auth::Basic::Request.new(controller.request.env)
14
- if @auth.provided? and @auth.basic?
15
- block.call(*@auth.credentials)
17
+ if @auth.provided? && @auth.basic?
18
+ yield(*@auth.credentials)
16
19
  else
17
20
  false
18
21
  end
@@ -23,7 +26,7 @@ module Authlogic
23
26
  end
24
27
 
25
28
  def cookie_domain
26
- raise NotImplementedError.new("The cookie_domain method has not been implemented by the controller adapter")
29
+ raise NotImplementedError.new(E_COOKIE_DOMAIN_ADAPTER)
27
30
  end
28
31
 
29
32
  def params
@@ -50,19 +53,43 @@ module Authlogic
50
53
  controller.send(:single_access_allowed?)
51
54
  end
52
55
 
53
- def responds_to_last_request_update_allowed?
54
- controller.respond_to?(:last_request_update_allowed?, true)
56
+ # You can disable the updating of `last_request_at`
57
+ # on a per-controller basis.
58
+ #
59
+ # # in your controller
60
+ # def last_request_update_allowed?
61
+ # false
62
+ # end
63
+ #
64
+ # For example, what if you had a javascript function that polled the
65
+ # server updating how much time is left in their session before it
66
+ # times out. Obviously you would want to ignore this request, because
67
+ # then the user would never time out. So you can do something like
68
+ # this in your controller:
69
+ #
70
+ # def last_request_update_allowed?
71
+ # action_name != "update_session_time_left"
72
+ # end
73
+ #
74
+ # See `authlogic/session/magic_columns.rb` to learn more about the
75
+ # `last_request_at` column itself.
76
+ def last_request_update_allowed?
77
+ if controller.respond_to?(:last_request_update_allowed?, true)
78
+ controller.send(:last_request_update_allowed?)
79
+ else
80
+ true
81
+ end
55
82
  end
56
83
 
57
- def last_request_update_allowed?
58
- controller.send(:last_request_update_allowed?)
84
+ def respond_to_missing?(*args)
85
+ super(*args) || controller.respond_to?(*args)
59
86
  end
60
87
 
61
88
  private
62
89
 
63
- def method_missing(id, *args, &block)
64
- controller.send(id, *args, &block)
65
- end
90
+ def method_missing(id, *args, &block)
91
+ controller.send(id, *args, &block)
92
+ end
66
93
  end
67
94
  end
68
95
  end
@@ -32,7 +32,7 @@ module Authlogic
32
32
  # # Authlogic options go here
33
33
  # end
34
34
  #
35
- # class User < ActiveRecord::Base
35
+ # class User < ApplicationRecord
36
36
  # acts_as_authentic
37
37
  # end
38
38
  #
@@ -48,7 +48,7 @@ module Authlogic
48
48
  end
49
49
 
50
50
  def remote_ip
51
- self.ip
51
+ ip
52
52
  end
53
53
  end
54
54
 
@@ -56,10 +56,14 @@ module Authlogic
56
56
  Authlogic::Session::Base.controller = self
57
57
  end
58
58
 
59
- # Rack Requests stores cookies with not just the value, but also with flags and expire information in the hash.
60
- # Authlogic does not like this, so we drop everything except the cookie value
59
+ # Rack Requests stores cookies with not just the value, but also with
60
+ # flags and expire information in the hash. Authlogic does not like this,
61
+ # so we drop everything except the cookie value.
61
62
  def cookies
62
- controller.cookies.map { |key, value_hash| { key => value_hash[:value] } }.inject(:merge) || {}
63
+ controller
64
+ .cookies
65
+ .map { |key, value_hash| { key => value_hash[:value] } }
66
+ .inject(:merge) || {}
63
67
  end
64
68
  end
65
69
  end
@@ -1,4 +1,4 @@
1
- require 'action_controller'
1
+ require "action_controller"
2
2
 
3
3
  module Authlogic
4
4
  module ControllerAdapters
@@ -13,12 +13,14 @@ module Authlogic
13
13
  controller.authenticate_with_http_basic(&block)
14
14
  end
15
15
 
16
+ # Returns a `ActionDispatch::Cookies::CookieJar`. See the AC guide
17
+ # http://guides.rubyonrails.org/action_controller_overview.html#cookies
16
18
  def cookies
17
19
  controller.send(:cookies)
18
20
  end
19
21
 
20
22
  def cookie_domain
21
- @cookie_domain_key ||= Rails::VERSION::STRING >= '2.3' ? :domain : :session_domain
23
+ @cookie_domain_key ||= Rails::VERSION::STRING >= "2.3" ? :domain : :session_domain
22
24
  controller.request.session_options[@cookie_domain_key]
23
25
  end
24
26
 
@@ -32,7 +34,7 @@ module Authlogic
32
34
  def self.included(klass) # :nodoc:
33
35
  if defined?(::ApplicationController)
34
36
  raise AuthlogicLoadedTooLateError.new(
35
- <<-EOS.strip_heredoc
37
+ <<~EOS.squish
36
38
  Authlogic is trying to add a callback to ActionController::Base
37
39
  but ApplicationController has already been loaded, so the
38
40
  callback won't be copied into your application. Generally this
@@ -54,12 +56,15 @@ module Authlogic
54
56
 
55
57
  private
56
58
 
57
- def activate_authlogic
58
- Authlogic::Session::Base.controller = RailsAdapter.new(self)
59
- end
59
+ def activate_authlogic
60
+ Authlogic::Session::Base.controller = RailsAdapter.new(self)
61
+ end
60
62
  end
61
63
  end
62
64
  end
63
65
  end
64
66
 
65
- ActionController::Base.send(:include, Authlogic::ControllerAdapters::RailsAdapter::RailsImplementation)
67
+ ActionController::Base.send(
68
+ :include,
69
+ Authlogic::ControllerAdapters::RailsAdapter::RailsImplementation
70
+ )
@@ -32,7 +32,7 @@ module Authlogic
32
32
  end
33
33
 
34
34
  def session
35
- env['rack.session']
35
+ env["rack.session"]
36
36
  end
37
37
 
38
38
  def method_missing(meth, *args, &block)
@@ -42,7 +42,7 @@ module Authlogic
42
42
 
43
43
  class Adapter < AbstractAdapter
44
44
  def cookie_domain
45
- env['SERVER_NAME']
45
+ env["SERVER_NAME"]
46
46
  end
47
47
 
48
48
  module Implementation
@@ -2,21 +2,23 @@ require "openssl"
2
2
 
3
3
  module Authlogic
4
4
  module CryptoProviders
5
- # This encryption method is reversible if you have the supplied key. So in order to
6
- # use this encryption method you must supply it with a key first. In an initializer,
7
- # or before your application initializes, you should do the following:
5
+ # This encryption method is reversible if you have the supplied key. So in
6
+ # order to use this encryption method you must supply it with a key first.
7
+ # In an initializer, or before your application initializes, you should do
8
+ # the following:
8
9
  #
9
- # Authlogic::CryptoProviders::AES256.key = "my really long and unique key, preferably a bunch of random characters"
10
+ # Authlogic::CryptoProviders::AES256.key = "long, unique, and random key"
10
11
  #
11
- # My final comment is that this is a strong encryption method, but its main weakness
12
- # is that it's reversible. If you do not need to reverse the hash then you should
13
- # consider Sha512 or BCrypt instead.
12
+ # My final comment is that this is a strong encryption method, but its main
13
+ # weakness is that it's reversible. If you do not need to reverse the hash
14
+ # then you should consider Sha512 or BCrypt instead.
14
15
  #
15
- # Keep your key in a safe place, some even say the key should be stored on a separate
16
- # server. This won't hurt performance because the only time it will try and access the
17
- # key on the separate server is during initialization, which only happens once. The
18
- # reasoning behind this is if someone does compromise your server they won't have the
19
- # key also. Basically, you don't want to store the key with the lock.
16
+ # Keep your key in a safe place, some even say the key should be stored on a
17
+ # separate server. This won't hurt performance because the only time it will
18
+ # try and access the key on the separate server is during initialization,
19
+ # which only happens once. The reasoning behind this is if someone does
20
+ # compromise your server they won't have the key also. Basically, you don't
21
+ # want to store the key with the lock.
20
22
  class AES256
21
23
  class << self
22
24
  attr_writer :key
@@ -37,29 +39,32 @@ module Authlogic
37
39
 
38
40
  private
39
41
 
40
- def aes
41
- if @key.blank?
42
- raise ArgumentError.new(
43
- "You must provide a key like #{name}.key = my_key before using the #{name}"
44
- )
45
- end
46
-
47
- @aes ||= openssl_cipher_class.new("AES-256-ECB")
42
+ def aes
43
+ if @key.blank?
44
+ raise ArgumentError.new(
45
+ "You must provide a key like #{name}.key = my_key before using the #{name}"
46
+ )
48
47
  end
49
48
 
50
- # `::OpenSSL::Cipher::Cipher` has been deprecated since at least 2014,
51
- # in favor of `::OpenSSL::Cipher`, but a deprecation warning was not
52
- # printed until 2016
53
- # (https://github.com/ruby/openssl/commit/5c20a4c014) when openssl
54
- # became a gem. Its first release as a gem was 2.0.0, in ruby 2.4.
55
- # (See https://github.com/ruby/ruby/blob/v2_4_0/NEWS)
56
- def openssl_cipher_class
57
- if ::Gem::Version.new(::OpenSSL::VERSION) < ::Gem::Version.new("2.0.0")
58
- ::OpenSSL::Cipher::Cipher
59
- else
60
- ::OpenSSL::Cipher
61
- end
49
+ @aes ||= openssl_cipher_class.new("AES-256-ECB")
50
+ end
51
+
52
+ # `::OpenSSL::Cipher::Cipher` has been deprecated since at least 2014,
53
+ # in favor of `::OpenSSL::Cipher`, but a deprecation warning was not
54
+ # printed until 2016
55
+ # (https://github.com/ruby/openssl/commit/5c20a4c014) when openssl
56
+ # became a gem. Its first release as a gem was 2.0.0, in ruby 2.4.
57
+ # (See https://github.com/ruby/ruby/blob/v2_4_0/NEWS)
58
+ #
59
+ # When we eventually drop support for ruby < 2.4, we can probably also
60
+ # drop support for openssl gem < 2.
61
+ def openssl_cipher_class
62
+ if ::Gem::Version.new(::OpenSSL::VERSION) < ::Gem::Version.new("2.0.0")
63
+ ::OpenSSL::Cipher::Cipher
64
+ else
65
+ ::OpenSSL::Cipher
62
66
  end
67
+ end
63
68
  end
64
69
  end
65
70
  end
@@ -16,10 +16,18 @@ module Authlogic
16
16
  # require "benchmark"
17
17
  #
18
18
  # Benchmark.bm(18) do |x|
19
- # x.report("BCrypt (cost = 10:") { 100.times { BCrypt::Password.create("mypass", :cost => 10) } }
20
- # x.report("BCrypt (cost = 4:") { 100.times { BCrypt::Password.create("mypass", :cost => 4) } }
21
- # x.report("Sha512:") { 100.times { Digest::SHA512.hexdigest("mypass") } }
22
- # x.report("Sha1:") { 100.times { Digest::SHA1.hexdigest("mypass") } }
19
+ # x.report("BCrypt (cost = 10:") {
20
+ # 100.times { BCrypt::Password.create("mypass", :cost => 10) }
21
+ # }
22
+ # x.report("BCrypt (cost = 4:") {
23
+ # 100.times { BCrypt::Password.create("mypass", :cost => 4) }
24
+ # }
25
+ # x.report("Sha512:") {
26
+ # 100.times { Digest::SHA512.hexdigest("mypass") }
27
+ # }
28
+ # x.report("Sha1:") {
29
+ # 100.times { Digest::SHA1.hexdigest("mypass") }
30
+ # }
23
31
  # end
24
32
  #
25
33
  # user system total real
@@ -66,7 +74,7 @@ module Authlogic
66
74
 
67
75
  # Creates a BCrypt hash for the password passed.
68
76
  def encrypt(*tokens)
69
- ::BCrypt::Password.create(join_tokens(tokens), :cost => cost)
77
+ ::BCrypt::Password.create(join_tokens(tokens), cost: cost)
70
78
  end
71
79
 
72
80
  # Does the hash match the tokens? Uses the same tokens that were used to
@@ -90,17 +98,15 @@ module Authlogic
90
98
 
91
99
  private
92
100
 
93
- def join_tokens(tokens)
94
- tokens.flatten.join
95
- end
101
+ def join_tokens(tokens)
102
+ tokens.flatten.join
103
+ end
96
104
 
97
- def new_from_hash(hash)
98
- begin
99
- ::BCrypt::Password.new(hash)
100
- rescue ::BCrypt::Errors::InvalidHash
101
- return nil
102
- end
103
- end
105
+ def new_from_hash(hash)
106
+ ::BCrypt::Password.new(hash)
107
+ rescue ::BCrypt::Errors::InvalidHash
108
+ nil
109
+ end
104
110
  end
105
111
  end
106
112
  end
@@ -6,7 +6,8 @@ module Authlogic
6
6
  # I highly discourage using this crypto provider as it superbly inferior
7
7
  # to your other options.
8
8
  #
9
- # Please use any other provider offered by Authlogic.
9
+ # Please use any other provider offered by Authlogic (except AES256, that
10
+ # would be even worse).
10
11
  class MD5
11
12
  class << self
12
13
  attr_accessor :join_token
@@ -24,7 +25,8 @@ module Authlogic
24
25
  digest
25
26
  end
26
27
 
27
- # Does the crypted password match the tokens? Uses the same tokens that were used to encrypt.
28
+ # Does the crypted password match the tokens? Uses the same tokens that
29
+ # were used to encrypt.
28
30
  def matches?(crypted, *tokens)
29
31
  encrypt(*tokens) == crypted
30
32
  end
@@ -19,7 +19,13 @@ module Authlogic
19
19
  # end
20
20
  class SCrypt
21
21
  class << self
22
- DEFAULTS = { :key_len => 32, :salt_size => 8, :max_time => 0.2, :max_mem => 1024 * 1024, :max_memfrac => 0.5 }
22
+ DEFAULTS = {
23
+ key_len: 32,
24
+ salt_size: 8,
25
+ max_time: 0.2,
26
+ max_mem: 1024 * 1024,
27
+ max_memfrac: 0.5
28
+ }.freeze
23
29
 
24
30
  attr_writer :key_len, :salt_size, :max_time, :max_mem, :max_memfrac
25
31
  # Key length - length in bytes of generated key, from 16 to 512.
@@ -42,7 +48,8 @@ module Authlogic
42
48
  @max_mem ||= DEFAULTS[:max_mem]
43
49
  end
44
50
 
45
- # Max memory fraction - maximum memory out of all available. Always greater than zero and <= 0.5.
51
+ # Max memory fraction - maximum memory out of all available. Always
52
+ # greater than zero and <= 0.5.
46
53
  def max_memfrac
47
54
  @max_memfrac ||= DEFAULTS[:max_memfrac]
48
55
  end
@@ -51,11 +58,11 @@ module Authlogic
51
58
  def encrypt(*tokens)
52
59
  ::SCrypt::Password.create(
53
60
  join_tokens(tokens),
54
- :key_len => key_len,
55
- :salt_size => salt_size,
56
- :max_mem => max_mem,
57
- :max_memfrac => max_memfrac,
58
- :max_time => max_time
61
+ key_len: key_len,
62
+ salt_size: salt_size,
63
+ max_mem: max_mem,
64
+ max_memfrac: max_memfrac,
65
+ max_time: max_time
59
66
  )
60
67
  end
61
68
 
@@ -68,17 +75,15 @@ module Authlogic
68
75
 
69
76
  private
70
77
 
71
- def join_tokens(tokens)
72
- tokens.flatten.join
73
- end
78
+ def join_tokens(tokens)
79
+ tokens.flatten.join
80
+ end
74
81
 
75
- def new_from_hash(hash)
76
- begin
77
- ::SCrypt::Password.new(hash)
78
- rescue ::SCrypt::Errors::InvalidHash
79
- return nil
80
- end
81
- end
82
+ def new_from_hash(hash)
83
+ ::SCrypt::Password.new(hash)
84
+ rescue ::SCrypt::Errors::InvalidHash
85
+ nil
86
+ end
82
87
  end
83
88
  end
84
89
  end
@@ -2,8 +2,10 @@ require "digest/sha1"
2
2
 
3
3
  module Authlogic
4
4
  module CryptoProviders
5
- # This class was made for the users transitioning from restful_authentication. I highly discourage using this
6
- # crypto provider as it is far inferior to your other options. Please use any other provider offered by Authlogic.
5
+ # This class was made for the users transitioning from
6
+ # restful_authentication. Use of this crypto provider is highly discouraged.
7
+ # It is far inferior to your other options. Please use any other provider
8
+ # offered by Authlogic.
7
9
  class Sha1
8
10
  class << self
9
11
  def join_token
@@ -11,7 +13,8 @@ module Authlogic
11
13
  end
12
14
  attr_writer :join_token
13
15
 
14
- # The number of times to loop through the encryption. This is ten because that is what restful_authentication defaults to.
16
+ # The number of times to loop through the encryption. This is ten
17
+ # because that is what restful_authentication defaults to.
15
18
  def stretches
16
19
  @stretches ||= 10
17
20
  end
@@ -21,11 +24,14 @@ module Authlogic
21
24
  def encrypt(*tokens)
22
25
  tokens = tokens.flatten
23
26
  digest = tokens.shift
24
- stretches.times { digest = Digest::SHA1.hexdigest([digest, *tokens].join(join_token)) }
27
+ stretches.times do
28
+ digest = Digest::SHA1.hexdigest([digest, *tokens].join(join_token))
29
+ end
25
30
  digest
26
31
  end
27
32
 
28
- # Does the crypted password match the tokens? Uses the same tokens that were used to encrypt.
33
+ # Does the crypted password match the tokens? Uses the same tokens that
34
+ # were used to encrypt.
29
35
  def matches?(crypted, *tokens)
30
36
  encrypt(*tokens) == crypted
31
37
  end
@@ -1,22 +1,25 @@
1
1
  require "digest/sha2"
2
2
 
3
3
  module Authlogic
4
- # The acts_as_authentic method has a crypto_provider option. This allows you to use any type of encryption you like.
5
- # Just create a class with a class level encrypt and matches? method. See example below.
4
+ # The acts_as_authentic method has a crypto_provider option. This allows you
5
+ # to use any type of encryption you like. Just create a class with a class
6
+ # level encrypt and matches? method. See example below.
6
7
  #
7
8
  # === Example
8
9
  #
9
10
  # class MyAwesomeEncryptionMethod
10
11
  # def self.encrypt(*tokens)
11
- # # the tokens passed will be an array of objects, what type of object is irrelevant,
12
- # # just do what you need to do with them and return a single encrypted string.
13
- # # for example, you will most likely join all of the objects into a single string and then encrypt that string
12
+ # # the tokens passed will be an array of objects, what type of object
13
+ # # is irrelevant, just do what you need to do with them and return a
14
+ # # single encrypted string. for example, you will most likely join all
15
+ # # of the objects into a single string and then encrypt that string
14
16
  # end
15
17
  #
16
18
  # def self.matches?(crypted, *tokens)
17
- # # return true if the crypted string matches the tokens.
18
- # # depending on your algorithm you might decrypt the string then compare it to the token, or you might
19
- # # encrypt the tokens and make sure it matches the crypted string, its up to you
19
+ # # return true if the crypted string matches the tokens. Depending on
20
+ # # your algorithm you might decrypt the string then compare it to the
21
+ # # token, or you might encrypt the tokens and make sure it matches the
22
+ # # crypted string, its up to you.
20
23
  # end
21
24
  # end
22
25
  module CryptoProviders
@@ -40,7 +43,8 @@ module Authlogic
40
43
  digest
41
44
  end
42
45
 
43
- # Does the crypted password match the tokens? Uses the same tokens that were used to encrypt.
46
+ # Does the crypted password match the tokens? Uses the same tokens that
47
+ # were used to encrypt.
44
48
  def matches?(crypted, *tokens)
45
49
  encrypt(*tokens) == crypted
46
50
  end