From: Tom Hughes Date: Tue, 29 Sep 2020 13:22:51 +0000 (+0100) Subject: Invalidate existing sessions when changing email or password X-Git-Tag: live~1899 X-Git-Url: https://git.openstreetmap.org/rails.git/commitdiff_plain/7db541d697436a4ff24f6f5a6bb2c0ecc9b8a9e6 Invalidate existing sessions when changing email or password As we don't have any way to actually find the active sessions for an account we instead store a fingerprint in the session, and refuse to use any session with a different fingerprint. --- diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 8adea79a4..052858932 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -23,7 +23,11 @@ class ApplicationController < ActionController::Base if session[:user] self.current_user = User.where(:id => session[:user]).where("status IN ('active', 'confirmed', 'suspended')").first - if current_user.status == "suspended" + if session[:fingerprint] && + session[:fingerprint] != current_user.fingerprint + reset_session + self.current_user = nil + elsif current_user.status == "suspended" session.delete(:user) session_expires_automatically @@ -42,6 +46,8 @@ class ApplicationController < ActionController::Base elsif session[:token] session[:user] = current_user.id if self.current_user = User.authenticate(:token => session[:token]) end + + session[:fingerprint] = current_user.fingerprint if current_user && session[:fingerprint].nil? rescue StandardError => e logger.info("Exception authorizing user: #{e}") reset_session diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index e5a57f47e..1cc27d9d9 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -183,6 +183,7 @@ class UsersController < ApplicationController if current_user.save token.destroy + session[:fingerprint] = current_user.fingerprint flash[:notice] = t "users.reset_password.flash changed" successful_login(current_user) end @@ -323,6 +324,7 @@ class UsersController < ApplicationController token.destroy session[:user] = user.id + session[:fingerprint] = user.fingerprint redirect_to referer || welcome_path end @@ -368,6 +370,7 @@ class UsersController < ApplicationController end current_user.tokens.delete_all session[:user] = current_user.id + session[:fingerprint] = current_user.fingerprint redirect_to :action => "account", :display_name => current_user.display_name elsif token flash[:error] = t "users.confirm_email.failure" @@ -552,6 +555,7 @@ class UsersController < ApplicationController # process a successful login def successful_login(user, referer = nil) session[:user] = user.id + session[:fingerprint] = user.fingerprint session_expires_after 28.days if session[:remember_me] target = referer || session[:referer] || url_for(:controller => :site, :action => :index) @@ -642,6 +646,8 @@ class UsersController < ApplicationController end if user.save + session[:fingerprint] = user.fingerprint + set_locale(true) if user.new_email.blank? || user.new_email == user.email diff --git a/app/models/user.rb b/app/models/user.rb index 65c70d2c7..7e1f1c6d6 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -44,6 +44,7 @@ # class User < ApplicationRecord + require "digest" require "xml/libxml" has_many :traces, -> { where(:visible => true) } @@ -306,6 +307,13 @@ class User < ApplicationRecord ClientApplication.find_by(:key => application_key).access_token_for_user(self) end + def fingerprint + digest = Digest::SHA256.new + digest.update(email) + digest.update(pass_crypt) + digest.hexdigest + end + private def set_defaults