]> cat aescling's git repositories - mastodon.git/commitdiff
Fix password change/reset not immediately invalidating other sessions (#12928)
authorEugen Rochko <eugen@zeonfederated.com>
Thu, 23 Jan 2020 23:20:38 +0000 (00:20 +0100)
committerGitHub <noreply@github.com>
Thu, 23 Jan 2020 23:20:38 +0000 (00:20 +0100)
While making browser requests in the other sessions after a password
change or reset does not allow you to be logged in and correctly
invalidates the session making the request, sessions have API tokens
associated with them, which can still be used until that session
is invalidated.

This is a security issue for accounts that were already compromised
some other way because it makes it harder to throw out the hijacker.

app/controllers/auth/passwords_controller.rb
app/controllers/auth/registrations_controller.rb
app/models/user.rb

index 34b98da53bfc1cb52120009d1f39d403cba6f3e9..b98bcecd0d05b3c8aec46a5a86e2b4a2c0ded4ba 100644 (file)
@@ -6,6 +6,12 @@ class Auth::PasswordsController < Devise::PasswordsController
 
   layout 'auth'
 
+  def update
+    super do |resource|
+      resource.session_activations.destroy_all if resource.errors.empty?
+    end
+  end
+
   private
 
   def check_validity_of_reset_password_token
index 212519c8b8055f023d83fdccc43fb0fa83740528..745b91d461ae335ce0ce2a98b3f2763a78836c42 100644 (file)
@@ -22,10 +22,17 @@ class Auth::RegistrationsController < Devise::RegistrationsController
     not_found
   end
 
+  def update
+    super do |resource|
+      resource.clear_other_sessions(current_session.session_id) if resource.saved_change_to_encrypted_password?
+    end
+  end
+
   protected
 
   def update_resource(resource, params)
     params[:password] = nil if Devise.pam_authentication && resource.encrypted_password.blank?
+
     super
   end
 
index a43e63b2e3fdd183c5de0ac3f7b266e9a5563908..058a8d5f87f9d77b0d31fac7e03b8e69f50b5f17 100644 (file)
@@ -247,7 +247,7 @@ class User < ApplicationRecord
                                  ip: request.remote_ip).session_id
   end
 
-  def exclusive_session(id)
+  def clear_other_sessions(id)
     session_activations.exclusive(id)
   end