authlogic 4.4.2 → 5.0.3

Sign up to get free protection for your applications and to get access to all the features.
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