Commit cb5a5eb8 authored by Robin Bobbitt's avatar Robin Bobbitt
Browse files

Instruct user to use a personal access token for Git over HTTP

If internal auth is disabled and LDAP is not configured on the instance,
present the user with a message to create a personal access token if his
Git over HTTP auth attempt fails.
parent da56991637d2
......@@ -39,7 +39,7 @@ def render_missing_personal_token
errors: [
{ code: 'UNAUTHORIZED',
message: "HTTP Basic: Access denied\n" \
"You have 2FA enabled, please use a personal access token for Git over HTTP.\n" \
"You must use a personal access token with 'api' scope for Git over HTTP.\n" \
"You can generate one at #{profile_personal_access_tokens_url}" }
]
}, status: 401
......
......@@ -104,7 +104,7 @@ def project_id_with_suffix
def render_missing_personal_token
render plain: "HTTP Basic: Access denied\n" \
"You have 2FA enabled, please use a personal access token for Git over HTTP.\n" \
"You must use a personal access token with 'api' scope for Git over HTTP.\n" \
"You can generate one at #{profile_personal_access_tokens_url}",
status: 401
end
......
---
title: Instruct user to use personal access token for Git over HTTP
merge_request: 11986
author: Robin Bobbitt
......@@ -37,7 +37,11 @@ def find_for_git_client(login, password, project:, ip:)
rate_limit!(ip, success: result.success?, login: login)
Gitlab::Auth::UniqueIpsLimiter.limit_user!(result.actor)
result
return result if result.success? || current_application_settings.signin_enabled? || Gitlab::LDAP::Config.enabled?
# If sign-in is disabled and LDAP is not configured, recommend a
# personal access token on failed auth attempts
raise Gitlab::Auth::MissingPersonalTokenError
end
def find_with_user_password(login, password)
......
......@@ -204,6 +204,12 @@ def operation
expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: login)
expect(gl_auth.find_for_git_client(login, 'bar', project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new)
end
it 'throws an error suggesting user create a PAT when internal auth is disabled' do
allow_any_instance_of(ApplicationSetting).to receive(:signin_enabled?) { false }
expect { gl_auth.find_for_git_client('foo', 'bar', project: nil, ip: 'ip') }.to raise_error(Gitlab::Auth::MissingPersonalTokenError)
end
end
describe 'find_with_user_password' do
......
......@@ -418,17 +418,17 @@
end
context 'when username and password are provided' do
it 'rejects pulls with 2FA error message' do
it 'rejects pulls with personal access token error message' do
download(path, user: user.username, password: user.password) do |response|
expect(response).to have_http_status(:unauthorized)
expect(response.body).to include('You have 2FA enabled, please use a personal access token for Git over HTTP')
expect(response.body).to include('You must use a personal access token with \'api\' scope for Git over HTTP')
end
end
it 'rejects the push attempt' do
it 'rejects the push attempt with personal access token error message' do
upload(path, user: user.username, password: user.password) do |response|
expect(response).to have_http_status(:unauthorized)
expect(response.body).to include('You have 2FA enabled, please use a personal access token for Git over HTTP')
expect(response.body).to include('You must use a personal access token with \'api\' scope for Git over HTTP')
end
end
end
......@@ -441,6 +441,41 @@
end
end
context 'when internal auth is disabled' do
before do
allow_any_instance_of(ApplicationSetting).to receive(:signin_enabled?) { false }
end
it 'rejects pulls with personal access token error message' do
download(path, user: 'foo', password: 'bar') do |response|
expect(response).to have_http_status(:unauthorized)
expect(response.body).to include('You must use a personal access token with \'api\' scope for Git over HTTP')
end
end
it 'rejects pushes with personal access token error message' do
upload(path, user: 'foo', password: 'bar') do |response|
expect(response).to have_http_status(:unauthorized)
expect(response.body).to include('You must use a personal access token with \'api\' scope for Git over HTTP')
end
end
context 'when LDAP is configured' do
before do
allow(Gitlab::LDAP::Config).to receive(:enabled?).and_return(true)
allow_any_instance_of(Gitlab::LDAP::Authentication).
to receive(:login).and_return(nil)
end
it 'does not display the personal access token error message' do
upload(path, user: 'foo', password: 'bar') do |response|
expect(response).to have_http_status(:unauthorized)
expect(response.body).not_to include('You must use a personal access token with \'api\' scope for Git over HTTP')
end
end
end
end
context "when blank password attempts follow a valid login" do
def attempt_login(include_password)
password = include_password ? user.password : ""
......
......@@ -70,7 +70,7 @@
context 'without personal token' do
it 'rejects the authorization attempt' do
expect(response).to have_http_status(401)
expect(response.body).to include('You have 2FA enabled, please use a personal access token for Git over HTTP')
expect(response.body).to include('You must use a personal access token with \'api\' scope for Git over HTTP')
end
end
......@@ -88,9 +88,24 @@
context 'using invalid login' do
let(:headers) { { authorization: credentials('invalid', 'password') } }
subject! { get '/jwt/auth', parameters, headers }
context 'when internal auth is enabled' do
it 'rejects the authorization attempt' do
get '/jwt/auth', parameters, headers
expect(response).to have_http_status(401)
expect(response.body).not_to include('You must use a personal access token with \'api\' scope for Git over HTTP')
end
end
it { expect(response).to have_http_status(401) }
context 'when internal auth is disabled' do
it 'rejects the authorization attempt with personal access token message' do
allow_any_instance_of(ApplicationSetting).to receive(:signin_enabled?) { false }
get '/jwt/auth', parameters, headers
expect(response).to have_http_status(401)
expect(response.body).to include('You must use a personal access token with \'api\' scope for Git over HTTP')
end
end
end
end
......
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