summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Bobbitt <ryehle@us.ibm.com>2017-06-07 15:49:45 -0400
committerRobin Bobbitt <ryehle@us.ibm.com>2017-06-07 21:12:51 -0400
commitcb5a5eb89265f7261ecc97b6de5bd26ca092960c (patch)
tree311b3d74e10c8da8cf9c89b5c6684071d932750f
parent359a8f1fc8df543e648b734acd332374bd779347 (diff)
downloadgitlab-ce-cb5a5eb89265f7261ecc97b6de5bd26ca092960c.tar.gz
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.
-rw-r--r--app/controllers/jwt_controller.rb2
-rw-r--r--app/controllers/projects/git_http_client_controller.rb2
-rw-r--r--changelogs/unreleased/pat-msg-on-auth-failure.yml4
-rw-r--r--lib/gitlab/auth.rb6
-rw-r--r--spec/lib/gitlab/auth_spec.rb6
-rw-r--r--spec/requests/git_http_spec.rb43
-rw-r--r--spec/requests/jwt_controller_spec.rb21
7 files changed, 74 insertions, 10 deletions
diff --git a/app/controllers/jwt_controller.rb b/app/controllers/jwt_controller.rb
index c585d26df77..11db164b3fa 100644
--- a/app/controllers/jwt_controller.rb
+++ b/app/controllers/jwt_controller.rb
@@ -39,7 +39,7 @@ class JwtController < ApplicationController
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
diff --git a/app/controllers/projects/git_http_client_controller.rb b/app/controllers/projects/git_http_client_controller.rb
index 7f3205a8001..928f17e6a8e 100644
--- a/app/controllers/projects/git_http_client_controller.rb
+++ b/app/controllers/projects/git_http_client_controller.rb
@@ -104,7 +104,7 @@ class Projects::GitHttpClientController < Projects::ApplicationController
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
diff --git a/changelogs/unreleased/pat-msg-on-auth-failure.yml b/changelogs/unreleased/pat-msg-on-auth-failure.yml
new file mode 100644
index 00000000000..c1b1528bb7a
--- /dev/null
+++ b/changelogs/unreleased/pat-msg-on-auth-failure.yml
@@ -0,0 +1,4 @@
+---
+title: Instruct user to use personal access token for Git over HTTP
+merge_request: 11986
+author: Robin Bobbitt
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index da07ba2f2a3..3933c3b04dd 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -37,7 +37,11 @@ module Gitlab
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)
diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb
index d6006eab0c9..d09da951869 100644
--- a/spec/lib/gitlab/auth_spec.rb
+++ b/spec/lib/gitlab/auth_spec.rb
@@ -204,6 +204,12 @@ describe Gitlab::Auth, lib: true do
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
diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb
index f018b48ceb2..ae2ec39f402 100644
--- a/spec/requests/git_http_spec.rb
+++ b/spec/requests/git_http_spec.rb
@@ -418,17 +418,17 @@ describe 'Git HTTP requests', lib: true do
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 @@ describe 'Git HTTP requests', lib: true do
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 : ""
diff --git a/spec/requests/jwt_controller_spec.rb b/spec/requests/jwt_controller_spec.rb
index e056353fa6f..54d7cf5f10d 100644
--- a/spec/requests/jwt_controller_spec.rb
+++ b/spec/requests/jwt_controller_spec.rb
@@ -70,7 +70,7 @@ describe JwtController do
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 @@ describe JwtController do
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