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:
|
|
|
|
"""
|
|
|
|
require 'rack/auth/basic'
|
|
|
|
get('/authorizations') { '[]' }
|
|
|
|
post('/authorizations') {
|
|
|
|
auth = Rack::Auth::Basic::Request.new(env)
|
|
|
|
halt 401 unless auth.credentials == %w[mislav kitty]
|
2013-05-12 14:33:51 +04:00
|
|
|
assert :scopes => ['repo']
|
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-03-13 21:28:01 +04:00
|
|
|
And the file "../home/.config/hub" should contain 'user = "MiSlAv"'
|
|
|
|
And the file "../home/.config/hub" should contain 'access_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
|
|
|
|
|
|
|
Scenario: Ask for username & password, re-use existing authorization
|
|
|
|
Given the GitHub API server:
|
|
|
|
"""
|
|
|
|
require 'rack/auth/basic'
|
|
|
|
get('/authorizations') {
|
|
|
|
auth = Rack::Auth::Basic::Request.new(env)
|
|
|
|
halt 401 unless auth.credentials == %w[mislav kitty]
|
2012-10-10 15:50:23 +04:00
|
|
|
json [
|
2014-02-28 18:57:52 +04:00
|
|
|
{:token => 'SKIPPD', :note_url => 'http://example.com'},
|
|
|
|
{:token => 'OTOKEN', :note_url => 'http://hub.github.com/'}
|
2012-05-08 15:01:35 +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-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 password for mislav (never stored):"
|
|
|
|
And the exit status should be 0
|
2014-03-13 22:05:48 +04:00
|
|
|
And the file "../home/.config/hub" should contain 'access_token = "OTOKEN"'
|
2012-05-08 15:01:35 +04:00
|
|
|
|
2014-02-28 19:17:01 +04:00
|
|
|
Scenario: Re-use existing authorization with an old URL
|
|
|
|
Given the GitHub API server:
|
|
|
|
"""
|
|
|
|
require 'rack/auth/basic'
|
|
|
|
get('/authorizations') {
|
|
|
|
auth = Rack::Auth::Basic::Request.new(env)
|
|
|
|
halt 401 unless auth.credentials == %w[mislav kitty]
|
|
|
|
json [
|
|
|
|
{:token => 'OTOKEN', :note => 'hub', :note_url => 'http://defunkt.io/hub/'}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
post('/authorizations') {
|
|
|
|
status 422
|
|
|
|
json :message => "Validation Failed",
|
|
|
|
:errors => [{:resource => "OauthAccess", :code => "already_exists", :field => "description"}]
|
|
|
|
}
|
|
|
|
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"
|
|
|
|
Then the output should contain "github.com password for mislav (never stored):"
|
|
|
|
And the exit status should be 0
|
2014-04-11 08:04:05 +04:00
|
|
|
And the file "../home/.config/hub" should contain 'access_token = "OTOKEN"'
|
2014-02-28 19:17:01 +04:00
|
|
|
|
2014-05-15 22:10:44 +04:00
|
|
|
Scenario: Re-use existing authorization found on page 3
|
|
|
|
Given the GitHub API server:
|
|
|
|
"""
|
|
|
|
get('/authorizations') {
|
|
|
|
assert_basic_auth 'mislav', 'kitty'
|
|
|
|
page = (params[:page] || 1).to_i
|
|
|
|
if page < 3
|
|
|
|
response.headers['Link'] = %(<#{url}?page=#{page+1}>; rel="next")
|
|
|
|
json []
|
|
|
|
else
|
|
|
|
json [
|
|
|
|
{:token => 'OTOKEN', :note => 'hub', :note_url => 'http://hub.github.com/'}
|
|
|
|
]
|
|
|
|
end
|
|
|
|
}
|
|
|
|
post('/authorizations') {
|
|
|
|
status 422
|
|
|
|
json :message => "Validation Failed",
|
|
|
|
:errors => [{:resource => "OauthAccess", :code => "already_exists", :field => "description"}]
|
2014-02-28 19:17:01 +04:00
|
|
|
}
|
|
|
|
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"
|
|
|
|
Then the output should contain "github.com password for mislav (never stored):"
|
|
|
|
And the exit status should be 0
|
2014-07-26 02:53:37 +04:00
|
|
|
And the file "../home/.config/hub" should contain 'access_token = "OTOKEN"'
|
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:
|
|
|
|
"""
|
|
|
|
require 'rack/auth/basic'
|
|
|
|
get('/authorizations') {
|
|
|
|
auth = Rack::Auth::Basic::Request.new(env)
|
|
|
|
halt 401 unless auth.credentials == %w[mislav kitty]
|
|
|
|
json [
|
2014-02-28 18:57:52 +04:00
|
|
|
{:token => 'OTOKEN', :note_url => 'http://hub.github.com/'}
|
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-03-13 22:08:31 +04:00
|
|
|
And the file "../home/.config/hub" should contain 'access_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:
|
|
|
|
"""
|
|
|
|
require 'rack/auth/basic'
|
|
|
|
get('/authorizations') {
|
|
|
|
auth = Rack::Auth::Basic::Request.new(env)
|
|
|
|
halt 401 unless auth.credentials == %w[mislav kitty]
|
|
|
|
}
|
|
|
|
"""
|
|
|
|
When I run `hub create` interactively
|
|
|
|
When I type "mislav"
|
|
|
|
And I type "WRONG"
|
|
|
|
Then the stderr should contain "Error creating repository: Unauthorized (HTTP 401)"
|
|
|
|
And the exit status should be 1
|
|
|
|
And the file "../home/.config/hub" should not exist
|
2013-09-20 02:29:09 +04:00
|
|
|
|
2013-10-01 13:53:29 +04:00
|
|
|
Scenario: Two-factor authentication, create authorization
|
|
|
|
Given the GitHub API server:
|
|
|
|
"""
|
|
|
|
require 'rack/auth/basic'
|
|
|
|
get('/authorizations') {
|
|
|
|
auth = Rack::Auth::Basic::Request.new(env)
|
|
|
|
halt 401 unless auth.credentials == %w[mislav kitty]
|
|
|
|
if request.env['HTTP_X_GITHUB_OTP'] != "112233"
|
2014-03-25 02:47:03 +04:00
|
|
|
response.headers['X-GitHub-OTP'] = "required; app"
|
2013-10-01 13:53:29 +04:00
|
|
|
halt 401
|
|
|
|
end
|
|
|
|
json [ ]
|
|
|
|
}
|
|
|
|
post('/authorizations') {
|
|
|
|
auth = Rack::Auth::Basic::Request.new(env)
|
|
|
|
halt 401 unless auth.credentials == %w[mislav kitty]
|
2013-12-18 16:56:08 +04:00
|
|
|
halt 412 unless params[:scopes]
|
2013-10-01 13:53:29 +04:00
|
|
|
if request.env['HTTP_X_GITHUB_OTP'] != "112233"
|
2014-03-25 02:47:03 +04:00
|
|
|
response.headers['X-GitHub-OTP'] = "required; app"
|
2013-10-01 13:53:29 +04:00
|
|
|
halt 401
|
|
|
|
end
|
|
|
|
json :token => 'OTOKEN'
|
|
|
|
}
|
|
|
|
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:"
|
|
|
|
And the exit status should be 0
|
2014-03-13 22:08:31 +04:00
|
|
|
And the file "../home/.config/hub" should contain 'access_token = "OTOKEN"'
|
2013-10-01 13:53:29 +04:00
|
|
|
|
|
|
|
Scenario: Two-factor authentication, re-use existing authorization
|
2013-09-20 02:29:09 +04:00
|
|
|
Given the GitHub API server:
|
|
|
|
"""
|
2013-12-18 16:56:08 +04:00
|
|
|
token = 'OTOKEN'
|
|
|
|
post('/authorizations') {
|
|
|
|
assert_basic_auth 'mislav', 'kitty'
|
|
|
|
token << 'SMS'
|
|
|
|
status 412
|
|
|
|
}
|
2013-09-20 02:29:09 +04:00
|
|
|
get('/authorizations') {
|
2013-12-18 16:56:08 +04:00
|
|
|
assert_basic_auth 'mislav', 'kitty'
|
2013-09-20 02:29:09 +04:00
|
|
|
if request.env['HTTP_X_GITHUB_OTP'] != "112233"
|
2014-03-25 02:47:03 +04:00
|
|
|
response.headers['X-GitHub-OTP'] = "required; app"
|
2013-09-20 02:29:09 +04:00
|
|
|
halt 401
|
|
|
|
end
|
2013-12-18 16:56:08 +04:00
|
|
|
json [ {
|
|
|
|
:token => token,
|
2014-02-28 18:57:52 +04:00
|
|
|
:note_url => 'http://hub.github.com/'
|
2013-12-18 16:56:08 +04:00
|
|
|
} ]
|
2013-09-20 02:29:09 +04:00
|
|
|
}
|
|
|
|
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:"
|
|
|
|
And the exit status should be 0
|
2014-03-13 22:08:31 +04:00
|
|
|
And the file "../home/.config/hub" should contain 'access_token = "OTOKENSMS"'
|
2013-09-30 09:25:36 +04:00
|
|
|
|
|
|
|
Scenario: Special characters in username & password
|
|
|
|
Given the GitHub API server:
|
|
|
|
"""
|
|
|
|
get('/authorizations') { '[]' }
|
|
|
|
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-03-13 22:47:36 +04:00
|
|
|
And the file "../home/.config/hub" should contain 'user = "mislav"'
|
2014-03-13 22:08:31 +04:00
|
|
|
And the file "../home/.config/hub" should contain 'access_token = "OTOKEN"'
|