2018-12-05 23:21:45 +05:30
# frozen_string_literal: true
2016-06-02 11:05:42 +05:30
class JwtController < ApplicationController
2019-12-04 20:38:33 +05:30
skip_around_action :set_session_storage
2016-06-02 11:05:42 +05:30
skip_before_action :authenticate_user!
skip_before_action :verify_authenticity_token
2020-05-24 23:13:21 +05:30
# Add this before other actions, since we want to have the user or project
prepend_before_action :auth_user , :authenticate_project_or_user
2016-06-02 11:05:42 +05:30
2021-01-03 14:25:43 +05:30
feature_category :authentication_and_authorization
2022-06-21 17:19:12 +05:30
# https://gitlab.com/gitlab-org/gitlab/-/issues/357037
urgency :low
2021-01-03 14:25:43 +05:30
2016-06-02 11:05:42 +05:30
SERVICES = {
2021-02-22 17:27:13 +05:30
:: Auth :: ContainerRegistryAuthenticationService :: AUDIENCE = > :: Auth :: ContainerRegistryAuthenticationService ,
:: Auth :: DependencyProxyAuthenticationService :: AUDIENCE = > :: Auth :: DependencyProxyAuthenticationService
2017-08-17 22:00:37 +05:30
} . freeze
2016-06-02 11:05:42 +05:30
def auth
service = SERVICES [ params [ :service ] ]
return head :not_found unless service
2021-10-27 15:23:28 +05:30
result = service . new ( @authentication_result . project , auth_user , auth_params )
2017-09-10 17:25:29 +05:30
. execute ( authentication_abilities : @authentication_result . authentication_abilities )
2016-06-02 11:05:42 +05:30
render json : result , status : result [ :http_status ]
end
private
def authenticate_project_or_user
2019-07-31 22:56:46 +05:30
@authentication_result = Gitlab :: Auth :: Result . new ( nil , nil , :none , Gitlab :: Auth . read_only_authentication_abilities )
2016-06-02 11:05:42 +05:30
2016-09-29 09:46:39 +05:30
authenticate_with_http_basic do | login , password |
@authentication_result = Gitlab :: Auth . find_for_git_client ( login , password , project : nil , ip : request . ip )
2016-06-02 11:05:42 +05:30
2018-05-09 12:01:36 +05:30
if @authentication_result . failed?
2022-09-01 20:07:04 +05:30
log_authentication_failed ( login , @authentication_result )
render_access_denied
2017-09-10 17:25:29 +05:30
end
2016-06-02 11:05:42 +05:30
end
2018-03-17 18:26:18 +05:30
rescue Gitlab :: Auth :: MissingPersonalAccessTokenError
2022-09-01 20:07:04 +05:30
render_access_denied
2016-06-02 11:05:42 +05:30
end
2022-09-01 20:07:04 +05:30
def log_authentication_failed ( login , result )
log_info = {
message : 'JWT authentication failed' ,
http_user : login ,
remote_ip : request . ip ,
auth_service : params [ :service ] ,
'auth_result.type' : result . type ,
'auth_result.actor_type' : result . actor & . class
} . merge ( :: Gitlab :: ApplicationContext . current )
Gitlab :: AuthLogger . warn ( log_info )
2016-10-01 15:18:49 +05:30
end
2022-09-01 20:07:04 +05:30
def render_access_denied
help_page = help_page_url (
'user/profile/account/two_factor_authentication' ,
anchor : 'troubleshooting'
)
render (
json : { errors : [ {
code : 'UNAUTHORIZED' ,
message : format ( _ ( " HTTP Basic: Access denied. The provided password or token is incorrect or your account has 2FA enabled and you must use a personal access token instead of a password. See %{help_page_url} " ) , help_page_url : help_page )
} ] } ,
status : :unauthorized
)
2016-06-02 11:05:42 +05:30
end
2016-09-29 09:46:39 +05:30
def auth_params
2018-11-18 11:00:15 +05:30
params . permit ( :service , :account , :client_id )
. merge ( additional_params )
end
def additional_params
2022-10-11 01:57:18 +05:30
{
scopes : scopes_param ,
deploy_token : @authentication_result . deploy_token ,
auth_type : @authentication_result . type
} . compact
2018-11-18 11:00:15 +05:30
end
# We have to parse scope here, because Docker Client does not send an array of scopes,
# but rather a flat list and we loose second scope when being processed by Rails:
# scope=scopeA&scope=scopeB
#
# This method makes to always return an array of scopes
def scopes_param
return unless params [ :scope ] . present?
Array ( Rack :: Utils . parse_query ( request . query_string ) [ 'scope' ] )
2016-06-02 11:05:42 +05:30
end
2020-05-24 23:13:21 +05:30
def auth_user
strong_memoize ( :auth_user ) do
2021-10-27 15:23:28 +05:30
@authentication_result . auth_user
2020-05-24 23:13:21 +05:30
end
end
2016-06-02 11:05:42 +05:30
end