authlogic 4.4.2 → 5.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. checksums.yaml +5 -5
  2. data/lib/authlogic.rb +4 -28
  3. data/lib/authlogic/acts_as_authentic/base.rb +3 -18
  4. data/lib/authlogic/acts_as_authentic/email.rb +3 -170
  5. data/lib/authlogic/acts_as_authentic/logged_in_status.rb +3 -1
  6. data/lib/authlogic/acts_as_authentic/login.rb +7 -174
  7. data/lib/authlogic/acts_as_authentic/magic_columns.rb +7 -4
  8. data/lib/authlogic/acts_as_authentic/password.rb +54 -253
  9. data/lib/authlogic/acts_as_authentic/perishable_token.rb +8 -5
  10. data/lib/authlogic/acts_as_authentic/persistence_token.rb +10 -4
  11. data/lib/authlogic/acts_as_authentic/queries/case_sensitivity.rb +53 -0
  12. data/lib/authlogic/acts_as_authentic/queries/find_with_case.rb +36 -20
  13. data/lib/authlogic/acts_as_authentic/session_maintenance.rb +8 -6
  14. data/lib/authlogic/acts_as_authentic/single_access_token.rb +10 -8
  15. data/lib/authlogic/config.rb +9 -1
  16. data/lib/authlogic/controller_adapters/abstract_adapter.rb +7 -4
  17. data/lib/authlogic/controller_adapters/rack_adapter.rb +2 -0
  18. data/lib/authlogic/controller_adapters/rails_adapter.rb +19 -19
  19. data/lib/authlogic/controller_adapters/sinatra_adapter.rb +6 -0
  20. data/lib/authlogic/cookie_credentials.rb +63 -0
  21. data/lib/authlogic/crypto_providers.rb +5 -20
  22. data/lib/authlogic/crypto_providers/bcrypt.rb +3 -3
  23. data/lib/authlogic/crypto_providers/md5.rb +3 -6
  24. data/lib/authlogic/crypto_providers/scrypt.rb +2 -0
  25. data/lib/authlogic/crypto_providers/sha1.rb +4 -6
  26. data/lib/authlogic/crypto_providers/sha256.rb +2 -0
  27. data/lib/authlogic/crypto_providers/sha512.rb +6 -5
  28. data/lib/authlogic/i18n.rb +3 -1
  29. data/lib/authlogic/i18n/translator.rb +3 -0
  30. data/lib/authlogic/random.rb +2 -0
  31. data/lib/authlogic/session/base.rb +2087 -39
  32. data/lib/authlogic/session/magic_column/assigns_last_request_at.rb +46 -0
  33. data/lib/authlogic/test_case.rb +4 -0
  34. data/lib/authlogic/test_case/mock_controller.rb +2 -0
  35. data/lib/authlogic/test_case/mock_cookie_jar.rb +7 -0
  36. data/lib/authlogic/test_case/mock_logger.rb +2 -0
  37. data/lib/authlogic/test_case/mock_request.rb +2 -0
  38. data/lib/authlogic/test_case/rails_request_adapter.rb +2 -0
  39. data/lib/authlogic/version.rb +2 -1
  40. metadata +136 -182
  41. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -28
  42. data/.github/ISSUE_TEMPLATE/feature_proposal.md +0 -32
  43. data/.github/triage.md +0 -86
  44. data/.gitignore +0 -15
  45. data/.rubocop.yml +0 -133
  46. data/.rubocop_todo.yml +0 -74
  47. data/.travis.yml +0 -24
  48. data/CHANGELOG.md +0 -326
  49. data/CONTRIBUTING.md +0 -91
  50. data/Gemfile +0 -6
  51. data/LICENSE +0 -20
  52. data/README.md +0 -439
  53. data/Rakefile +0 -21
  54. data/UPGRADING.md +0 -22
  55. data/authlogic.gemspec +0 -40
  56. data/doc/use_normal_rails_validation.md +0 -82
  57. data/gemfiles/Gemfile.rails-4.2.x +0 -6
  58. data/gemfiles/Gemfile.rails-5.1.x +0 -6
  59. data/gemfiles/Gemfile.rails-5.2.x +0 -6
  60. data/lib/authlogic/acts_as_authentic/restful_authentication.rb +0 -106
  61. data/lib/authlogic/acts_as_authentic/validations_scope.rb +0 -35
  62. data/lib/authlogic/authenticates_many/association.rb +0 -50
  63. data/lib/authlogic/authenticates_many/base.rb +0 -81
  64. data/lib/authlogic/crypto_providers/aes256.rb +0 -71
  65. data/lib/authlogic/crypto_providers/wordpress.rb +0 -72
  66. data/lib/authlogic/regex.rb +0 -79
  67. data/lib/authlogic/session/activation.rb +0 -73
  68. data/lib/authlogic/session/active_record_trickery.rb +0 -65
  69. data/lib/authlogic/session/brute_force_protection.rb +0 -127
  70. data/lib/authlogic/session/callbacks.rb +0 -153
  71. data/lib/authlogic/session/cookies.rb +0 -296
  72. data/lib/authlogic/session/existence.rb +0 -103
  73. data/lib/authlogic/session/foundation.rb +0 -105
  74. data/lib/authlogic/session/http_auth.rb +0 -107
  75. data/lib/authlogic/session/id.rb +0 -53
  76. data/lib/authlogic/session/klass.rb +0 -73
  77. data/lib/authlogic/session/magic_columns.rb +0 -119
  78. data/lib/authlogic/session/magic_states.rb +0 -82
  79. data/lib/authlogic/session/params.rb +0 -130
  80. data/lib/authlogic/session/password.rb +0 -318
  81. data/lib/authlogic/session/perishable_token.rb +0 -24
  82. data/lib/authlogic/session/persistence.rb +0 -77
  83. data/lib/authlogic/session/priority_record.rb +0 -38
  84. data/lib/authlogic/session/scopes.rb +0 -138
  85. data/lib/authlogic/session/session.rb +0 -77
  86. data/lib/authlogic/session/timeout.rb +0 -103
  87. data/lib/authlogic/session/unauthorized_record.rb +0 -56
  88. data/lib/authlogic/session/validation.rb +0 -93
  89. data/test/acts_as_authentic_test/base_test.rb +0 -27
  90. data/test/acts_as_authentic_test/email_test.rb +0 -241
  91. data/test/acts_as_authentic_test/logged_in_status_test.rb +0 -64
  92. data/test/acts_as_authentic_test/login_test.rb +0 -153
  93. data/test/acts_as_authentic_test/magic_columns_test.rb +0 -29
  94. data/test/acts_as_authentic_test/password_test.rb +0 -263
  95. data/test/acts_as_authentic_test/perishable_token_test.rb +0 -98
  96. data/test/acts_as_authentic_test/persistence_token_test.rb +0 -62
  97. data/test/acts_as_authentic_test/restful_authentication_test.rb +0 -48
  98. data/test/acts_as_authentic_test/session_maintenance_test.rb +0 -150
  99. data/test/acts_as_authentic_test/single_access_test.rb +0 -46
  100. data/test/adapter_test.rb +0 -23
  101. data/test/authenticates_many_test.rb +0 -33
  102. data/test/config_test.rb +0 -38
  103. data/test/crypto_provider_test/aes256_test.rb +0 -16
  104. data/test/crypto_provider_test/bcrypt_test.rb +0 -16
  105. data/test/crypto_provider_test/scrypt_test.rb +0 -16
  106. data/test/crypto_provider_test/sha1_test.rb +0 -25
  107. data/test/crypto_provider_test/sha256_test.rb +0 -16
  108. data/test/crypto_provider_test/sha512_test.rb +0 -16
  109. data/test/crypto_provider_test/wordpress_test.rb +0 -26
  110. data/test/fixtures/companies.yml +0 -5
  111. data/test/fixtures/employees.yml +0 -17
  112. data/test/fixtures/projects.yml +0 -3
  113. data/test/fixtures/users.yml +0 -41
  114. data/test/i18n/lol.yml +0 -4
  115. data/test/i18n_test.rb +0 -35
  116. data/test/libs/affiliate.rb +0 -9
  117. data/test/libs/company.rb +0 -8
  118. data/test/libs/employee.rb +0 -9
  119. data/test/libs/employee_session.rb +0 -4
  120. data/test/libs/ldaper.rb +0 -5
  121. data/test/libs/project.rb +0 -5
  122. data/test/libs/user.rb +0 -9
  123. data/test/libs/user_session.rb +0 -27
  124. data/test/random_test.rb +0 -15
  125. data/test/session_test/activation_test.rb +0 -45
  126. data/test/session_test/active_record_trickery_test.rb +0 -78
  127. data/test/session_test/brute_force_protection_test.rb +0 -110
  128. data/test/session_test/callbacks_test.rb +0 -42
  129. data/test/session_test/cookies_test.rb +0 -226
  130. data/test/session_test/credentials_test.rb +0 -0
  131. data/test/session_test/existence_test.rb +0 -88
  132. data/test/session_test/foundation_test.rb +0 -24
  133. data/test/session_test/http_auth_test.rb +0 -60
  134. data/test/session_test/id_test.rb +0 -19
  135. data/test/session_test/klass_test.rb +0 -42
  136. data/test/session_test/magic_columns_test.rb +0 -62
  137. data/test/session_test/magic_states_test.rb +0 -60
  138. data/test/session_test/params_test.rb +0 -61
  139. data/test/session_test/password_test.rb +0 -107
  140. data/test/session_test/perishability_test.rb +0 -17
  141. data/test/session_test/persistence_test.rb +0 -35
  142. data/test/session_test/scopes_test.rb +0 -68
  143. data/test/session_test/session_test.rb +0 -80
  144. data/test/session_test/timeout_test.rb +0 -84
  145. data/test/session_test/unauthorized_record_test.rb +0 -15
  146. data/test/session_test/validation_test.rb +0 -25
  147. data/test/test_helper.rb +0 -272
