2012-05-08 15:01:35 +04:00
|
|
|
Feature: OAuth authentication
|
|
|
|
Background:
|
|
|
|
Given I am in "dotfiles" git repo
|
|
|
|
|
|
|
|
Scenario: Ask for username & password, create authorization
|
|
|
|
Given the GitHub API server:
|
|
|
|
"""
|
2014-12-24 00:58:04 +03:00
|
|
|
require 'socket'
|
|
|
|
require 'etc'
|
|
|
|
machine_id = "#{Etc.getlogin}@#{Socket.gethostname}"
|
|
|
|
|
2012-05-08 15:01:35 +04:00
|
|
|
post('/authorizations') {
|
2014-12-24 00:58:04 +03:00
|
|
|
assert_basic_auth 'mislav', 'kitty'
|
|
|
|
assert :scopes => ['repo'],
|
|
|
|
:note => "hub for #{machine_id}",
|
|
|
|
:note_url => 'http://hub.github.com/'
|
2012-10-10 15:50:23 +04:00
|
|
|
json :token => 'OTOKEN'
|
2012-05-08 15:01:35 +04:00
|
|
|
}
|
2012-11-24 23:22:22 +04:00
|
|
|
get('/user') {
|
|
|
|
halt 401 unless request.env['HTTP_AUTHORIZATION'] == 'token OTOKEN'
|
|
|
|
json :login => 'MiSlAv'
|
|
|
|
}
|
2012-11-22 15:55:28 +04:00
|
|
|
post('/user/repos') {
|
2012-11-24 23:22:22 +04:00
|
|
|
halt 401 unless request.env['HTTP_AUTHORIZATION'] == 'token OTOKEN'
|
2012-11-22 15:55:28 +04:00
|
|
|
json :full_name => 'mislav/dotfiles'
|
|
|
|
}
|
2012-05-08 15:01:35 +04:00
|
|
|
"""
|
|
|
|
When I run `hub create` interactively
|
|
|
|
When I type "mislav"
|
|
|
|
And I type "kitty"
|
|
|
|
Then the output should contain "github.com username:"
|
|
|
|
And the output should contain "github.com password for mislav (never stored):"
|
|
|
|
And the exit status should be 0
|
2014-09-15 05:35:43 +04:00
|
|
|
And the file "../home/.config/hub" should contain "user: MiSlAv"
|
|
|
|
And the file "../home/.config/hub" should contain "oauth_token: OTOKEN"
|
2012-07-19 01:18:08 +04:00
|
|
|
And the file "../home/.config/hub" should have mode "0600"
|
2012-05-08 15:01:35 +04:00
|
|
|
|
2014-12-24 00:58:04 +03:00
|
|
|
Scenario: Rename & retry creating authorization if there's a token name collision
|
2012-05-08 15:01:35 +04:00
|
|
|
Given the GitHub API server:
|
|
|
|
"""
|
2014-12-24 00:58:04 +03:00
|
|
|
require 'socket'
|
|
|
|
require 'etc'
|
|
|
|
machine_id = "#{Etc.getlogin}@#{Socket.gethostname}"
|
2012-05-08 15:01:35 +04:00
|
|
|
|
2014-02-28 19:17:01 +04:00
|
|
|
post('/authorizations') {
|
2014-12-24 00:58:04 +03:00
|
|
|
assert_basic_auth 'mislav', 'kitty'
|
|
|
|
if params[:note] == "hub for #{machine_id} 3"
|
|
|
|
json :token => 'OTOKEN'
|
|
|
|
else
|
|
|
|
status 422
|
|
|
|
json :message => 'Validation Failed',
|
|
|
|
:errors => [{
|
|
|
|
:resource => 'OauthAccess',
|
|
|
|
:code => 'already_exists',
|
|
|
|
:field => 'description'
|
|
|
|
}]
|
|
|
|
end
|
2014-02-28 19:17:01 +04:00
|
|
|
}
|
|
|
|
get('/user') {
|
2014-12-24 00:58:04 +03:00
|
|
|
json :login => 'MiSlAv'
|
2014-02-28 19:17:01 +04:00
|
|
|
}
|
|
|
|
post('/user/repos') {
|
|
|
|
json :full_name => 'mislav/dotfiles'
|
|
|
|
}
|
|
|
|
"""
|
|
|
|
When I run `hub create` interactively
|
|
|
|
When I type "mislav"
|
|
|
|
And I type "kitty"
|
2014-12-24 00:58:04 +03:00
|
|
|
Then the output should contain "github.com username:"
|
2014-02-28 19:17:01 +04:00
|
|
|
And the exit status should be 0
|
2014-09-15 05:35:43 +04:00
|
|
|
And the file "../home/.config/hub" should contain "oauth_token: OTOKEN"
|
2014-02-28 19:17:01 +04:00
|
|
|
|
2014-12-24 00:58:04 +03:00
|
|
|
Scenario: Avoid getting caught up in infinite recursion while retrying token names
|
2014-05-15 22:10:44 +04:00
|
|
|
Given the GitHub API server:
|
|
|
|
"""
|
2014-12-24 00:58:04 +03:00
|
|
|
tries = 0
|
2014-05-15 22:10:44 +04:00
|
|
|
post('/authorizations') {
|
2014-12-24 00:58:04 +03:00
|
|
|
tries += 1
|
|
|
|
halt 400, json(:message => "too many tries") if tries >= 10
|
2014-05-15 22:10:44 +04:00
|
|
|
status 422
|
2014-12-24 00:58:04 +03:00
|
|
|
json :message => 'Validation Failed',
|
|
|
|
:errors => [{
|
|
|
|
:resource => 'OauthAccess',
|
|
|
|
:code => 'already_exists',
|
|
|
|
:field => 'description'
|
|
|
|
}]
|
2014-02-28 19:17:01 +04:00
|
|
|
}
|
|
|
|
"""
|
|
|
|
When I run `hub create` interactively
|
|
|
|
When I type "mislav"
|
|
|
|
And I type "kitty"
|
2014-12-24 00:58:04 +03:00
|
|
|
Then the output should contain:
|
|
|
|
"""
|
|
|
|
Error creating repository: Unprocessable Entity (HTTP 422)
|
|
|
|
Duplicate value for "description"
|
|
|
|
"""
|
|
|
|
And the exit status should be 1
|
|
|
|
And the file "../home/.config/hub" should not exist
|
2014-02-28 19:17:01 +04:00
|
|
|
|
2012-11-06 00:40:12 +04:00
|
|
|
Scenario: Credentials from GITHUB_USER & GITHUB_PASSWORD
|
|
|
|
Given the GitHub API server:
|
|
|
|
"""
|
2014-12-24 00:58:04 +03:00
|
|
|
post('/authorizations') {
|
|
|
|
assert_basic_auth 'mislav', 'kitty'
|
|
|
|
json :token => 'OTOKEN'
|
2012-11-06 00:40:12 +04:00
|
|
|
}
|
2012-11-24 23:22:22 +04:00
|
|
|
get('/user') {
|
|
|
|
json :login => 'mislav'
|
|
|
|
}
|
2012-11-22 15:55:28 +04:00
|
|
|
post('/user/repos') {
|
|
|
|
json :full_name => 'mislav/dotfiles'
|
|
|
|
}
|
2012-11-06 00:40:12 +04:00
|
|
|
"""
|
|
|
|
Given $GITHUB_USER is "mislav"
|
|
|
|
And $GITHUB_PASSWORD is "kitty"
|
|
|
|
When I successfully run `hub create`
|
|
|
|
Then the output should not contain "github.com password for mislav"
|
2014-09-15 05:35:43 +04:00
|
|
|
And the file "../home/.config/hub" should contain "oauth_token: OTOKEN"
|
2012-11-06 00:40:12 +04:00
|
|
|
|
2012-05-08 15:01:35 +04:00
|
|
|
Scenario: Wrong password
|
|
|
|
Given the GitHub API server:
|
|
|
|
"""
|
2014-12-24 00:58:04 +03:00
|
|
|
post('/authorizations') {
|
|
|
|
assert_basic_auth 'mislav', 'kitty'
|
2012-05-08 15:01:35 +04:00
|
|
|
}
|
|
|
|
"""
|
|
|
|
When I run `hub create` interactively
|
|
|
|
When I type "mislav"
|
|
|
|
And I type "WRONG"
|
2014-12-24 00:58:04 +03:00
|
|
|
Then the stderr should contain exactly:
|
|
|
|
"""
|
|
|
|
Error creating repository: Unauthorized (HTTP 401)
|
|
|
|
Bad credentials
|
|
|
|
|
|
|
|
"""
|
2012-05-08 15:01:35 +04:00
|
|
|
And the exit status should be 1
|
|
|
|
And the file "../home/.config/hub" should not exist
|
2013-09-20 02:29:09 +04:00
|
|
|
|
2014-12-24 00:58:04 +03:00
|
|
|
Scenario: Personal access token used instead of password
|
2013-10-01 13:53:29 +04:00
|
|
|
Given the GitHub API server:
|
|
|
|
"""
|
2014-12-24 00:58:04 +03:00
|
|
|
post('/authorizations') {
|
|
|
|
status 403
|
|
|
|
json :message => "This API can only be accessed with username and password Basic Auth"
|
2013-10-01 13:53:29 +04:00
|
|
|
}
|
2014-12-24 00:58:04 +03:00
|
|
|
"""
|
|
|
|
When I run `hub create` interactively
|
|
|
|
When I type "mislav"
|
|
|
|
And I type "PERSONALACCESSTOKEN"
|
|
|
|
Then the stderr should contain exactly:
|
|
|
|
"""
|
|
|
|
Error creating repository: Forbidden (HTTP 403)
|
|
|
|
This API can only be accessed with username and password Basic Auth
|
|
|
|
|
|
|
|
"""
|
|
|
|
And the exit status should be 1
|
|
|
|
And the file "../home/.config/hub" should not exist
|
|
|
|
|
|
|
|
Scenario: Two-factor authentication, create authorization
|
|
|
|
Given the GitHub API server:
|
|
|
|
"""
|
2013-10-01 13:53:29 +04:00
|
|
|
post('/authorizations') {
|
2014-12-24 00:58:04 +03:00
|
|
|
assert_basic_auth 'mislav', 'kitty'
|
|
|
|
if request.env['HTTP_X_GITHUB_OTP'] == '112233'
|
|
|
|
json :token => 'OTOKEN'
|
|
|
|
else
|
|
|
|
response.headers['X-GitHub-OTP'] = 'required; app'
|
|
|
|
status 401
|
|
|
|
json :message => "Must specify two-factor authentication OTP code."
|
2013-10-01 13:53:29 +04:00
|
|
|
end
|
|
|
|
}
|
|
|
|
get('/user') {
|
|
|
|
json :login => 'mislav'
|
|
|
|
}
|
|
|
|
post('/user/repos') {
|
|
|
|
json :full_name => 'mislav/dotfiles'
|
|
|
|
}
|
|
|
|
"""
|
|
|
|
When I run `hub create` interactively
|
|
|
|
When I type "mislav"
|
|
|
|
And I type "kitty"
|
|
|
|
And I type "112233"
|
|
|
|
Then the output should contain "github.com password for mislav (never stored):"
|
|
|
|
Then the output should contain "two-factor authentication code:"
|
2014-12-24 00:58:04 +03:00
|
|
|
And the output should not contain "warning: invalid two-factor code"
|
2013-10-01 13:53:29 +04:00
|
|
|
And the exit status should be 0
|
2014-09-15 05:35:43 +04:00
|
|
|
And the file "../home/.config/hub" should contain "oauth_token: OTOKEN"
|
2013-10-01 13:53:29 +04:00
|
|
|
|
2014-12-24 00:58:04 +03:00
|
|
|
Scenario: Retry entering two-factor authentication code
|
2013-09-20 02:29:09 +04:00
|
|
|
Given the GitHub API server:
|
|
|
|
"""
|
2014-12-24 00:58:04 +03:00
|
|
|
previous_otp_code = nil
|
2013-12-18 16:56:08 +04:00
|
|
|
post('/authorizations') {
|
|
|
|
assert_basic_auth 'mislav', 'kitty'
|
2014-12-24 00:58:04 +03:00
|
|
|
if request.env['HTTP_X_GITHUB_OTP'] == '112233'
|
|
|
|
halt 400 unless '666' == previous_otp_code
|
|
|
|
json :token => 'OTOKEN'
|
|
|
|
else
|
|
|
|
previous_otp_code = request.env['HTTP_X_GITHUB_OTP']
|
|
|
|
response.headers['X-GitHub-OTP'] = 'required; app'
|
|
|
|
status 401
|
|
|
|
json :message => "Must specify two-factor authentication OTP code."
|
2013-09-20 02:29:09 +04:00
|
|
|
end
|
|
|
|
}
|
|
|
|
get('/user') {
|
|
|
|
json :login => 'mislav'
|
|
|
|
}
|
|
|
|
post('/user/repos') {
|
|
|
|
json :full_name => 'mislav/dotfiles'
|
|
|
|
}
|
|
|
|
"""
|
|
|
|
When I run `hub create` interactively
|
|
|
|
When I type "mislav"
|
|
|
|
And I type "kitty"
|
2014-12-24 00:58:04 +03:00
|
|
|
And I type "666"
|
2013-09-20 02:29:09 +04:00
|
|
|
And I type "112233"
|
2014-12-24 00:58:04 +03:00
|
|
|
Then the output should contain "warning: invalid two-factor code"
|
2013-09-20 02:29:09 +04:00
|
|
|
And the exit status should be 0
|
2014-12-24 00:58:04 +03:00
|
|
|
And the file "../home/.config/hub" should contain "oauth_token: OTOKEN"
|
2013-09-30 09:25:36 +04:00
|
|
|
|
|
|
|
Scenario: Special characters in username & password
|
|
|
|
Given the GitHub API server:
|
|
|
|
"""
|
|
|
|
post('/authorizations') {
|
2013-10-12 01:15:35 +04:00
|
|
|
assert_basic_auth 'mislav@example.com', 'my pass@phrase ok?'
|
2013-09-30 09:25:36 +04:00
|
|
|
json :token => 'OTOKEN'
|
|
|
|
}
|
|
|
|
get('/user') {
|
|
|
|
json :login => 'mislav'
|
|
|
|
}
|
2013-10-12 01:15:35 +04:00
|
|
|
get('/repos/mislav/dotfiles') { status 200 }
|
2013-09-30 09:25:36 +04:00
|
|
|
"""
|
|
|
|
When I run `hub create` interactively
|
2013-10-12 01:15:35 +04:00
|
|
|
When I type "mislav@example.com"
|
2013-09-30 09:25:36 +04:00
|
|
|
And I type "my pass@phrase ok?"
|
2013-10-12 01:15:35 +04:00
|
|
|
Then the output should contain "github.com password for mislav@example.com (never stored):"
|
|
|
|
And the exit status should be 0
|
2014-09-15 05:35:43 +04:00
|
|
|
And the file "../home/.config/hub" should contain "user: mislav"
|
|
|
|
And the file "../home/.config/hub" should contain "oauth_token: OTOKEN"
|