##// END OF EJS Templates
Invalidate security tokens on password or email changes (#17717)....
Jean-Baptiste Barth -
r13033:2eb95f41b41d
parent child
Show More
@@ -112,7 +112,7 class User < Principal
112 before_create :set_mail_notification
112 before_create :set_mail_notification
113 before_save :generate_password_if_needed, :update_hashed_password
113 before_save :generate_password_if_needed, :update_hashed_password
114 before_destroy :remove_references_before_destroy
114 before_destroy :remove_references_before_destroy
115 after_save :update_notified_project_ids
115 after_save :update_notified_project_ids, :destroy_tokens
116
116
117 scope :in_group, lambda {|group|
117 scope :in_group, lambda {|group|
118 group_id = group.is_a?(Group) ? group.id : group.to_i
118 group_id = group.is_a?(Group) ? group.id : group.to_i
@@ -681,6 +681,18 class User < Principal
681 end
681 end
682 end
682 end
683
683
684 # Delete all outstanding password reset tokens on password or email change.
685 # Delete the autologin tokens on password change to prohibit session leakage.
686 # This helps to keep the account secure in case the associated email account
687 # was compromised.
688 def destroy_tokens
689 tokens = []
690 tokens |= ['recovery', 'autologin'] if changes.has_key?('hashed_password')
691 tokens |= ['recovery'] if changes.has_key?('mail')
692
693 Token.delete_all(['user_id = ? AND action IN (?)', self.id, tokens]) if tokens.any?
694 end
695
684 # Removes references that are not handled by associations
696 # Removes references that are not handled by associations
685 # Things that are not deleted are reassociated with the anonymous user
697 # Things that are not deleted are reassociated with the anonymous user
686 def remove_references_before_destroy
698 def remove_references_before_destroy
@@ -403,6 +403,42 class UserTest < ActiveSupport::TestCase
403 end
403 end
404 end
404 end
405
405
406 def test_password_change_should_destroy_tokens
407 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
408 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
409
410 user = User.find(2)
411 user.password, user.password_confirmation = "a new password", "a new password"
412 assert user.save
413
414 assert_nil Token.find_by_id(recovery_token.id)
415 assert_nil Token.find_by_id(autologin_token.id)
416 end
417
418 def test_mail_change_should_destroy_tokens
419 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
420 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
421
422 user = User.find(2)
423 user.mail = "user@somwehere.com"
424 assert user.save
425
426 assert_nil Token.find_by_id(recovery_token.id)
427 assert_equal autologin_token, Token.find_by_id(autologin_token.id)
428 end
429
430 def test_change_on_other_fields_should_not_destroy_tokens
431 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
432 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
433
434 user = User.find(2)
435 user.firstname = "Bobby"
436 assert user.save
437
438 assert_equal recovery_token, Token.find_by_id(recovery_token.id)
439 assert_equal autologin_token, Token.find_by_id(autologin_token.id)
440 end
441
406 def test_validate_login_presence
442 def test_validate_login_presence
407 @admin.login = ""
443 @admin.login = ""
408 assert !@admin.save
444 assert !@admin.save
General Comments 0
You need to be logged in to leave comments. Login now