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'
JOB_TOKEN_PARAM =
:job_token
DEPLOY_TOKEN_HEADER =
'HTTP_DEPLOY_TOKEN'
RUNNER_TOKEN_PARAM =
:token
RUNNER_JOB_TOKEN_PARAM =
:token
PATH_DEPENDENT_FEED_TOKEN_REGEX =
/\A#{User::FEED_TOKEN_PREFIX}(\h{64})-(\d+)\z/

Instance Method Summary collapse

Instance Method Details

#cluster_agent_token_from_authorization_tokenObject



166
167
168
169
170
171
172
173
# File 'lib/gitlab/auth/auth_finders.rb', line 166

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.active.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



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

def deploy_token_from_request
  return unless route_authentication_setting[:deploy_token_allowed]
  return unless Gitlab::ExternalAuthorization.allow_deploy_tokens_and_deploy_keys?

  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



175
176
177
178
179
180
181
182
# File 'lib/gitlab/auth/auth_finders.rb', line 175

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



136
137
138
139
140
141
142
143
144
# File 'lib/gitlab/auth/auth_finders.rb', line 136

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



81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/gitlab/auth/auth_finders.rb', line 81

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)
  @current_authenticated_job = job # rubocop:disable Gitlab/ModuleWithInstanceVariables

  job.user
end

#find_user_from_basic_auth_passwordObject



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

def find_user_from_basic_auth_password
  return unless has_basic_credentials?(current_request)

  , password = user_name_and_password(current_request)
  return if ::Gitlab::Auth::CI_JOB_USER == 

  Gitlab::Auth.find_with_user_password(, password)
end

#find_user_from_bearer_tokenObject



61
62
63
64
# File 'lib/gitlab/auth/auth_finders.rb', line 61

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



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

def find_user_from_feed_token(request_format)
  return unless valid_rss_format?(request_format)
  return if Gitlab::CurrentSettings.disable_feed_token

  # 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

  find_feed_token_user(token) || raise(UnauthorizedError)
end

#find_user_from_job_tokenObject



66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/gitlab/auth/auth_finders.rb', line 66

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_lfs_tokenObject



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

def find_user_from_lfs_token
  return unless has_basic_credentials?(current_request)

  , token = user_name_and_password(current_request)
  user = User.()

  user if user && Gitlab::LfsToken.new(user).token_valid?(token)
end

#find_user_from_personal_access_tokenObject



112
113
114
115
116
117
118
# File 'lib/gitlab/auth/auth_finders.rb', line 112

def find_user_from_personal_access_token
  return unless access_token

  validate_access_token!

  access_token&.user || raise(UnauthorizedError)
end

#find_user_from_static_object_token(request_format) ⇒ Object



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

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



36
37
38
# File 'lib/gitlab/auth/auth_finders.rb', line 36

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

#find_user_from_web_access_token(request_format, scopes: [:api]) ⇒ Object

We 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. And to allow accessing /archive programatically as it was a big pain point for users gitlab.com/gitlab-org/gitlab/-/issues/28978. Used for release downloading as well



126
127
128
129
130
131
132
133
134
# File 'lib/gitlab/auth/auth_finders.rb', line 126

def find_user_from_web_access_token(request_format, scopes: [:api])
  return unless access_token && valid_web_access_format?(request_format)

  validate_access_token!(scopes: scopes)

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

  access_token.user || raise(UnauthorizedError)
end

#validate_access_token!(scopes: []) ⇒ Object



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/gitlab/auth/auth_finders.rb', line 184

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, scopes
  when AccessTokenValidationService::EXPIRED
    raise ExpiredError
  when AccessTokenValidationService::REVOKED
    revoke_token_family(access_token)

    raise RevokedError
  when AccessTokenValidationService::IMPERSONATION_DISABLED
    raise ImpersonationDisabled
  end
end