156 lines
5.8 KiB
Ruby
156 lines
5.8 KiB
Ruby
require 'spec_helper'
|
|
|
|
describe Travis::Api::App::Endpoint::Authorization do
|
|
include Travis::Testing::Stubs
|
|
|
|
before do
|
|
add_endpoint '/info' do
|
|
get '/login', scope: :private do
|
|
env['travis.access_token'].user.login
|
|
end
|
|
end
|
|
|
|
user.stubs(:github_id).returns(42)
|
|
User.stubs(:find_github_id).returns(user)
|
|
User.stubs(:find).returns(user)
|
|
|
|
@original_config = Travis.config.oauth2
|
|
Travis.config.oauth2 = {
|
|
authorization_server: 'https://foobar.com',
|
|
access_token_path: '/access_token_path',
|
|
client_id: 'client-id',
|
|
client_secret: 'client-secret',
|
|
scope: 'public_repo,user:email,new_scope',
|
|
insufficient_access_redirect_url: 'https://travis-ci.org/insufficient_access'
|
|
}
|
|
end
|
|
|
|
after do
|
|
Travis.config.oauth2 = @original_config
|
|
end
|
|
|
|
describe 'GET /auth/authorize' do
|
|
skip "not yet implemented"
|
|
end
|
|
|
|
describe 'POST /auth/access_token' do
|
|
skip "not yet implemented"
|
|
end
|
|
|
|
describe "GET /auth/handshake" do
|
|
describe 'evil hackers messing with the state' do
|
|
it 'does not succeed if state cookie mismatches' do
|
|
Travis.redis.sadd('github:states', 'github-state')
|
|
response = get '/auth/handshake?state=github-state&code=oauth-code'
|
|
response.status.should be == 400
|
|
response.body.should be == "state mismatch"
|
|
Travis.redis.srem('github:states', 'github-state')
|
|
end
|
|
end
|
|
|
|
describe 'with insufficient oauth permissions' do
|
|
before do
|
|
Travis.redis.sadd('github:states', 'github-state')
|
|
rack_mock_session.cookie_jar['travis.state'] = 'github-state'
|
|
|
|
response = mock('response')
|
|
response.expects(:body).returns('access_token=foobarbaz-token')
|
|
Faraday.expects(:post).with('https://foobar.com/access_token_path',
|
|
client_id: 'client-id',
|
|
client_secret: 'client-secret',
|
|
scope: 'public_repo,user:email,new_scope',
|
|
redirect_uri: 'http://example.org/auth/handshake',
|
|
state: 'github-state',
|
|
code: 'oauth-code').returns(response)
|
|
|
|
data = { 'id' => 111 }
|
|
data.expects(:headers).returns('x-oauth-scopes' => 'public_repo,user:email')
|
|
GH.expects(:with).with(token: 'foobarbaz-token', client_id: nil).returns(data)
|
|
end
|
|
|
|
after do
|
|
Travis.redis.srem('github:states', 'github-state')
|
|
# this is cached after first run, so if we change scopes, it will stay
|
|
# like that for the rest of the run
|
|
User::Oauth.instance_variable_set("@wanted_scopes", nil)
|
|
end
|
|
|
|
# in endpoint/authorization.rb 271, get_token faraday raises the exception:
|
|
# hostname "foobar.com" does not match the server certificate
|
|
# TODO disabling this as per @rkh's advice
|
|
xit 'redirects to insufficient access page' do
|
|
response = get '/auth/handshake?state=github-state&code=oauth-code'
|
|
response.should redirect_to('https://travis-ci.org/insufficient_access')
|
|
end
|
|
|
|
# TODO disabling this as per @rkh's advice
|
|
xit 'redirects to insufficient access page for existing user' do
|
|
user = mock('user')
|
|
User.expects(:find_by_github_id).with(111).returns(user)
|
|
expect {
|
|
response = get '/auth/handshake?state=github-state&code=oauth-code'
|
|
response.should redirect_to('https://travis-ci.org/insufficient_access#existing-user')
|
|
}.to_not change { User.count }
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'POST /auth/github' do
|
|
before do
|
|
data = { 'id' => user.github_id, 'name' => user.name, 'login' => user.login, 'gravatar_id' => user.gravatar_id }
|
|
GH.stubs(:with).with(token: 'private repos', client_id: nil).returns stub(:[] => user.login, :headers => {'x-oauth-scopes' => 'repo'}, :to_hash => data)
|
|
GH.stubs(:with).with(token: 'public repos', client_id: nil).returns stub(:[] => user.login, :headers => {'x-oauth-scopes' => 'public_repo'}, :to_hash => data)
|
|
GH.stubs(:with).with(token: 'no repos', client_id: nil).returns stub(:[] => user.login, :headers => {'x-oauth-scopes' => 'user'}, :to_hash => data)
|
|
GH.stubs(:with).with(token: 'invalid token', client_id: nil).raises(Faraday::Error::ClientError, 'CLIENT ERROR!')
|
|
end
|
|
|
|
def get_token(github_token)
|
|
post('/auth/github', github_token: github_token).should be_ok
|
|
parsed_body['access_token']
|
|
end
|
|
|
|
def user_for(github_token)
|
|
get '/info/login', access_token: get_token(github_token)
|
|
last_response.status.should == 200
|
|
user if user.login == body
|
|
end
|
|
|
|
it 'accepts tokens with repo scope' do
|
|
user_for('private repos').name.should == user.name
|
|
end
|
|
|
|
it 'accepts tokens with public_repo scope' do
|
|
user_for('public repos').name.should == user.name
|
|
end
|
|
|
|
it 'rejects tokens with user scope' do
|
|
post('/auth/github', github_token: 'no repos').should_not be_ok
|
|
body.should_not include('access_token')
|
|
end
|
|
|
|
it 'rejects tokens with user scope' do
|
|
post('/auth/github', github_token: 'invalid token').should_not be_ok
|
|
body.should_not include('access_token')
|
|
end
|
|
|
|
it 'does not store the token' do
|
|
user_for('public repos').github_oauth_token.should_not == 'public repos'
|
|
end
|
|
|
|
it "errors if no token is given" do
|
|
User.stubs(:find_by_github_id).with(111).returns(user)
|
|
post("/auth/github").should_not be_ok
|
|
last_response.status.should == 422
|
|
body.should_not include("access_token")
|
|
end
|
|
|
|
it "errors if github throws an error" do
|
|
GH.stubs(:with).raises(GH::Error)
|
|
post("/auth/github", github_token: 'foo bar').should_not be_ok
|
|
last_response.status.should == 403
|
|
body.should_not include("access_token")
|
|
body.should include("not a Travis user")
|
|
end
|
|
end
|
|
end
|