Module: Gitlab::Auth::AuthFinders

Includes:
ActionController::HttpAuthentication::Basic, ActionController::HttpAuthentication::Token, Utils::StrongMemoize
Included in:
API::APIGuard::HelperMethods, RequestAuthenticator
Defined in:
lib/gitlab/auth/auth_finders.rb

Constant Summary collapse

PRIVATE_TOKEN_HEADER =
'HTTP_PRIVATE_TOKEN'
PRIVATE_TOKEN_PARAM =
:private_token
JOB_TOKEN_HEADER =
'HTTP_JOB_TOKEN'.freeze
JOB_TOKEN_PARAM =
:job_token
DEPLOY_TOKEN_HEADER =
'HTTP_DEPLOY_TOKEN'.freeze
RUNNER_TOKEN_PARAM =
:token
RUNNER_JOB_TOKEN_PARAM =
:token

Instance Method Summary collapse

Methods included from Utils::StrongMemoize

#clear_memoization, #strong_memoize, #strong_memoized?

Instance Method Details

#cluster_agent_token_from_authorization_tokenObject


131
132
133
134
135
136
137
138
# File 'lib/gitlab/auth/auth_finders.rb', line 131

def cluster_agent_token_from_authorization_token
  return unless route_authentication_setting[:cluster_agent_token_allowed]
  return unless current_request.authorization.present?

  authorization_token, _options = token_and_options(current_request)

  ::Clusters::AgentToken.find_by_token(authorization_token)
end

#deploy_token_from_requestObject

This returns a deploy token, not a user since a deploy token does not belong to a user.

deploy tokens are accepted with deploy token headers and basic auth headers


116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/gitlab/auth/auth_finders.rb', line 116

def deploy_token_from_request
  return unless route_authentication_setting[:deploy_token_allowed]

  token = current_request.env[DEPLOY_TOKEN_HEADER].presence || parsed_oauth_token

  if has_basic_credentials?(current_request)
    _, token = user_name_and_password(current_request)
  end

  deploy_token = DeployToken.active.find_by_token(token)
  @current_authenticated_deploy_token = deploy_token # rubocop:disable Gitlab/ModuleWithInstanceVariables

  deploy_token
end

#find_runner_from_tokenObject


140
141
142
143
144
145
146
147
# File 'lib/gitlab/auth/auth_finders.rb', line 140

def find_runner_from_token
  return unless api_request?

  token = current_request.params[RUNNER_TOKEN_PARAM].presence
  return unless token

  ::Ci::Runner.find_by_token(token) || raise(UnauthorizedError)
end

#find_user_from_access_tokenObject


102
103
104
105
106
107
108
109
110
# File 'lib/gitlab/auth/auth_finders.rb', line 102

def find_user_from_access_token
  return unless access_token

  validate_access_token!

  ::PersonalAccessTokens::LastUsedService.new(access_token).execute

  access_token.user || raise(UnauthorizedError)
end

#find_user_from_basic_auth_jobObject


78
79
80
81
82
83
84
85
86
87
# File 'lib/gitlab/auth/auth_finders.rb', line 78

def find_user_from_basic_auth_job
  return unless has_basic_credentials?(current_request)

  , password = user_name_and_password(current_request)
  return unless .present? && password.present?
  return unless ::Gitlab::Auth::CI_JOB_USER == 

  job = find_valid_running_job_by_token!(password)
  job.user
end

#find_user_from_bearer_tokenObject


58
59
60
61
# File 'lib/gitlab/auth/auth_finders.rb', line 58

def find_user_from_bearer_token
  find_user_from_job_bearer_token ||
    find_user_from_access_token
end

#find_user_from_feed_token(request_format) ⇒ Object


47
48
49
50
51
52
53
54
55
56
# File 'lib/gitlab/auth/auth_finders.rb', line 47

def find_user_from_feed_token(request_format)
  return unless valid_rss_format?(request_format)

  # NOTE: feed_token was renamed from rss_token but both needs to be supported because
  #       users might have already added the feed to their RSS reader before the rename
  token = current_request.params[:feed_token].presence || current_request.params[:rss_token].presence
  return unless token

  User.find_by_feed_token(token) || raise(UnauthorizedError)
end

#find_user_from_job_tokenObject


63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/gitlab/auth/auth_finders.rb', line 63

def find_user_from_job_token
  return unless route_authentication_setting[:job_token_allowed]
  return find_user_from_basic_auth_job if route_authentication_setting[:job_token_allowed] == :basic_auth

  token = current_request.params[JOB_TOKEN_PARAM].presence ||
    current_request.params[RUNNER_JOB_TOKEN_PARAM].presence ||
    current_request.env[JOB_TOKEN_HEADER].presence
  return unless token

  job = find_valid_running_job_by_token!(token)
  @current_authenticated_job = job # rubocop:disable Gitlab/ModuleWithInstanceVariables

  job.user
end

#find_user_from_static_object_token(request_format) ⇒ Object


38
39
40
41
42
43
44
45
# File 'lib/gitlab/auth/auth_finders.rb', line 38

def find_user_from_static_object_token(request_format)
  return unless valid_static_objects_format?(request_format)

  token = current_request.params[:token].presence || current_request.headers['X-Gitlab-Static-Object-Token'].presence
  return unless token

  User.find_by_static_object_token(token) || raise(UnauthorizedError)
end

#find_user_from_wardenObject

Check the Rails session for valid authentication details


34
35
36
# File 'lib/gitlab/auth/auth_finders.rb', line 34

def find_user_from_warden
  current_request.env['warden']&.authenticate if verified_request?
end

#find_user_from_web_access_token(request_format) ⇒ Object

We only allow Private Access Tokens with `api` scope to be used by web requests on RSS feeds or ICS files for backwards compatibility. It is also used by GraphQL/API requests.


92
93
94
95
96
97
98
99
100
# File 'lib/gitlab/auth/auth_finders.rb', line 92

def find_user_from_web_access_token(request_format)
  return unless access_token && valid_web_access_format?(request_format)

  validate_access_token!(scopes: [:api])

  ::PersonalAccessTokens::LastUsedService.new(access_token).execute

  access_token.user || raise(UnauthorizedError)
end

#validate_access_token!(scopes: []) ⇒ Object


149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/gitlab/auth/auth_finders.rb', line 149

def validate_access_token!(scopes: [])
  # return early if we've already authenticated via a job token
  return if @current_authenticated_job.present? # rubocop:disable Gitlab/ModuleWithInstanceVariables

  # return early if we've already authenticated via a deploy token
  return if @current_authenticated_deploy_token.present? # rubocop:disable Gitlab/ModuleWithInstanceVariables

  return unless access_token

  case AccessTokenValidationService.new(access_token, request: request).validate(scopes: scopes)
  when AccessTokenValidationService::INSUFFICIENT_SCOPE
    raise InsufficientScopeError.new(scopes)
  when AccessTokenValidationService::EXPIRED
    raise ExpiredError
  when AccessTokenValidationService::REVOKED
    raise RevokedError
  when AccessTokenValidationService::IMPERSONATION_DISABLED
    raise ImpersonationDisabled
  end
end