authlogic 1.4.2 → 1.4.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of authlogic might be problematic. Click here for more details.
- data/CHANGELOG.rdoc +4 -0
- data/authlogic.gemspec +2 -2
- data/lib/authlogic/i18n.rb +1 -1
- data/lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/session_maintenance.rb +6 -12
- data/lib/authlogic/session/base.rb +23 -34
- data/lib/authlogic/session/brute_force_protection.rb +11 -11
- data/lib/authlogic/session/config.rb +1 -1
- data/lib/authlogic/version.rb +1 -1
- data/test/session_tests/brute_force_protection_test.rb +34 -0
- metadata +2 -2
data/CHANGELOG.rdoc
CHANGED
data/authlogic.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{authlogic}
|
5
|
-
s.version = "1.4.
|
5
|
+
s.version = "1.4.3"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Ben Johnson of Binary Logic"]
|
9
|
-
s.date = %q{2009-02-
|
9
|
+
s.date = %q{2009-02-22}
|
10
10
|
s.description = %q{A clean, simple, and unobtrusive ruby authentication solution.}
|
11
11
|
s.email = %q{bjohnson@binarylogic.com}
|
12
12
|
s.extra_rdoc_files = ["CHANGELOG.rdoc", "lib/authlogic/controller_adapters/abstract_adapter.rb", "lib/authlogic/controller_adapters/merb_adapter.rb", "lib/authlogic/controller_adapters/rails_adapter.rb", "lib/authlogic/crypto_providers/aes256.rb", "lib/authlogic/crypto_providers/bcrypt.rb", "lib/authlogic/crypto_providers/sha1.rb", "lib/authlogic/crypto_providers/sha512.rb", "lib/authlogic/i18n.rb", "lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/base.rb", "lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/config.rb", "lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/credentials.rb", "lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/logged_in.rb", "lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/perishability.rb", "lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/persistence.rb", "lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/session_maintenance.rb", "lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/single_access.rb", "lib/authlogic/orm_adapters/active_record_adapter/authenticates_many.rb", "lib/authlogic/session/active_record_trickery.rb", "lib/authlogic/session/authenticates_many_association.rb", "lib/authlogic/session/base.rb", "lib/authlogic/session/brute_force_protection.rb", "lib/authlogic/session/callbacks.rb", "lib/authlogic/session/config.rb", "lib/authlogic/session/cookies.rb", "lib/authlogic/session/errors.rb", "lib/authlogic/session/params.rb", "lib/authlogic/session/perishability.rb", "lib/authlogic/session/record_info.rb", "lib/authlogic/session/scopes.rb", "lib/authlogic/session/session.rb", "lib/authlogic/session/timeout.rb", "lib/authlogic/testing/test_unit_helpers.rb", "lib/authlogic/version.rb", "lib/authlogic.rb", "README.rdoc"]
|
data/lib/authlogic/i18n.rb
CHANGED
@@ -33,7 +33,7 @@ module Authlogic
|
|
33
33
|
# login_blank: can not be blank
|
34
34
|
# login_not_found: does not exist
|
35
35
|
# login_invalid: should use only letters, numbers, spaces, and .-_@ please.
|
36
|
-
# consecutive_failed_logins_limit_exceeded: Consecutive failed logins limit exceeded.
|
36
|
+
# consecutive_failed_logins_limit_exceeded: Consecutive failed logins limit exceeded, account is disabled.
|
37
37
|
# email_invalid: should look like an email address.
|
38
38
|
# password_blank: can not be blank
|
39
39
|
# password_invalid: is not valid
|
data/lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/session_maintenance.rb
CHANGED
@@ -40,11 +40,9 @@ module Authlogic
|
|
40
40
|
|
41
41
|
#{options[:session_ids].inspect}.each do |session_id|
|
42
42
|
session = #{options[:session_class]}.find(session_id, self)
|
43
|
-
if session
|
44
|
-
|
45
|
-
|
46
|
-
@_sessions << session if session.record == self
|
47
|
-
end
|
43
|
+
if session && !session.record.blank?
|
44
|
+
@_logged_out = false
|
45
|
+
@_sessions << session if session.record == self
|
48
46
|
end
|
49
47
|
end
|
50
48
|
end
|
@@ -61,13 +59,9 @@ module Authlogic
|
|
61
59
|
# We only want to automatically login into the first session, since this is the main session. The other sessions are sessions
|
62
60
|
# that need to be created after logging into the main session.
|
63
61
|
session_id = #{options[:session_ids].inspect}.first
|
64
|
-
|
65
|
-
#
|
66
|
-
|
67
|
-
|
68
|
-
# Log me in
|
69
|
-
args = [self, session_id].compact
|
70
|
-
#{options[:session_class]}.create(*args)
|
62
|
+
|
63
|
+
# Log me in, only if we aren't already logged in
|
64
|
+
#{options[:session_class]}.create(*[self, session_id].compact) if !#{options[:session_class]}.find(session_id, self)
|
71
65
|
end
|
72
66
|
|
73
67
|
def update_sessions!
|
@@ -93,8 +93,8 @@ module Authlogic
|
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
|
-
attr_accessor :new_session
|
97
|
-
attr_reader :
|
96
|
+
attr_accessor :attempted_record, :new_session, :record
|
97
|
+
attr_reader :unauthorized_record
|
98
98
|
attr_writer :authenticating_with, :id, :persisting
|
99
99
|
|
100
100
|
# You can initialize a session by doing any of the following:
|
@@ -322,25 +322,23 @@ module Authlogic
|
|
322
322
|
# you will not have a record.
|
323
323
|
def valid?
|
324
324
|
errors.clear
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
# hooks
|
325
|
+
self.attempted_record = nil
|
326
|
+
|
327
|
+
before_validation
|
328
|
+
new_session? ? before_validation_on_create : before_validation_on_update
|
329
|
+
valid_credentials?
|
330
|
+
validate
|
331
|
+
|
332
|
+
if errors.empty?
|
334
333
|
new_session? ? after_validation_on_create : after_validation_on_update
|
335
334
|
after_validation
|
336
|
-
|
337
|
-
record
|
338
|
-
|
339
|
-
return true if errors.empty?
|
335
|
+
else
|
336
|
+
self.record = nil
|
340
337
|
end
|
341
338
|
|
342
|
-
|
343
|
-
|
339
|
+
attempted_record.save_without_session_maintenance(false) if attempted_record && attempted_record.changed?
|
340
|
+
self.attempted_record = nil
|
341
|
+
errors.empty?
|
344
342
|
end
|
345
343
|
|
346
344
|
# Tries to validate the session from information from a basic http auth, if it was provided.
|
@@ -409,53 +407,44 @@ module Authlogic
|
|
409
407
|
self.class.klass_name
|
410
408
|
end
|
411
409
|
|
412
|
-
def record=(value)
|
413
|
-
@record = value
|
414
|
-
end
|
415
|
-
|
416
410
|
def search_for_record(method, value)
|
417
411
|
klass.send(method, value)
|
418
412
|
end
|
419
413
|
|
420
414
|
def valid_credentials?
|
421
|
-
unchecked_record = nil
|
422
|
-
|
423
415
|
case authenticating_with
|
424
416
|
when :password
|
425
417
|
errors.add(login_field, I18n.t('error_messages.login_blank', :default => "can not be blank")) if send(login_field).blank?
|
426
418
|
errors.add(password_field, I18n.t('error_messages.password_blank', :default => "can not be blank")) if send("protected_#{password_field}").blank?
|
427
419
|
return false if errors.count > 0
|
428
420
|
|
429
|
-
|
421
|
+
self.attempted_record = search_for_record(find_by_login_method, send(login_field))
|
430
422
|
|
431
|
-
if
|
423
|
+
if attempted_record.blank?
|
432
424
|
errors.add(login_field, I18n.t('error_messages.login_not_found', :default => "does not exist"))
|
433
425
|
return false
|
434
426
|
end
|
435
427
|
|
436
|
-
unless
|
428
|
+
unless attempted_record.send(verify_password_method, send("protected_#{password_field}"))
|
437
429
|
errors.add(password_field, I18n.t('error_messages.password_invalid', :default => "is not valid"))
|
438
430
|
return false
|
439
431
|
end
|
440
|
-
|
441
|
-
self.record = unchecked_record
|
442
432
|
when :unauthorized_record
|
443
|
-
|
433
|
+
self.attempted_record = unauthorized_record
|
444
434
|
|
445
|
-
if
|
435
|
+
if attempted_record.blank?
|
446
436
|
errors.add_to_base(I18n.t('error_messages.blank_record', :default => "You can not login with a blank record"))
|
447
437
|
return false
|
448
438
|
end
|
449
439
|
|
450
|
-
if
|
440
|
+
if attempted_record.new_record?
|
451
441
|
errors.add_to_base(I18n.t('error_messages.new_record', :default => "You can not login with a new record"))
|
452
442
|
return false
|
453
443
|
end
|
454
|
-
|
455
|
-
self.record = unchecked_record
|
456
444
|
end
|
457
445
|
|
458
|
-
|
446
|
+
self.record = attempted_record
|
447
|
+
valid_record?
|
459
448
|
end
|
460
449
|
|
461
450
|
def valid_record?
|
@@ -19,7 +19,7 @@ module Authlogic
|
|
19
19
|
module BruteForceProtection
|
20
20
|
def self.included(klass)
|
21
21
|
klass.validate :validate_failed_logins, :if => :protect_from_brute_force_attacks?
|
22
|
-
klass.
|
22
|
+
klass.validate :increase_failed_login_count, :if => :protect_from_brute_force_attacks?
|
23
23
|
klass.after_save :reset_failed_login_count, :if => :protect_from_brute_force_attacks?
|
24
24
|
end
|
25
25
|
|
@@ -27,26 +27,26 @@ module Authlogic
|
|
27
27
|
# trying to login. So, if an account exceeds the limit the only way they will be able to log back in is if your execute this
|
28
28
|
# method, which merely resets the failed_login_count field to 0.
|
29
29
|
def reset_failed_login_count
|
30
|
-
record.
|
30
|
+
record.failed_login_count = 0
|
31
31
|
end
|
32
32
|
|
33
33
|
private
|
34
34
|
def protect_from_brute_force_attacks?
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
def record_by_login
|
39
|
-
unchecked_record = search_for_record(find_by_login_method, send(login_field))
|
35
|
+
r = attempted_record || record
|
36
|
+
r && r.respond_to?(:failed_login_count) && consecutive_failed_logins_limit > 0
|
40
37
|
end
|
41
38
|
|
42
39
|
def validate_failed_logins
|
43
|
-
|
40
|
+
if attempted_record.failed_login_count && attempted_record.failed_login_count >= consecutive_failed_logins_limit
|
41
|
+
errors.clear # Clear all other error messages, as they are irrelevant at this point and can only provide additional information that is not needed
|
42
|
+
errors.add_to_base(I18n.t('error_messages.consecutive_failed_logins_limit_exceeded', :default => "Consecutive failed logins limit exceeded, account is disabled."))
|
43
|
+
end
|
44
44
|
end
|
45
45
|
|
46
46
|
def increase_failed_login_count
|
47
|
-
if
|
48
|
-
|
49
|
-
|
47
|
+
if errors.on(password_field)
|
48
|
+
attempted_record.failed_login_count ||= 0
|
49
|
+
attempted_record.failed_login_count += 1
|
50
50
|
end
|
51
51
|
end
|
52
52
|
end
|
@@ -202,7 +202,7 @@ module Authlogic
|
|
202
202
|
write_inheritable_attribute(:consecutive_failed_logins_limit, value)
|
203
203
|
end
|
204
204
|
end
|
205
|
-
alias_method :
|
205
|
+
alias_method :consecutive_failed_logins_limit=, :consecutive_failed_logins_limit
|
206
206
|
|
207
207
|
def not_active_message(value = nil) # :nodoc:
|
208
208
|
new_i18n_error
|
data/lib/authlogic/version.rb
CHANGED
@@ -15,5 +15,39 @@ module SessionTests
|
|
15
15
|
assert ben.save
|
16
16
|
assert !UserSession.create(:login => ben.login, :password => "benrocks")
|
17
17
|
end
|
18
|
+
|
19
|
+
def test_exeeding_failed_logins_limit
|
20
|
+
UserSession.consecutive_failed_logins_limit = 2
|
21
|
+
ben = users(:ben)
|
22
|
+
|
23
|
+
2.times do |i|
|
24
|
+
session = UserSession.new(:login => ben.login, :password => "badpassword")
|
25
|
+
assert !session.save
|
26
|
+
assert session.errors.on(:password)
|
27
|
+
assert_equal i + 1, ben.reload.failed_login_count
|
28
|
+
end
|
29
|
+
|
30
|
+
session = UserSession.new(:login => ben.login, :password => "badpassword2")
|
31
|
+
assert !session.save
|
32
|
+
assert !session.errors.on(:password)
|
33
|
+
assert_equal 2, ben.reload.failed_login_count
|
34
|
+
|
35
|
+
UserSession.consecutive_failed_logins_limit = 50
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_resetting_failed_logins_count
|
39
|
+
ben = users(:ben)
|
40
|
+
|
41
|
+
2.times do |i|
|
42
|
+
session = UserSession.new(:login => ben.login, :password => "badpassword")
|
43
|
+
assert !session.save
|
44
|
+
assert session.errors.on(:password)
|
45
|
+
assert_equal i + 1, ben.reload.failed_login_count
|
46
|
+
end
|
47
|
+
|
48
|
+
session = UserSession.new(:login => ben.login, :password => "benrocks")
|
49
|
+
assert session.save
|
50
|
+
assert_equal 0, ben.reload.failed_login_count
|
51
|
+
end
|
18
52
|
end
|
19
53
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: authlogic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.4.
|
4
|
+
version: 1.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Johnson of Binary Logic
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-02-
|
12
|
+
date: 2009-02-22 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|