@@ -1,71 +0,0 @@
1
- require "openssl"
2
-
3
- module Authlogic
4
- module CryptoProviders
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:
9
- #
10
- # Authlogic::CryptoProviders::AES256.key = "long, unique, and random key"
11
- #
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.
15
- #
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.
22
- class AES256
23
- class << self
24
- attr_writer :key
25
-
26
- def encrypt(*tokens)
27
- aes.encrypt
28
- aes.key = @key
29
- [aes.update(tokens.join) + aes.final].pack("m").chomp
30
- end
31
-
32
- def matches?(crypted, *tokens)
33
- aes.decrypt
34
- aes.key = @key
35
- (aes.update(crypted.unpack("m").first) + aes.final) == tokens.join
36
- rescue OpenSSL::CipherError
37
- false
38
- end
39
-
40
- private
41
-
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
- )
47
- end
48
-
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
66
- end
67
- end
68
- end
69
- end
70
- end
71
- end
@@ -1,72 +0,0 @@
1
- require "digest/md5"
2
-
3
- ::ActiveSupport::Deprecation.warn(
4
- <<~EOS,
5
- authlogic/crypto_providers/wordpress.rb is deprecated without replacement.
6
- Yes, the entire file. Don't `require` it. Let us know ASAP if you are still
7
- using it.
8
-
9
- Reasons for deprecation: This file is not autoloaded by
10
- `authlogic/crypto_providers.rb`. It's not documented. There are no tests.
11
- So, it's likely used by a *very* small number of people, if any. It's never
12
- had any contributions except by its original author, Jeffry Degrande, in
13
- 2009. It is unclear why it should live in the main authlogic codebase. It
14
- could be in a separate gem, authlogic-wordpress, or it could just live in
15
- Jeffry's codebase, if he still even needs it, in 2018, nine years later.
16
- EOS
17
- caller(1)
18
- )
19
-
20
- module Authlogic
21
- module CryptoProviders
22
- # Crypto provider to transition from wordpress user accounts. Written by
23
- # Jeffry Degrande in 2009. First released in 2.1.3.
24
- #
25
- # Problems:
26
- #
27
- # - There are no tests.
28
- # - We can't even figure out how to run this without it crashing.
29
- # - Presumably it implements some spec, but it doesn't mention which.
30
- # - It is not documented anywhere.
31
- # - There is no PR associated with this, and no discussion about it could be found.
32
- #
33
- class Wordpress
34
- class << self
35
- ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".freeze
36
-
37
- def matches?(crypted, *tokens)
38
- stretches = 1 << ITOA64.index(crypted[3, 1])
39
- plain, salt = *tokens
40
- hashed = Digest::MD5.digest(salt + plain)
41
- stretches.times do
42
- hashed = Digest::MD5.digest(hashed + plain)
43
- end
44
- crypted[0, 12] + encode_64(hashed, 16) == crypted
45
- end
46
-
47
- def encode_64(input, length)
48
- output = ""
49
- i = 0
50
- while i < length
51
- value = input[i]
52
- i += 1
53
- break if value.nil?
54
- output += ITOA64[value & 0x3f, 1]
55
- value |= input[i] << 8 if i < length
56
- output += ITOA64[(value >> 6) & 0x3f, 1]
57
-
58
- i += 1
59
- break if i >= length
60
- value |= input[i] << 16 if i < length
61
- output += ITOA64[(value >> 12) & 0x3f, 1]
62
-
63
- i += 1
64
- break if i >= length
65
- output += ITOA64[(value >> 18) & 0x3f, 1]
66
- end
67
- output
68
- end
69
- end
70
- end
71
- end
72
- end
@@ -1,79 +0,0 @@
1
- module Authlogic
2
- # This is a module the contains regular expressions used throughout Authlogic.
3
- # The point of extracting them out into their own module is to make them
4
- # easily available to you for other uses. Ex:
5
- #
6
- # validates_format_of :my_email_field, :with => Authlogic::Regex.email
7
- module Regex
8
- # A general email regular expression. It allows top level domains (TLD) to
9
- # be from 2 - 24 in length. The decisions behind this regular expression
10
- # were made by analyzing the list of top-level domains maintained by IANA
11
- # and by reading this website:
12
- # http://www.regular-expressions.info/email.html, which is an excellent
13
- # resource for regular expressions.
14
- EMAIL = /
15
- \A
16
- [A-Z0-9_.&%+\-']+ # mailbox
17
- @
18
- (?:[A-Z0-9\-]+\.)+ # subdomains
19
- (?:[A-Z]{2,25}) # TLD
20
- \z
21
- /ix
22
-
23
- # A draft regular expression for internationalized email addresses. Given
24
- # that the standard may be in flux, this simply emulates @email_regex but
25
- # rather than allowing specific characters for each part, it instead
26
- # disallows the complement set of characters:
27
- #
28
- # - email_name_regex disallows: @[]^ !"#$()*,/:;<=>?`{|}~\ and control characters
29
- # - domain_head_regex disallows: _%+ and all characters in email_name_regex
30
- # - domain_tld_regex disallows: 0123456789- and all characters in domain_head_regex
31
- #
32
- # http://en.wikipedia.org/wiki/Email_address#Internationalization
33
- # http://tools.ietf.org/html/rfc6530
34
- # http://www.unicode.org/faq/idn.html
35
- # http://ruby-doc.org/core-2.1.5/Regexp.html#class-Regexp-label-Character+Classes
36
- # http://en.wikipedia.org/wiki/Unicode_character_property#General_Category
37
- EMAIL_NONASCII = /
38
- \A
39
- [^[:cntrl:][@\[\]\^ \!"\#$\(\)*,\/:;<=>?`{|}~\\]]+ # mailbox
40
- @
41
- (?:[^[:cntrl:][@\[\]\^ \!\"\#$&\(\)*,\/:;<=>\?`{|}~\\_.%+']]+\.)+ # subdomains
42
- (?:[^[:cntrl:][@\[\]\^ \!\"\#$&\(\)*,\/:;<=>\?`{|}~\\_.%+\-'0-9]]{2,25}) # TLD
43
- \z
44
- /x
45
-
46
- # A simple regular expression that only allows for letters, numbers, spaces, and
47
- # .-_@+. Just a standard login / username regular expression.
48
- LOGIN = /\A[a-zA-Z0-9_][a-zA-Z0-9\.+\-_@ ]+\z/
49
-
50
- # Accessing the above constants using the following methods is deprecated.
51
-
52
- # @deprecated
53
- def self.email
54
- ::ActiveSupport::Deprecation.warn(
55
- "Authlogic::Regex.email is deprecated, use Authlogic::Regex::EMAIL",
56
- caller(1)
57
- )
58
- EMAIL
59
- end
60
-
61
- # @deprecated
62
- def self.email_nonascii
63
- ::ActiveSupport::Deprecation.warn(
64
- "Authlogic::Regex.email_nonascii is deprecated, use Authlogic::Regex::EMAIL_NONASCII",
65
- caller(1)
66
- )
67
- EMAIL_NONASCII
68
- end
69
-
70
- # @deprecated
71
- def self.login
72
- ::ActiveSupport::Deprecation.warn(
73
- "Authlogic::Regex.login is deprecated, use Authlogic::Regex::LOGIN",
74
- caller(1)
75
- )
76
- LOGIN
77
- end
78
- end
79
- end
@@ -1,73 +0,0 @@
1
- require "request_store"
2
-
3
- module Authlogic
4
- module Session
5
- # Activating Authlogic requires that you pass it an
6
- # Authlogic::ControllerAdapters::AbstractAdapter object, or a class that
7
- # extends it. This is sort of like a database connection for an ORM library,
8
- # Authlogic can't do anything until it is "connected" to a controller. If
9
- # you are using a supported framework, Authlogic takes care of this for you.
10
- module Activation
11
- class NotActivatedError < ::StandardError # :nodoc:
12
- def initialize
13
- super(
14
- "You must activate the Authlogic::Session::Base.controller with " \
15
- "a controller object before creating objects"
16
- )
17
- end
18
- end
19
-
20
- def self.included(klass)
21
- klass.class_eval do
22
- extend ClassMethods
23
- include InstanceMethods
24
- end
25
- end
26
-
27
- module ClassMethods
28
- # Returns true if a controller has been set and can be used properly.
29
- # This MUST be set before anything can be done. Similar to how
30
- # ActiveRecord won't allow you to do anything without establishing a DB
31
- # connection. In your framework environment this is done for you, but if
32
- # you are using Authlogic outside of your framework, you need to assign
33
- # a controller object to Authlogic via
34
- # Authlogic::Session::Base.controller = obj. See the controller= method
35
- # for more information.
36
- def activated?
37
- !controller.nil?
38
- end
39
-
40
- # This accepts a controller object wrapped with the Authlogic controller
41
- # adapter. The controller adapters close the gap between the different
42
- # controllers in each framework. That being said, Authlogic is expecting
43
- # your object's class to extend
44
- # Authlogic::ControllerAdapters::AbstractAdapter. See
45
- # Authlogic::ControllerAdapters for more info.
46
- #
47
- # Lastly, this is thread safe.
48
- def controller=(value)
49
- RequestStore.store[:authlogic_controller] = value
50
- end
51
-
52
- # The current controller object
53
- def controller
54
- RequestStore.store[:authlogic_controller]
55
- end
56
- end
57
-
58
- module InstanceMethods
59
- # Making sure we are activated before we start creating objects
60
- def initialize(*args)
61
- raise NotActivatedError unless self.class.activated?
62
- super
63
- end
64
-
65
- private
66
-
67
- def controller
68
- self.class.controller
69
- end
70
- end
71
- end
72
- end
73
- end
@@ -1,65 +0,0 @@
1
- module Authlogic
2
- module Session
3
- # Authlogic looks like ActiveRecord, sounds like ActiveRecord, but its not
4
- # ActiveRecord. That's the goal here. This is useful for the various rails
5
- # helper methods such as form_for, error_messages_for, or any method that
6
- # expects an ActiveRecord object. The point is to disguise the object as an
7
- # ActiveRecord object so we can take advantage of the many ActiveRecord
8
- # tools.
9
- module ActiveRecordTrickery
10
- def self.included(klass)
11
- klass.extend ActiveModel::Naming
12
- klass.extend ActiveModel::Translation
13
-
14
- # Support ActiveModel::Name#name for Rails versions before 4.0.
15
- unless klass.model_name.respond_to?(:name)
16
- ActiveModel::Name.module_eval do
17
- alias_method :name, :to_s
18
- end
19
- end
20
-
21
- klass.extend ClassMethods
22
- klass.send(:include, InstanceMethods)
23
- end
24
-
25
- module ClassMethods
26
- # How to name the class, works JUST LIKE ActiveRecord, except it uses
27
- # the following namespace:
28
- #
29
- # authlogic.models.user_session
30
- def human_name(*)
31
- I18n.t("models.#{name.underscore}", count: 1, default: name.humanize)
32
- end
33
-
34
- def i18n_scope
35
- I18n.scope
36
- end
37
- end
38
-
39
- module InstanceMethods
40
- # Don't use this yourself, this is to just trick some of the helpers
41
- # since this is the method it calls.
42
- def new_record?
43
- new_session?
44
- end
45
-
46
- def persisted?
47
- !(new_record? || destroyed?)
48
- end
49
-
50
- def destroyed?
51
- record.nil?
52
- end
53
-
54
- def to_key
55
- new_record? ? nil : record.to_key
56
- end
57
-
58
- # For rails >= 3.0
59
- def to_model
60
- self
61
- end
62
- end
63
- end
64
- end
65
- end
@@ -1,127 +0,0 @@
1
- module Authlogic
2
- module Session
3
- # A brute force attacks is executed by hammering a login with as many password
4
- # combinations as possible, until one works. A brute force attacked is generally
5
- # combated with a slow hashing algorithm such as BCrypt. You can increase the cost,
6
- # which makes the hash generation slower, and ultimately increases the time it takes
7
- # to execute a brute force attack. Just to put this into perspective, if a hacker was
8
- # to gain access to your server and execute a brute force attack locally, meaning
9
- # there is no network lag, it would probably take decades to complete. Now throw in
10
- # network lag and it would take MUCH longer.
11
- #
12
- # But for those that are extra paranoid and can't get enough protection, why not stop
13
- # them as soon as you realize something isn't right? That's what this module is all
14
- # about. By default the consecutive_failed_logins_limit configuration option is set to
15
- # 50, if someone consecutively fails to login after 50 attempts their account will be
16
- # suspended. This is a very liberal number and at this point it should be obvious that
17
- # something is not right. If you wish to lower this number just set the configuration
18
- # to a lower number:
19
- #
20
- # class UserSession < Authlogic::Session::Base
21
- # consecutive_failed_logins_limit 10
22
- # end
23
- module BruteForceProtection
24
- def self.included(klass)
25
- klass.class_eval do
26
- extend Config
27
- include InstanceMethods
28
- validate :reset_failed_login_count, if: :reset_failed_login_count?
29
- validate :validate_failed_logins, if: :being_brute_force_protected?
30
- end
31
- end
32
-
33
- # Configuration for the brute force protection feature.
34
- module Config
35
- # To help protect from brute force attacks you can set a limit on the
36
- # allowed number of consecutive failed logins. By default this is 50,
37
- # this is a very liberal number, and if someone fails to login after 50
38
- # tries it should be pretty obvious that it's a machine trying to login
39
- # in and very likely a brute force attack.
40
- #
41
- # In order to enable this field your model MUST have a
42
- # failed_login_count (integer) field.
43
- #
44
- # If you don't know what a brute force attack is, it's when a machine
45
- # tries to login into a system using every combination of character
46
- # possible. Thus resulting in possibly millions of attempts to log into
47
- # an account.
48
- #
49
- # * <tt>Default:</tt> 50
50
- # * <tt>Accepts:</tt> Integer, set to 0 to disable
51
- def consecutive_failed_logins_limit(value = nil)
52
- rw_config(:consecutive_failed_logins_limit, value, 50)
53
- end
54
- alias_method :consecutive_failed_logins_limit=, :consecutive_failed_logins_limit
55
-
56
- # Once the failed logins limit has been exceed, how long do you want to
57
- # ban the user? This can be a temporary or permanent ban.
58
- #
59
- # * <tt>Default:</tt> 2.hours
60
- # * <tt>Accepts:</tt> Fixnum, set to 0 for permanent ban
61
- def failed_login_ban_for(value = nil)
62
- rw_config(:failed_login_ban_for, (!value.nil? && value) || value, 2.hours.to_i)
63
- end
64
- alias_method :failed_login_ban_for=, :failed_login_ban_for
65
- end
66
-
67
- # The methods available for an Authlogic::Session::Base object that make
68
- # up the brute force protection feature.
69
- module InstanceMethods
70
- # Returns true when the consecutive_failed_logins_limit has been
71
- # exceeded and is being temporarily banned. Notice the word temporary,
72
- # the user will not be permanently banned unless you choose to do so
73
- # with configuration. By default they will be banned for 2 hours. During
74
- # that 2 hour period this method will return true.
75
- def being_brute_force_protected?
76
- exceeded_failed_logins_limit? &&
77
- (
78
- failed_login_ban_for <= 0 ||
79
- attempted_record.respond_to?(:updated_at) &&
80
- attempted_record.updated_at >= failed_login_ban_for.seconds.ago
81
- )
82
- end
83
-
84
- private
85
-
86
- def exceeded_failed_logins_limit?
87
- !attempted_record.nil? &&
88
- attempted_record.respond_to?(:failed_login_count) &&
89
- consecutive_failed_logins_limit > 0 &&
90
- attempted_record.failed_login_count &&
91
- attempted_record.failed_login_count >= consecutive_failed_logins_limit
92
- end
93
-
94
- def reset_failed_login_count?
95
- exceeded_failed_logins_limit? && !being_brute_force_protected?
96
- end
97
-
98
- def reset_failed_login_count
99
- attempted_record.failed_login_count = 0
100
- end
101
-
102
- def validate_failed_logins
103
- # Clear all other error messages, as they are irrelevant at this point and can
104
- # only provide additional information that is not needed
105
- errors.clear
106
- errors.add(
107
- :base,
108
- I18n.t(
109
- "error_messages.consecutive_failed_logins_limit_exceeded",
110
- default: "Consecutive failed logins limit exceeded, account has been" +
111
- (failed_login_ban_for.zero? ? "" : " temporarily") +
112
- " disabled."
113
- )
114
- )
115
- end
116
-
117
- def consecutive_failed_logins_limit
118
- self.class.consecutive_failed_logins_limit
119
- end
120
-
121
- def failed_login_ban_for
122
- self.class.failed_login_ban_for
123
- end
124
- end
125
- end
126
- end
127
- end