From 048cdfbcfa42fa60d8d3eb2c9da64a2f7ff0752b Mon Sep 17 00:00:00 2001 From: Bianca Nenciu Date: Fri, 12 Oct 2018 02:40:48 +0300 Subject: [PATCH] FIX: Do not allow revoking the token of current session. (#6472) * FIX: Do not allow revoking the token of current session. * DEV: Add getter of current auth_token from Guardian. --- app/controllers/users_controller.rb | 5 ++++- app/serializers/user_auth_token_serializer.rb | 4 +--- lib/guardian.rb | 7 +++++++ spec/components/guardian_spec.rb | 10 ++++++++++ spec/requests/users_controller_spec.rb | 18 ++++++------------ 5 files changed, 28 insertions(+), 16 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index c72ae0864c4..1c5ad6a7011 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1119,7 +1119,10 @@ class UsersController < ApplicationController user = fetch_user_from_params guardian.ensure_can_edit!(user) - if !SiteSetting.log_out_strict && params[:token_id] + if params[:token_id] + token = UserAuthToken.find_by(id: params[:token_id], user_id: user.id) + # The user should not be able to revoke the auth token of current session. + raise Discourse::NotFound if guardian.auth_token == token.auth_token UserAuthToken.where(id: params[:token_id], user_id: user.id).each(&:destroy!) else UserAuthToken.where(user_id: user.id).each(&:destroy!) diff --git a/app/serializers/user_auth_token_serializer.rb b/app/serializers/user_auth_token_serializer.rb index d7dd0ad489f..b033ac66a55 100644 --- a/app/serializers/user_auth_token_serializer.rb +++ b/app/serializers/user_auth_token_serializer.rb @@ -9,9 +9,7 @@ class UserAuthTokenSerializer < ApplicationSerializer end def is_active - cookie = scope.request.cookies[Auth::DefaultCurrentUserProvider::TOKEN_COOKIE] - - UserAuthToken.hash_token(cookie) == object.auth_token + scope.auth_token == object.auth_token end def seen_at diff --git a/lib/guardian.rb b/lib/guardian.rb index 2804b23c84e..ca51129055a 100644 --- a/lib/guardian.rb +++ b/lib/guardian.rb @@ -381,6 +381,13 @@ class Guardian (components - Theme.components_for(parent)).empty? end + def auth_token + return nil if !request&.cookies[Auth::DefaultCurrentUserProvider::TOKEN_COOKIE] + + cookie = request.cookies[Auth::DefaultCurrentUserProvider::TOKEN_COOKIE] + UserAuthToken.hash_token(cookie) + end + private def is_my_own?(obj) diff --git a/spec/components/guardian_spec.rb b/spec/components/guardian_spec.rb index cc7c4a2c955..5a05341928c 100644 --- a/spec/components/guardian_spec.rb +++ b/spec/components/guardian_spec.rb @@ -2963,4 +2963,14 @@ describe Guardian do end end end + + describe '#auth_token' do + it 'returns the correct auth token' do + token = UserAuthToken.generate!(user_id: user.id) + env = Rack::MockRequest.env_for("/", "HTTP_COOKIE" => "_t=#{token.unhashed_auth_token};") + + guardian = Guardian.new(user, Rack::Request.new(env)) + expect(guardian.auth_token).to eq(token.auth_token) + end + end end diff --git a/spec/requests/users_controller_spec.rb b/spec/requests/users_controller_spec.rb index f3bb8996b13..210170ad770 100644 --- a/spec/requests/users_controller_spec.rb +++ b/spec/requests/users_controller_spec.rb @@ -3270,9 +3270,6 @@ describe UsersController do end it 'logs user out' do - SiteSetting.log_out_strict = false - expect(user.user_auth_tokens.count).to eq(2) - ids = user.user_auth_tokens.map { |token| token.id } post "/u/#{user.username}/preferences/revoke-auth-token.json", params: { token_id: ids[0] } @@ -3283,20 +3280,17 @@ describe UsersController do expect(user.user_auth_tokens.first.id).to eq(ids[1]) end - it 'logs user out from everywhere if log_out_strict is enabled' do - SiteSetting.log_out_strict = true - expect(user.user_auth_tokens.count).to eq(2) + it 'does not let user log out of current session' do + token = UserAuthToken.generate!(user_id: user.id) + env = Rack::MockRequest.env_for("/", "HTTP_COOKIE" => "_t=#{token.unhashed_auth_token};") + Guardian.any_instance.stubs(:request).returns(Rack::Request.new(env)) - ids = user.user_auth_tokens.map { |token| token.id } - post "/u/#{user.username}/preferences/revoke-auth-token.json", params: { token_id: ids[0] } + post "/u/#{user.username}/preferences/revoke-auth-token.json", params: { token_id: token.id } - expect(response.status).to eq(200) - expect(user.user_auth_tokens.count).to eq(0) + expect(response.status).to eq(404) end it 'logs user out from everywhere if token_id is not present' do - expect(user.user_auth_tokens.count).to eq(2) - post "/u/#{user.username}/preferences/revoke-auth-token.json" expect(response.status).to eq(200)