SECURITY: don't grant same privileges to user_api and api access

User API is no longer gets bypasses that standard API gets.
Only bypasses are CSRF and XHR requirements.
This commit is contained in:
Sam 2016-12-16 12:05:20 +11:00
parent 197517d55e
commit 6ff309aa80
6 changed files with 24 additions and 6 deletions

View File

@ -25,7 +25,7 @@ class ApplicationController < ActionController::Base
# and then raising a CSRF exception
def handle_unverified_request
# NOTE: API key is secret, having it invalidates the need for a CSRF token
unless is_api?
unless is_api? || is_user_api?
super
clear_current_user
render text: "['BAD CSRF']", status: 403
@ -501,7 +501,7 @@ class ApplicationController < ActionController::Base
def check_xhr
# bypass xhr check on PUT / POST / DELETE provided api key is there, otherwise calling api is annoying
return if !request.get? && is_api?
return if !request.get? && (is_api? || is_user_api?)
raise RenderEmpty.new unless ((request.format && request.format.json?) || request.xhr?)
end

View File

@ -467,7 +467,7 @@ class PostsController < ApplicationController
json_obj = json_obj[:post]
end
if !success && GlobalSetting.try(:verbose_api_logging) && is_api?
if !success && GlobalSetting.try(:verbose_api_logging) && (is_api? || is_user_api?)
Rails.logger.error "Error creating post via API:\n\n#{json_obj.inspect}"
end

View File

@ -25,6 +25,10 @@ class Auth::CurrentUserProvider
raise NotImplementedError
end
def is_user_api?
raise NotImplementedError
end
# we may need to know very early on in the middleware if an auth token
# exists, to optimise caching
def has_auth_cookie?

View File

@ -8,6 +8,7 @@ class Auth::DefaultCurrentUserProvider
USER_API_KEY ||= "HTTP_USER_API_KEY".freeze
USER_API_CLIENT_ID ||= "HTTP_USER_API_CLIENT_ID".freeze
API_KEY_ENV ||= "_DISCOURSE_API".freeze
USER_API_KEY_ENV ||= "_DISCOURSE_USER_API".freeze
TOKEN_COOKIE ||= "_t".freeze
PATH_INFO ||= "PATH_INFO".freeze
COOKIE_ATTEMPTS_PER_MIN ||= 10
@ -97,7 +98,7 @@ class Auth::DefaultCurrentUserProvider
limiter_min.performed!
limiter_day.performed!
@env[API_KEY_ENV] = true
@env[USER_API_KEY_ENV] = true
end
@env[CURRENT_USER_KEY] = current_user
@ -172,7 +173,12 @@ class Auth::DefaultCurrentUserProvider
# api has special rights return true if api was detected
def is_api?
current_user
@env[API_KEY_ENV]
!!(@env[API_KEY_ENV])
end
def is_user_api?
current_user
!!(@env[USER_API_KEY_ENV])
end
def has_auth_cookie?

View File

@ -26,6 +26,10 @@ module CurrentUser
current_user_provider.is_api?
end
def is_user_api?
current_user_provider.is_user_api?
end
def current_user
current_user_provider.current_user
end

View File

@ -175,7 +175,11 @@ describe Auth::DefaultCurrentUserProvider do
"HTTP_USER_API_KEY" => api_key.key,
}
expect(provider("/", params).current_user.id).to eq(user.id)
good_provider = provider("/", params)
expect(good_provider.current_user.id).to eq(user.id)
expect(good_provider.is_api?).to eq(false)
expect(good_provider.is_user_api?).to eq(true)
expect {
provider("/", params.merge({"REQUEST_METHOD" => "POST"})).current_user