From 13e2c7492940ace16f359a7b53b9928c37119edb Mon Sep 17 00:00:00 2001 From: Donal McBreen Date: Wed, 1 Apr 2026 08:35:30 +0100 Subject: [PATCH 1/2] Restrict bearer token authentication to JSON requests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bearer tokens are for API/SDK/CLI access — they should only authenticate JSON requests. --- app/controllers/concerns/authentication.rb | 2 +- test/controllers/users_controller_test.rb | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/app/controllers/concerns/authentication.rb b/app/controllers/concerns/authentication.rb index 05efbf4fc..760ee81cb 100644 --- a/app/controllers/concerns/authentication.rb +++ b/app/controllers/concerns/authentication.rb @@ -56,7 +56,7 @@ module Authentication end def authenticate_by_bearer_token - if request.authorization.to_s.include?("Bearer") + if request.authorization.to_s.include?("Bearer") && request.format.json? authenticate_or_request_with_http_token do |token| if identity = Identity.find_by_permissable_access_token(token, method: request.method) Current.identity = identity diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb index 094a2310c..1e49f0d9c 100644 --- a/test/controllers/users_controller_test.rb +++ b/test/controllers/users_controller_test.rb @@ -145,6 +145,26 @@ class UsersControllerTest < ActionDispatch::IntegrationTest assert_response :no_content end + test "bearer token does not authenticate HTML requests" do + sign_in_as :jason + sign_out + + bearer = { "HTTP_AUTHORIZATION" => "Bearer #{identity_access_tokens(:jasons_api_token).token}" } + get user_path(users(:jason)), env: bearer + + assert_response :redirect + end + + test "bearer token authenticates JSON requests" do + sign_in_as :jason + sign_out + + bearer = { "HTTP_AUTHORIZATION" => "Bearer #{identity_access_tokens(:jasons_api_token).token}" } + get user_path(users(:jason)), env: bearer, as: :json + + assert_response :success + end + test "index avoids N+1 queries on identity" do sign_in_as :kevin From b4c4a32205417397778e30284d28e5b9934ee675 Mon Sep 17 00:00:00 2001 From: Donal McBreen Date: Wed, 1 Apr 2026 09:09:00 +0100 Subject: [PATCH 2/2] Return 401 for bearer tokens on non-JSON requests Rather than silently ignoring bearer tokens on HTML requests (which breaks the audit console's error handling), explicitly reject them with 401. Bearer tokens on JSON requests continue to authenticate normally. --- app/controllers/concerns/authentication.rb | 12 ++++++++---- test/controllers/users_controller_test.rb | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/app/controllers/concerns/authentication.rb b/app/controllers/concerns/authentication.rb index 760ee81cb..a269fc2d6 100644 --- a/app/controllers/concerns/authentication.rb +++ b/app/controllers/concerns/authentication.rb @@ -56,11 +56,15 @@ module Authentication end def authenticate_by_bearer_token - if request.authorization.to_s.include?("Bearer") && request.format.json? - authenticate_or_request_with_http_token do |token| - if identity = Identity.find_by_permissable_access_token(token, method: request.method) - Current.identity = identity + if request.authorization.to_s.include?("Bearer") + if request.format.json? + authenticate_or_request_with_http_token do |token| + if identity = Identity.find_by_permissable_access_token(token, method: request.method) + Current.identity = identity + end end + else + request_http_token_authentication end end end diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb index 1e49f0d9c..7fd9fd28d 100644 --- a/test/controllers/users_controller_test.rb +++ b/test/controllers/users_controller_test.rb @@ -152,7 +152,7 @@ class UsersControllerTest < ActionDispatch::IntegrationTest bearer = { "HTTP_AUTHORIZATION" => "Bearer #{identity_access_tokens(:jasons_api_token).token}" } get user_path(users(:jason)), env: bearer - assert_response :redirect + assert_response :unauthorized end test "bearer token authenticates JSON requests" do