summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Release Tools Bot <robert+release-tools@gitlab.com>2019-08-26 07:42:37 +0000
committerGitLab Release Tools Bot <robert+release-tools@gitlab.com>2019-08-26 07:42:37 +0000
commit298c1357ebb07519eb968d318c375bd81ca69d2f (patch)
tree3a89645be6320296eeb45aaa71a7cc27272c09b8
parentf3853daceca5061e41d0351d0dff2938ba374bfa (diff)
parent0c21854764464bd110b505d689b3fa112936944f (diff)
downloadgitlab-ce-298c1357ebb07519eb968d318c375bd81ca69d2f.tar.gz
Merge branch 'security-sarcila-fix-weak-session-management-12-1' into '12-1-stable'
Clear reset_password_tokens when login (email or username) change See merge request gitlab/gitlabhq!3347
-rw-r--r--app/models/user.rb7
-rw-r--r--changelogs/unreleased/security-sarcila-fix-weak-session-management.yml6
-rw-r--r--spec/features/profiles/user_edit_profile_spec.rb17
-rw-r--r--spec/models/user_spec.rb41
4 files changed, 71 insertions, 0 deletions
diff --git a/app/models/user.rb b/app/models/user.rb
index 0fd3daa3383..58509976135 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -630,6 +630,13 @@ class User < ApplicationRecord
end
end
+ # will_save_change_to_attribute? is used by Devise to check if it is necessary
+ # to clear any existing reset_password_tokens before updating an authentication_key
+ # and login in our case is a virtual attribute to allow login by username or email.
+ def will_save_change_to_login?
+ will_save_change_to_username? || will_save_change_to_email?
+ end
+
def unique_email
if !emails.exists?(email: email) && Email.exists?(email: email)
errors.add(:email, _('has already been taken'))
diff --git a/changelogs/unreleased/security-sarcila-fix-weak-session-management.yml b/changelogs/unreleased/security-sarcila-fix-weak-session-management.yml
new file mode 100644
index 00000000000..a37a3099519
--- /dev/null
+++ b/changelogs/unreleased/security-sarcila-fix-weak-session-management.yml
@@ -0,0 +1,6 @@
+---
+title: Fix weak session management by clearing password reset tokens after login (username/email)
+ are updated
+merge_request:
+author:
+type: security
diff --git a/spec/features/profiles/user_edit_profile_spec.rb b/spec/features/profiles/user_edit_profile_spec.rb
index a53da94ef7d..9ab5026dbc4 100644
--- a/spec/features/profiles/user_edit_profile_spec.rb
+++ b/spec/features/profiles/user_edit_profile_spec.rb
@@ -47,6 +47,23 @@ describe 'User edit profile' do
end
end
+ describe 'when I change my email' do
+ before do
+ user.send_reset_password_instructions
+ end
+
+ it 'clears the reset password token' do
+ expect(user.reset_password_token?).to be true
+
+ fill_in 'user_email', with: 'new-email@example.com'
+ submit_settings
+
+ user.reload
+ expect(user.confirmation_token).not_to be_nil
+ expect(user.reset_password_token?).to be false
+ end
+ end
+
context 'user avatar' do
before do
attach_file(:user_avatar, Rails.root.join('spec', 'fixtures', 'banana_sample.gif'))
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 5cfa64fd764..f4e1fea739b 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -3037,6 +3037,47 @@ describe User do
end
end
+ describe '#will_save_change_to_login?' do
+ let(:user) { create(:user, username: 'old-username', email: 'old-email@example.org') }
+ let(:new_username) { 'new-name' }
+ let(:new_email) { 'new-email@example.org' }
+
+ subject { user.will_save_change_to_login? }
+
+ context 'when the username is changed' do
+ before do
+ user.username = new_username
+ end
+
+ it { is_expected.to be true }
+ end
+
+ context 'when the email is changed' do
+ before do
+ user.email = new_email
+ end
+
+ it { is_expected.to be true }
+ end
+
+ context 'when both email and username are changed' do
+ before do
+ user.username = new_username
+ user.email = new_email
+ end
+
+ it { is_expected.to be true }
+ end
+
+ context 'when email and username aren\'t changed' do
+ before do
+ user.name = 'new_name'
+ end
+
+ it { is_expected.to be_falsy }
+ end
+ end
+
describe '#sync_attribute?' do
let(:user) { described_class.new }