提交 55b58054 编写于 作者: M Mislav Marohnić

Stop trying to re-use existing Access Tokens for hub

Due to upcoming GitHub API changes, the "token" field will not be
accessible anymore, which will make it impossible for hub to re-use an
existing token that might have been generated for another computer.

Now, a new Access Token will be created every time hub needs to exchange
the username/password credentials for an OAuth token.

https://developer.github.com/changes/2014-12-08-removing-authorizations-token/
上级 93691aea
......@@ -5,10 +5,11 @@ Feature: OAuth authentication
Scenario: Ask for username & password, create authorization
Given the GitHub API server:
"""
get('/authorizations') { '[]' }
post('/authorizations') {
assert_basic_auth 'mislav', 'kitty'
assert :scopes => ['repo']
assert :scopes => ['repo'],
:note => 'hub',
:note_url => 'http://hub.github.com/'
json :token => 'OTOKEN'
}
get('/user') {
......@@ -30,100 +31,12 @@ Feature: OAuth authentication
And the file "../home/.config/hub" should contain "oauth_token: OTOKEN"
And the file "../home/.config/hub" should have mode "0600"
Scenario: Ask for username & password, re-use existing authorization
Given the GitHub API server:
"""
get('/authorizations') {
assert_basic_auth 'mislav', 'kitty'
json [
{:token => 'SKIPPD', :note_url => 'http://example.com'},
{:token => 'OTOKEN', :note_url => 'http://hub.github.com/'}
]
}
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
And the file "../home/.config/hub" should contain "oauth_token: OTOKEN"
Scenario: Re-use existing authorization with an old URL
Given the GitHub API server:
"""
get('/authorizations') {
assert_basic_auth '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
And the file "../home/.config/hub" should contain "oauth_token: OTOKEN"
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"}]
}
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
And the file "../home/.config/hub" should contain "oauth_token: OTOKEN"
Scenario: Credentials from GITHUB_USER & GITHUB_PASSWORD
Given the GitHub API server:
"""
get('/authorizations') {
post('/authorizations') {
assert_basic_auth 'mislav', 'kitty'
json [
{:token => 'OTOKEN', :note_url => 'http://hub.github.com/'}
]
json :token => 'OTOKEN'
}
get('/user') {
json :login => 'mislav'
......@@ -141,7 +54,7 @@ Feature: OAuth authentication
Scenario: Wrong password
Given the GitHub API server:
"""
get('/authorizations') {
post('/authorizations') {
assert_basic_auth 'mislav', 'kitty'
}
"""
......@@ -155,17 +68,8 @@ Feature: OAuth authentication
Scenario: Two-factor authentication, create authorization
Given the GitHub API server:
"""
get('/authorizations') {
assert_basic_auth 'mislav', 'kitty'
if request.env['HTTP_X_GITHUB_OTP'] != "112233"
response.headers['X-GitHub-OTP'] = "required;application"
halt 401
end
json [ ]
}
post('/authorizations') {
assert_basic_auth 'mislav', 'kitty'
halt 412 unless params[:scopes]
if request.env['HTTP_X_GITHUB_OTP'] != "112233"
response.headers['X-GitHub-OTP'] = "required;application"
halt 401
......@@ -188,46 +92,9 @@ Feature: OAuth authentication
And the exit status should be 0
And the file "../home/.config/hub" should contain "oauth_token: OTOKEN"
Scenario: Two-factor authentication, re-use existing authorization
Given the GitHub API server:
"""
token = 'OTOKEN'
post('/authorizations') {
assert_basic_auth 'mislav', 'kitty'
token << 'SMS'
status 412
}
get('/authorizations') {
assert_basic_auth 'mislav', 'kitty'
if request.env['HTTP_X_GITHUB_OTP'] != "112233"
response.headers['X-GitHub-OTP'] = "required;application"
halt 401
end
json [ {
:token => token,
:note_url => 'http://hub.github.com/'
} ]
}
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
And the file "../home/.config/hub" should contain "oauth_token: OTOKENSMS"
Scenario: Special characters in username & password
Given the GitHub API server:
"""
get('/authorizations') { '[]' }
post('/authorizations') {
assert_basic_auth 'mislav@example.com', 'my pass@phrase ok?'
json :token => 'OTOKEN'
......
......@@ -333,36 +333,31 @@ module Hub
end
end
def obtain_oauth_token host, user, two_factor_code = nil
def obtain_oauth_token host, user
auth_url = URI.parse("https://%s@%s/authorizations" % [CGI.escape(user), host])
auth_params = {
:scopes => ['repo'],
:note => 'hub',
:note_url => oauth_app_url
}
res = nil
two_factor_code = nil
# dummy request to trigger a 2FA SMS since a HTTP GET won't do it
post(auth_url) if !two_factor_code
loop do
res = post(auth_url, auth_params) do |req|
req['X-GitHub-OTP'] = two_factor_code if two_factor_code
end
# first try to fetch existing authorization
res = get_all(auth_url) do |req|
req['X-GitHub-OTP'] = two_factor_code if two_factor_code
end
unless res.success?
if !two_factor_code && res['X-GitHub-OTP'].to_s.include?('required')
if res.success?
break
elsif res.status == 401 && res['X-GitHub-OTP'].to_s.include?('required')
two_factor_code = config.prompt_auth_code
return obtain_oauth_token(host, user, two_factor_code)
else
res.error!
end
end
if found = res.data.find {|auth| auth['note'] == 'hub' || auth['note_url'] == oauth_app_url }
found['token']
else
# create a new authorization
res = post auth_url,
:scopes => %w[repo], :note => 'hub', :note_url => oauth_app_url do |req|
req['X-GitHub-OTP'] = two_factor_code if two_factor_code
end
res.error! unless res.success?
res.data['token']
end
res.data['token']
end
end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册