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 CHANGED
@@ -1,3 +1,7 @@
1
+ == 1.4.3 released 2009-2-22
2
+
3
+ * Fixed issue with brute force protection.
4
+
1
5
  == 1.4.2 released 2009-2-20
2
6
 
3
7
  * Cleaned up callbacks system to use hooks and execute in the proper order.
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.2"
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-20}
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"]
@@ -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
@@ -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
- if !session.record.blank?
45
- @_logged_out = false
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
- # If we are already logged in, ignore this completely. All that we care about is updating ourself.
66
- next if #{options[:session_class]}.find(session_id, self)
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 :record, :unauthorized_record
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
- if valid_credentials?
326
- # hooks
327
- before_validation
328
- new_session? ? before_validation_on_create : before_validation_on_update
329
- validate
330
-
331
- valid_record?
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.save_without_session_maintenance(false) if record.changed?
338
-
339
- return true if errors.empty?
335
+ else
336
+ self.record = nil
340
337
  end
341
338
 
342
- self.record = nil
343
- false
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
- unchecked_record = search_for_record(find_by_login_method, send(login_field))
421
+ self.attempted_record = search_for_record(find_by_login_method, send(login_field))
430
422
 
431
- if unchecked_record.blank?
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 unchecked_record.send(verify_password_method, send("protected_#{password_field}"))
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
- unchecked_record = unauthorized_record
433
+ self.attempted_record = unauthorized_record
444
434
 
445
- if unchecked_record.blank?
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 unchecked_record.new_record?
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
- true
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.after_validation :increase_failed_login_count, :if => :protect_from_brute_force_attacks?
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.update_attribute(:failed_login_count, 0)
30
+ record.failed_login_count = 0
31
31
  end
32
32
 
33
33
  private
34
34
  def protect_from_brute_force_attacks?
35
- record && record.respond_to?(:failed_login_count) && consecutive_failed_logins_limit > 0
36
- end
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
- errors.add_to_base(I18n.t('error_messages.consecutive_failed_logins_limit_exceeded', :default => "Consecutive failed logins limit exceeded.")) if record.failed_login_count && record.failed_login_count >= consecutive_failed_logins_limit
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 !errors.empty?
48
- record.failed_login_count ||= 0
49
- record.failed_login_count += 1
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 :logout_on_timeout=, :logout_on_timeout
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
@@ -44,7 +44,7 @@ module Authlogic # :nodoc:
44
44
 
45
45
  MAJOR = 1
46
46
  MINOR = 4
47
- TINY = 2
47
+ TINY = 3
48
48
 
49
49
  # The current version as a Version instance
50
50
  CURRENT = new(MAJOR, MINOR, TINY)
@@ -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.2
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-20 00:00:00 -05:00
12
+ date: 2009-02-22 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency