2021-01-01 10:10:11 -05:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
module API
|
|
|
|
module Helpers
|
|
|
|
module Authentication
|
|
|
|
extend ActiveSupport::Concern
|
|
|
|
|
|
|
|
class_methods do
|
|
|
|
def authenticate_with(&block)
|
|
|
|
strategies = ::Gitlab::APIAuthentication::Builder.new.build(&block)
|
|
|
|
namespace_inheritable :authentication, strategies
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
included do
|
|
|
|
helpers ::Gitlab::Utils::StrongMemoize
|
|
|
|
|
|
|
|
helpers do
|
|
|
|
def token_from_namespace_inheritable
|
|
|
|
strong_memoize(:token_from_namespace_inheritable) do
|
|
|
|
strategies = namespace_inheritable(:authentication)
|
|
|
|
next unless strategies&.any?
|
|
|
|
|
|
|
|
# Extract credentials from the request
|
|
|
|
found = strategies.to_h { |location, _| [location, ::Gitlab::APIAuthentication::TokenLocator.new(location).extract(current_request)] }
|
|
|
|
found.filter! { |location, raw| raw }
|
|
|
|
next unless found.any?
|
|
|
|
|
|
|
|
# Specifying multiple credentials is an error
|
|
|
|
# https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38627#note_475984136
|
|
|
|
bad_request!('Found more than one set of credentials') if found.size > 1
|
|
|
|
|
|
|
|
location, raw = found.first
|
|
|
|
find_token_from_raw_credentials(strategies[location], raw)
|
|
|
|
end
|
|
|
|
|
|
|
|
rescue ::Gitlab::Auth::UnauthorizedError
|
|
|
|
# TODO: this should be rescued and converted by the exception handling middleware
|
|
|
|
# https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38627#note_475174516
|
|
|
|
unauthorized!
|
|
|
|
end
|
|
|
|
|
|
|
|
def access_token_from_namespace_inheritable
|
|
|
|
token = token_from_namespace_inheritable
|
|
|
|
token if token.is_a? PersonalAccessToken
|
|
|
|
end
|
|
|
|
|
|
|
|
def user_from_namespace_inheritable
|
|
|
|
token = token_from_namespace_inheritable
|
|
|
|
return token if token.is_a? DeployToken
|
|
|
|
|
|
|
|
token&.user
|
|
|
|
end
|
|
|
|
|
2021-03-23 08:09:33 -04:00
|
|
|
def ci_build_from_namespace_inheritable
|
|
|
|
token = token_from_namespace_inheritable
|
|
|
|
token if token.is_a?(::Ci::Build)
|
|
|
|
end
|
|
|
|
|
2021-01-01 10:10:11 -05:00
|
|
|
private
|
|
|
|
|
|
|
|
def find_token_from_raw_credentials(token_types, raw)
|
|
|
|
token_types.each do |token_type|
|
|
|
|
# Resolve a token from the raw credentials
|
|
|
|
token = ::Gitlab::APIAuthentication::TokenResolver.new(token_type).resolve(raw)
|
|
|
|
return token if token
|
|
|
|
end
|
|
|
|
|
|
|
|
# If a request provides credentials via an allowed transport, the
|
|
|
|
# credentials must be valid. If we reach this point, the credentials
|
|
|
|
# must not be valid credentials of an allowed type.
|
|
|
|
raise ::Gitlab::Auth::UnauthorizedError
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|