api: disable csrf protection for api requests.

Fixes POST/PUT API requests failing with InvalidAuthenticityToken errors
due to missing CSRF tokens.

CSRF protection is only necessary for cookie-based authentication. For
non-cookie-based authentication we can safely disable it. That is, if
the user is already passing their login + api_key, then we don't need
to additionally verify the request with a CSRF token.

ref: 2e407fa476 (comments)
This commit is contained in:
evazion
2019-08-24 22:55:35 -05:00
parent 9c79f006f8
commit 2d34e69737
3 changed files with 71 additions and 15 deletions

View File

@@ -3,23 +3,23 @@ class SessionLoader
attr_reader :session, :cookies, :request, :params
def initialize(session, cookies, request, params)
@session = session
@cookies = cookies
def initialize(request)
@request = request
@params = params
@session = request.session
@cookies = request.cookie_jar
@params = request.parameters
end
def load
CurrentUser.user = User.anonymous
CurrentUser.ip_addr = request.remote_ip
if session[:user_id]
if has_api_authentication?
load_session_for_api
elsif session[:user_id]
load_session_user
elsif cookie_password_hash_valid?
load_cookie_user
else
load_session_for_api
end
set_statement_timeout
@@ -30,6 +30,10 @@ class SessionLoader
DanbooruLogger.initialize(request, session, CurrentUser.user)
end
def has_api_authentication?
request.authorization.present? || params[:login].present? || params[:api_key].present? || params[:password_hash].present?
end
private
def set_statement_timeout
@@ -40,21 +44,21 @@ private
def load_session_for_api
if request.authorization
authenticate_basic_auth
elsif params[:login].present? && params[:api_key].present?
authenticate_api_key(params[:login], params[:api_key])
elsif params[:login].present? && params[:password_hash].present?
authenticate_legacy_api_key(params[:login], params[:password_hash])
else
raise AuthenticationFailure
end
end
def authenticate_basic_auth
credentials = ::Base64.decode64(request.authorization.split(' ', 2).last || '')
login, api_key = credentials.split(/:/, 2)
authenticate_api_key(login, api_key)
end
def authenticate_api_key(name, api_key)
CurrentUser.user = User.authenticate_api_key(name, api_key)
@@ -62,7 +66,7 @@ private
raise AuthenticationFailure.new
end
end
def authenticate_legacy_api_key(name, password_hash)
CurrentUser.user = User.authenticate_hash(name, password_hash)