Commit 3e83cecf authored by Lukas 'Eipi' Eipert's avatar Lukas 'Eipi' Eipert Committed by Sean McGivern

Allow HEAD requests for read_api and read_user scope tokens

> The HEAD method is identical to GET except that the server MUST NOT
> send a message body in the response (i.e., the response terminates at
> the end of the header section)

https://tools.ietf.org/html/rfc7231#section-4.3.2

Judging from that section of the RFC 7231 it should be safe to allow
HEAD requests in the read_api and read_user scopes
parent d2ef64ae
---
title: Allow HEAD requests for read_api and read_user scope tokens
merge_request: 53088
author:
type: fixed
......@@ -30,7 +30,7 @@ module API
]
allow_access_with_scope :api
allow_access_with_scope :read_api, if: -> (request) { request.get? }
allow_access_with_scope :read_api, if: -> (request) { request.get? || request.head? }
prefix :api
version 'v3', using: :path do
......
......@@ -6,7 +6,7 @@ module API
include APIGuard
helpers ::API::Helpers::EventsHelpers
allow_access_with_scope :read_user, if: -> (request) { request.get? }
allow_access_with_scope :read_user, if: -> (request) { request.get? || request.head? }
feature_category :users
......
......@@ -6,7 +6,7 @@ module API
include APIGuard
include Helpers::CustomAttributes
allow_access_with_scope :read_user, if: -> (request) { request.get? }
allow_access_with_scope :read_user, if: -> (request) { request.get? || request.head? }
feature_category :users, ['/users/:id/custom_attributes', '/users/:id/custom_attributes/:key']
......
......@@ -5,7 +5,7 @@ module API
helpers ::API::Helpers::GraphqlHelpers
include APIGuard
allow_access_with_scope :read_user, if: -> (request) { request.get? }
allow_access_with_scope :read_user, if: -> (request) { request.get? || request.head? }
before { authenticate! }
......
......@@ -36,6 +36,12 @@ RSpec.describe API::API do
expect(response).to have_gitlab_http_status(:ok)
end
it 'does authorize user for head request' do
head api('/groups', personal_access_token: token)
expect(response).to have_gitlab_http_status(:ok)
end
it 'does not authorize user for revoked token' do
revoked = create(:personal_access_token, :revoked, user: user, scopes: [:read_api])
......
......@@ -55,6 +55,12 @@ RSpec.describe API::Events do
expect(json_response).to be_an Array
expect(json_response.size).to eq(1)
end
it 'returns "200" response on head request' do
head api('/events?action=closed&target_type=issue&after=2016-12-1&before=2016-12-31', personal_access_token: token)
expect(response).to have_gitlab_http_status(:ok)
end
end
context 'when the requesting token does not have "read_user" or "api" scope' do
......
......@@ -33,6 +33,12 @@ RSpec.describe API::Version do
expect_version
end
it 'returns "200" response on head requests' do
head api('/version', personal_access_token: personal_access_token)
expect(response).to have_gitlab_http_status(:ok)
end
end
context 'with read_user scope' do
......@@ -43,6 +49,12 @@ RSpec.describe API::Version do
expect_version
end
it 'returns "200" response on head requests' do
head api('/version', personal_access_token: personal_access_token)
expect(response).to have_gitlab_http_status(:ok)
end
end
context 'with neither api nor read_user scope' do
......
......@@ -7,21 +7,33 @@ RSpec.shared_examples 'allows the "read_user" scope' do |api_version|
context 'when the requesting token has the "api" scope' do
let(:token) { create(:personal_access_token, scopes: ['api'], user: user) }
it 'returns a "200" response' do
it 'returns a "200" response on get request' do
get api_call.call(path, user, personal_access_token: token, version: version)
expect(response).to have_gitlab_http_status(:ok)
end
it 'returns a "200" response on head request' do
head api_call.call(path, user, personal_access_token: token, version: version)
expect(response).to have_gitlab_http_status(:ok)
end
end
context 'when the requesting token has the "read_user" scope' do
let(:token) { create(:personal_access_token, scopes: ['read_user'], user: user) }
it 'returns a "200" response' do
it 'returns a "200" response on get request' do
get api_call.call(path, user, personal_access_token: token, version: version)
expect(response).to have_gitlab_http_status(:ok)
end
it 'returns a "200" response on head request' do
head api_call.call(path, user, personal_access_token: token, version: version)
expect(response).to have_gitlab_http_status(:ok)
end
end
context 'when the requesting token does not have any required scope' do
......@@ -45,21 +57,33 @@ RSpec.shared_examples 'allows the "read_user" scope' do |api_version|
context 'when the requesting token has the "api" scope' do
let!(:token) { Doorkeeper::AccessToken.create! application_id: application.id, resource_owner_id: user.id, scopes: "api" }
it 'returns a "200" response' do
it 'returns a "200" response on get request' do
get api_call.call(path, user, oauth_access_token: token)
expect(response).to have_gitlab_http_status(:ok)
end
it 'returns a "200" response on head request' do
head api_call.call(path, user, oauth_access_token: token)
expect(response).to have_gitlab_http_status(:ok)
end
end
context 'when the requesting token has the "read_user" scope' do
let!(:token) { Doorkeeper::AccessToken.create! application_id: application.id, resource_owner_id: user.id, scopes: "read_user" }
it 'returns a "200" response' do
it 'returns a "200" response on get request' do
get api_call.call(path, user, oauth_access_token: token)
expect(response).to have_gitlab_http_status(:ok)
end
it 'returns a "200" response on head request' do
head api_call.call(path, user, oauth_access_token: token)
expect(response).to have_gitlab_http_status(:ok)
end
end
context 'when the requesting token does not have any required scope' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment