commit
c75d7398ff
|
@ -9,7 +9,7 @@ rvm:
|
|||
- jruby
|
||||
matrix:
|
||||
allow_failures:
|
||||
- rbx-2 # See rubinius/rubinius#3485 - rubocop segfaults
|
||||
- rvm: rbx-2 # See rubinius/rubinius#3485 - rubocop segfaults
|
||||
script: "bundle exec rake"
|
||||
addons:
|
||||
apt:
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
## 0.5.0 (12/10/2015)
|
||||
|
||||
### Changes
|
||||
|
||||
* Initial support for user credentials ([@sqrrrl][])
|
||||
* Update Signet to 0.7
|
||||
|
||||
## 0.4.2 (05/08/2015)
|
||||
|
||||
### Changes
|
||||
|
|
1
Gemfile
1
Gemfile
|
@ -15,6 +15,7 @@ group :development do
|
|||
gem 'fakeredis', '~> 0.5'
|
||||
gem 'webmock', '~> 1.21'
|
||||
gem 'rack-test', '~> 0.6'
|
||||
gem 'sinatra'
|
||||
end
|
||||
|
||||
platforms :jruby do
|
||||
|
|
81
README.md
81
README.md
|
@ -38,7 +38,8 @@ $ gem install googleauth
|
|||
require 'googleauth'
|
||||
|
||||
# Get the environment configured authorization
|
||||
scopes = ['https://www.googleapis.com/auth/cloud-platform', 'https://www.googleapis.com/auth/compute']
|
||||
scopes = ['https://www.googleapis.com/auth/cloud-platform',
|
||||
'https://www.googleapis.com/auth/compute']
|
||||
authorization = Google::Auth.get_application_default(scopes)
|
||||
|
||||
# Add the the access token obtained using the authorization to a hash, e.g
|
||||
|
@ -61,6 +62,84 @@ and authorization level for the application independent of the user. This is
|
|||
the recommended approach to authorize calls to Cloud APIs, particularly when
|
||||
you're building an application that uses Google Compute Engine.
|
||||
|
||||
## User Credentials
|
||||
|
||||
The library also provides support for requesting and storing user
|
||||
credentials (3-Legged OAuth2.) Two implementations are currently available,
|
||||
a generic authorizer useful for command line apps or custom integrations as
|
||||
well as a web variant tailored toward Rack-based applications.
|
||||
|
||||
The authorizers are intended for authorization use cases. For sign-on,
|
||||
see [Google Idenity Platform](https://developers.google.com/identity/)
|
||||
|
||||
### Example (Web)
|
||||
|
||||
```ruby
|
||||
require 'googleauth'
|
||||
require 'googleauth/web_user_authorizer'
|
||||
require 'googleauth/stores/redis_token_store'
|
||||
require 'redis'
|
||||
|
||||
client_id = Google::Auth::ClientId.from_file('/path/to/client_secrets.json')
|
||||
scope = ['https://www.googleapis.com/auth/drive']
|
||||
token_store = Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new)
|
||||
authorizer = Google::Auth::WebUserAuthorizer.new(
|
||||
client_id, scope, token_store, '/oauth2callback')
|
||||
|
||||
|
||||
get('/authorize') do
|
||||
# NOTE: Assumes the user is already authenticated to the app
|
||||
user_id = request.session['user_id']
|
||||
credentials = authorizer.get_credentials(user_id, request)
|
||||
if credentials.nil?
|
||||
redirect authorizer.get_authorization_url(user_id: user_id, request: request)
|
||||
end
|
||||
# Credentials are valid, can call APIs
|
||||
# ...
|
||||
end
|
||||
|
||||
get('/oauth2callback') do
|
||||
target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(
|
||||
request)
|
||||
redirect target_url
|
||||
end
|
||||
```
|
||||
|
||||
### Example (Command Line)
|
||||
|
||||
```ruby
|
||||
require 'googleauth'
|
||||
require 'googleauth/stores/file_token_store'
|
||||
|
||||
scope = 'https://www.googleapis.com/auth/drive'
|
||||
client_id = Google::Auth::ClientId.from_file('/path/to/client_secrets.json')
|
||||
token_store = Google::Auth::Stores::FileTokenStore.new(
|
||||
:file => '/path/to/tokens.yaml')
|
||||
authorizer = Google::Auth::UserAuthorizer.new(client_id, scope, token_store)
|
||||
|
||||
credentials = authorizer.get_credentials(user_id)
|
||||
if credentials.nil?
|
||||
url = authorizer.get_authorization_url(base_url: 'urn:ietf:wg:oauth:2.0:oob')
|
||||
puts "Open #{url} in your browser and enter the resulting code:"
|
||||
code = gets
|
||||
credentials = authorizer.get_and_store_credentials_from_code(
|
||||
user_id: user_id, code: code, base_url: OOB_URI)
|
||||
end
|
||||
|
||||
# OK to use credentials
|
||||
```
|
||||
|
||||
### Storage
|
||||
|
||||
Authorizers require a storage instance to manage long term persistence of
|
||||
access and refresh tokens. Two storage implementations are included:
|
||||
|
||||
* Google::Auth::Stores::FileTokenStore
|
||||
* Google::Auth::Stores::RedisTokenStore
|
||||
|
||||
Custom storage implementations can also be used. See
|
||||
[token_store.rb](lib/googleauth/token_store.rb) for additional details.
|
||||
|
||||
## What about auth in google-apis-ruby-client?
|
||||
|
||||
The goal is for all auth done by
|
||||
|
|
|
@ -30,5 +30,5 @@ Gem::Specification.new do |s|
|
|||
s.add_dependency 'jwt', '~> 1.4'
|
||||
s.add_dependency 'memoist', '~> 0.12'
|
||||
s.add_dependency 'multi_json', '~> 1.11'
|
||||
s.add_dependency 'signet', '~> 0.6'
|
||||
s.add_dependency 'signet', '~> 0.7'
|
||||
end
|
||||
|
|
|
@ -42,7 +42,7 @@ module Signet
|
|||
def apply!(a_hash, opts = {})
|
||||
# fetch the access token there is currently not one, or if the client
|
||||
# has expired
|
||||
fetch_access_token!(opts) if access_token.nil? || expired?
|
||||
fetch_access_token!(opts) if access_token.nil? || expires_within?(60)
|
||||
a_hash[AUTH_METADATA_KEY] = "Bearer #{access_token}"
|
||||
end
|
||||
|
||||
|
@ -65,7 +65,7 @@ module Signet
|
|||
end
|
||||
|
||||
alias_method :orig_fetch_access_token!, :fetch_access_token!
|
||||
def fetch_access_token!(options)
|
||||
def fetch_access_token!(options = {})
|
||||
info = orig_fetch_access_token!(options)
|
||||
notify_refresh_listeners
|
||||
info
|
||||
|
|
|
@ -31,6 +31,6 @@ module Google
|
|||
# Module Auth provides classes that provide Google-specific authorization
|
||||
# used to access Google APIs.
|
||||
module Auth
|
||||
VERSION = '0.4.2'
|
||||
VERSION = '0.5.0'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -44,16 +44,17 @@ module Google
|
|||
# user_id = request.session['user_email']
|
||||
# credentials = authorizer.get_credentials(user_id, request)
|
||||
# if credentials.nil?
|
||||
# redirect authorizer.get_redirect_uri(user_id, request)
|
||||
# redirect authorizer.get_authorization_url(user_id: user_id,
|
||||
# request: request)
|
||||
# end
|
||||
# # Credentials are valid, can call APIs
|
||||
# ...
|
||||
# end
|
||||
#
|
||||
# get('/oauth2callback') do
|
||||
# user_id = request.session['user_email']
|
||||
# _, return_uri = authorizer.handle_auth_callback(user_id, request)
|
||||
# redirect return_uri
|
||||
# url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(
|
||||
# request)
|
||||
# redirect url
|
||||
# end
|
||||
#
|
||||
# Instead of implementing the callback directly, applications are
|
||||
|
|
|
@ -34,18 +34,6 @@ $LOAD_PATH.uniq!
|
|||
require 'faraday'
|
||||
require 'spec_helper'
|
||||
|
||||
def build_json_response(payload)
|
||||
[200,
|
||||
{ 'Content-Type' => 'application/json; charset=utf-8' },
|
||||
MultiJson.dump(payload)]
|
||||
end
|
||||
|
||||
def build_access_token_json(token)
|
||||
build_json_response('access_token' => token,
|
||||
'token_type' => 'Bearer',
|
||||
'expires_in' => 3600)
|
||||
end
|
||||
|
||||
shared_examples 'apply/apply! are OK' do
|
||||
let(:auth_key) { :Authorization }
|
||||
|
||||
|
@ -57,124 +45,101 @@ shared_examples 'apply/apply! are OK' do
|
|||
# auth client
|
||||
describe '#fetch_access_token' do
|
||||
let(:token) { '1/abcdef1234567890' }
|
||||
let(:stubs) do
|
||||
let(:stub) do
|
||||
make_auth_stubs access_token: token
|
||||
end
|
||||
let(:connection) do
|
||||
Faraday.new do |b|
|
||||
b.adapter(:test, stubs)
|
||||
end
|
||||
end
|
||||
|
||||
it 'should set access_token to the fetched value' do
|
||||
@client.fetch_access_token!(connection: connection)
|
||||
stub
|
||||
@client.fetch_access_token!
|
||||
expect(@client.access_token).to eq(token)
|
||||
stubs.verify_stubbed_calls
|
||||
expect(stub).to have_been_requested
|
||||
end
|
||||
|
||||
it 'should notify refresh listeners after updating' do
|
||||
stub
|
||||
expect do |b|
|
||||
@client.on_refresh(&b)
|
||||
@client.fetch_access_token!(connection: connection)
|
||||
@client.fetch_access_token!
|
||||
end.to yield_with_args(have_attributes(
|
||||
access_token: '1/abcdef1234567890'))
|
||||
stubs.verify_stubbed_calls
|
||||
expect(stub).to have_been_requested
|
||||
end
|
||||
end
|
||||
|
||||
describe '#apply!' do
|
||||
it 'should update the target hash with fetched access token' do
|
||||
token = '1/abcdef1234567890'
|
||||
stubs = make_auth_stubs access_token: token
|
||||
c = Faraday.new do |b|
|
||||
b.adapter(:test, stubs)
|
||||
end
|
||||
stub = make_auth_stubs access_token: token
|
||||
|
||||
md = { foo: 'bar' }
|
||||
@client.apply!(md, connection: c)
|
||||
@client.apply!(md)
|
||||
want = { :foo => 'bar', auth_key => "Bearer #{token}" }
|
||||
expect(md).to eq(want)
|
||||
stubs.verify_stubbed_calls
|
||||
expect(stub).to have_been_requested
|
||||
end
|
||||
end
|
||||
|
||||
describe 'updater_proc' do
|
||||
it 'should provide a proc that updates a hash with the access token' do
|
||||
token = '1/abcdef1234567890'
|
||||
stubs = make_auth_stubs access_token: token
|
||||
c = Faraday.new do |b|
|
||||
b.adapter(:test, stubs)
|
||||
end
|
||||
|
||||
stub = make_auth_stubs access_token: token
|
||||
md = { foo: 'bar' }
|
||||
the_proc = @client.updater_proc
|
||||
got = the_proc.call(md, connection: c)
|
||||
got = the_proc.call(md)
|
||||
want = { :foo => 'bar', auth_key => "Bearer #{token}" }
|
||||
expect(got).to eq(want)
|
||||
stubs.verify_stubbed_calls
|
||||
expect(stub).to have_been_requested
|
||||
end
|
||||
end
|
||||
|
||||
describe '#apply' do
|
||||
it 'should not update the original hash with the access token' do
|
||||
token = '1/abcdef1234567890'
|
||||
stubs = make_auth_stubs access_token: token
|
||||
c = Faraday.new do |b|
|
||||
b.adapter(:test, stubs)
|
||||
end
|
||||
stub = make_auth_stubs access_token: token
|
||||
|
||||
md = { foo: 'bar' }
|
||||
@client.apply(md, connection: c)
|
||||
@client.apply(md)
|
||||
want = { foo: 'bar' }
|
||||
expect(md).to eq(want)
|
||||
stubs.verify_stubbed_calls
|
||||
expect(stub).to have_been_requested
|
||||
end
|
||||
|
||||
it 'should add the token to the returned hash' do
|
||||
token = '1/abcdef1234567890'
|
||||
stubs = make_auth_stubs access_token: token
|
||||
c = Faraday.new do |b|
|
||||
b.adapter(:test, stubs)
|
||||
end
|
||||
stub = make_auth_stubs access_token: token
|
||||
|
||||
md = { foo: 'bar' }
|
||||
got = @client.apply(md, connection: c)
|
||||
got = @client.apply(md)
|
||||
want = { :foo => 'bar', auth_key => "Bearer #{token}" }
|
||||
expect(got).to eq(want)
|
||||
stubs.verify_stubbed_calls
|
||||
expect(stub).to have_been_requested
|
||||
end
|
||||
|
||||
it 'should not fetch a new token if the current is not expired' do
|
||||
token = '1/abcdef1234567890'
|
||||
stubs = make_auth_stubs access_token: token
|
||||
c = Faraday.new do |b|
|
||||
b.adapter(:test, stubs)
|
||||
end
|
||||
stub = make_auth_stubs access_token: token
|
||||
|
||||
n = 5 # arbitrary
|
||||
n.times do |_t|
|
||||
md = { foo: 'bar' }
|
||||
got = @client.apply(md, connection: c)
|
||||
got = @client.apply(md)
|
||||
want = { :foo => 'bar', auth_key => "Bearer #{token}" }
|
||||
expect(got).to eq(want)
|
||||
end
|
||||
stubs.verify_stubbed_calls
|
||||
expect(stub).to have_been_requested
|
||||
end
|
||||
|
||||
it 'should fetch a new token if the current one is expired' do
|
||||
token_1 = '1/abcdef1234567890'
|
||||
token_2 = '2/abcdef1234567890'
|
||||
token_2 = '2/abcdef1234567891'
|
||||
|
||||
[token_1, token_2].each do |t|
|
||||
stubs = make_auth_stubs access_token: t
|
||||
c = Faraday.new do |b|
|
||||
b.adapter(:test, stubs)
|
||||
end
|
||||
make_auth_stubs access_token: t
|
||||
md = { foo: 'bar' }
|
||||
got = @client.apply(md, connection: c)
|
||||
got = @client.apply(md)
|
||||
want = { :foo => 'bar', auth_key => "Bearer #{t}" }
|
||||
expect(got).to eq(want)
|
||||
stubs.verify_stubbed_calls
|
||||
@client.expires_at -= 3601 # default is to expire in 1hr
|
||||
end
|
||||
end
|
||||
|
|
|
@ -37,7 +37,7 @@ require 'googleauth/compute_engine'
|
|||
require 'spec_helper'
|
||||
|
||||
describe Google::Auth::GCECredentials do
|
||||
MD_URI = '/computeMetadata/v1/instance/service-accounts/default/token'
|
||||
MD_URI = 'http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token'
|
||||
GCECredentials = Google::Auth::GCECredentials
|
||||
|
||||
before(:example) do
|
||||
|
@ -46,16 +46,14 @@ describe Google::Auth::GCECredentials do
|
|||
|
||||
def make_auth_stubs(opts = {})
|
||||
access_token = opts[:access_token] || ''
|
||||
Faraday::Adapter::Test::Stubs.new do |stub|
|
||||
stub.get(MD_URI) do |env|
|
||||
headers = env[:request_headers]
|
||||
expect(headers['Metadata-Flavor']).to eq('Google')
|
||||
build_json_response(
|
||||
'access_token' => access_token,
|
||||
'token_type' => 'Bearer',
|
||||
'expires_in' => 3600)
|
||||
end
|
||||
end
|
||||
body = MultiJson.dump('access_token' => access_token,
|
||||
'token_type' => 'Bearer',
|
||||
'expires_in' => 3600)
|
||||
stub_request(:get, MD_URI)
|
||||
.with(headers: { 'Metadata-Flavor' => 'Google' })
|
||||
.to_return(body: body,
|
||||
status: 200,
|
||||
headers: { 'Content-Type' => 'application/json' })
|
||||
end
|
||||
|
||||
it_behaves_like 'apply/apply! are OK'
|
||||
|
@ -63,83 +61,48 @@ describe Google::Auth::GCECredentials do
|
|||
context 'metadata is unavailable' do
|
||||
describe '#fetch_access_token' do
|
||||
it 'should fail if the metadata request returns a 404' do
|
||||
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
||||
stub.get(MD_URI) do |_env|
|
||||
[404,
|
||||
{ 'Metadata-Flavor' => 'Google' },
|
||||
'']
|
||||
end
|
||||
end
|
||||
c = Faraday.new do |b|
|
||||
b.adapter(:test, stubs)
|
||||
end
|
||||
blk = proc { @client.fetch_access_token!(connection: c) }
|
||||
stub = stub_request(:get, MD_URI)
|
||||
.to_return(status: 404,
|
||||
headers: { 'Metadata-Flavor' => 'Google' })
|
||||
blk = proc { @client.fetch_access_token! }
|
||||
expect(&blk).to raise_error Signet::AuthorizationError
|
||||
stubs.verify_stubbed_calls
|
||||
expect(stub).to have_been_requested
|
||||
end
|
||||
|
||||
it 'should fail if the metadata request returns an unexpected code' do
|
||||
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
||||
stub.get(MD_URI) do |_env|
|
||||
[503,
|
||||
{ 'Metadata-Flavor' => 'Google' },
|
||||
'']
|
||||
end
|
||||
end
|
||||
c = Faraday.new do |b|
|
||||
b.adapter(:test, stubs)
|
||||
end
|
||||
blk = proc { @client.fetch_access_token!(connection: c) }
|
||||
stub = stub_request(:get, MD_URI)
|
||||
.to_return(status: 503,
|
||||
headers: { 'Metadata-Flavor' => 'Google' })
|
||||
blk = proc { @client.fetch_access_token! }
|
||||
expect(&blk).to raise_error Signet::AuthorizationError
|
||||
stubs.verify_stubbed_calls
|
||||
expect(stub).to have_been_requested
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#on_gce?' do
|
||||
it 'should be true when Metadata-Flavor is Google' do
|
||||
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
||||
stub.get('/') do |_env|
|
||||
[200,
|
||||
{ 'Metadata-Flavor' => 'Google' },
|
||||
'']
|
||||
end
|
||||
end
|
||||
c = Faraday.new do |b|
|
||||
b.adapter(:test, stubs)
|
||||
end
|
||||
expect(GCECredentials.on_gce?(connection: c)).to eq(true)
|
||||
stubs.verify_stubbed_calls
|
||||
stub = stub_request(:get, 'http://169.254.169.254')
|
||||
.to_return(status: 200,
|
||||
headers: { 'Metadata-Flavor' => 'Google' })
|
||||
expect(GCECredentials.on_gce?({}, true)).to eq(true)
|
||||
expect(stub).to have_been_requested
|
||||
end
|
||||
|
||||
it 'should be false when Metadata-Flavor is not Google' do
|
||||
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
||||
stub.get('/') do |_env|
|
||||
[200,
|
||||
{ 'Metadata-Flavor' => 'NotGoogle' },
|
||||
'']
|
||||
end
|
||||
end
|
||||
c = Faraday.new do |b|
|
||||
b.adapter(:test, stubs)
|
||||
end
|
||||
expect(GCECredentials.on_gce?(connection: c)).to eq(false)
|
||||
stubs.verify_stubbed_calls
|
||||
stub = stub_request(:get, 'http://169.254.169.254')
|
||||
.to_return(status: 200,
|
||||
headers: { 'Metadata-Flavor' => 'NotGoogle' })
|
||||
expect(GCECredentials.on_gce?({}, true)).to eq(false)
|
||||
expect(stub).to have_been_requested
|
||||
end
|
||||
|
||||
it 'should be false if the response is not 200' do
|
||||
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
||||
stub.get('/') do |_env|
|
||||
[404,
|
||||
{ 'Metadata-Flavor' => 'Google' },
|
||||
'']
|
||||
end
|
||||
end
|
||||
c = Faraday.new do |b|
|
||||
b.adapter(:test, stubs)
|
||||
end
|
||||
expect(GCECredentials.on_gce?(connection: c)).to eq(false)
|
||||
stubs.verify_stubbed_calls
|
||||
stub = stub_request(:get, 'http://169.254.169.254')
|
||||
.to_return(status: 404,
|
||||
headers: { 'Metadata-Flavor' => 'NotGoogle' })
|
||||
expect(GCECredentials.on_gce?({}, true)).to eq(false)
|
||||
expect(stub).to have_been_requested
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -37,6 +37,9 @@ require 'googleauth'
|
|||
require 'spec_helper'
|
||||
|
||||
describe '#get_application_default' do
|
||||
# Pass unique options each time to bypass memoization
|
||||
let(:options) { |example| { dememoize: example } }
|
||||
|
||||
before(:example) do
|
||||
@key = OpenSSL::PKey::RSA.new(2048)
|
||||
@var_name = ENV_VAR
|
||||
|
@ -59,31 +62,24 @@ describe '#get_application_default' do
|
|||
Dir.mktmpdir do |dir|
|
||||
key_path = File.join(dir, 'does-not-exist')
|
||||
ENV[@var_name] = key_path
|
||||
expect { Google::Auth.get_application_default(@scope) }
|
||||
expect { Google::Auth.get_application_default(@scope, options) }
|
||||
.to raise_error RuntimeError
|
||||
end
|
||||
end
|
||||
|
||||
it 'fails without default file or env if not on compute engine' do
|
||||
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
||||
stub.get('/') do |_env|
|
||||
[404,
|
||||
{ 'Metadata-Flavor' => 'Google' },
|
||||
'']
|
||||
end
|
||||
end # GCE not detected
|
||||
stub = stub_request(:get, 'http://169.254.169.254')
|
||||
.to_return(status: 404,
|
||||
headers: { 'Metadata-Flavor' => 'NotGoogle' })
|
||||
Dir.mktmpdir do |dir|
|
||||
ENV.delete(@var_name) unless ENV[@var_name].nil? # no env var
|
||||
ENV['HOME'] = dir # no config present in this tmp dir
|
||||
c = Faraday.new do |b|
|
||||
b.adapter(:test, stubs)
|
||||
end
|
||||
blk = proc do
|
||||
Google::Auth.get_application_default(@scope, connection: c)
|
||||
Google::Auth.get_application_default(@scope, options)
|
||||
end
|
||||
expect(&blk).to raise_error RuntimeError
|
||||
end
|
||||
stubs.verify_stubbed_calls
|
||||
expect(stub).to have_been_requested
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -94,7 +90,8 @@ describe '#get_application_default' do
|
|||
FileUtils.mkdir_p(File.dirname(key_path))
|
||||
File.write(key_path, cred_json_text)
|
||||
ENV[@var_name] = key_path
|
||||
expect(Google::Auth.get_application_default(@scope)).to_not be_nil
|
||||
expect(Google::Auth.get_application_default(@scope, options))
|
||||
.to_not be_nil
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -105,7 +102,8 @@ describe '#get_application_default' do
|
|||
FileUtils.mkdir_p(File.dirname(key_path))
|
||||
File.write(key_path, cred_json_text)
|
||||
ENV['HOME'] = dir
|
||||
expect(Google::Auth.get_application_default(@scope)).to_not be_nil
|
||||
expect(Google::Auth.get_application_default(@scope, options))
|
||||
.to_not be_nil
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -116,30 +114,21 @@ describe '#get_application_default' do
|
|||
FileUtils.mkdir_p(File.dirname(key_path))
|
||||
File.write(key_path, cred_json_text)
|
||||
ENV['HOME'] = dir
|
||||
expect(Google::Auth.get_application_default).to_not be_nil
|
||||
expect(Google::Auth.get_application_default(nil, options)).to_not be_nil
|
||||
end
|
||||
end
|
||||
|
||||
it 'succeeds without default file or env if on compute engine' do
|
||||
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
||||
stub.get('/') do |_env|
|
||||
[200,
|
||||
{ 'Metadata-Flavor' => 'Google' },
|
||||
'']
|
||||
end
|
||||
end # GCE detected
|
||||
stub = stub_request(:get, 'http://169.254.169.254')
|
||||
.to_return(status: 200,
|
||||
headers: { 'Metadata-Flavor' => 'Google' })
|
||||
Dir.mktmpdir do |dir|
|
||||
ENV.delete(@var_name) unless ENV[@var_name].nil? # no env var
|
||||
ENV['HOME'] = dir # no config present in this tmp dir
|
||||
c = Faraday.new do |b|
|
||||
b.adapter(:test, stubs)
|
||||
end
|
||||
creds = Google::Auth.get_application_default(
|
||||
@scope,
|
||||
connection: c)
|
||||
creds = Google::Auth.get_application_default(@scope, options)
|
||||
expect(creds).to_not be_nil
|
||||
end
|
||||
stubs.verify_stubbed_calls
|
||||
expect(stub).to have_been_requested
|
||||
end
|
||||
|
||||
it 'succeeds with system default file' do
|
||||
|
@ -148,7 +137,8 @@ describe '#get_application_default' do
|
|||
key_path = File.join('/etc/google/auth/', CREDENTIALS_FILE_NAME)
|
||||
FileUtils.mkdir_p(File.dirname(key_path))
|
||||
File.write(key_path, cred_json_text)
|
||||
expect(Google::Auth.get_application_default(@scope)).to_not be_nil
|
||||
expect(Google::Auth.get_application_default(@scope, options))
|
||||
.to_not be_nil
|
||||
File.delete(key_path)
|
||||
end
|
||||
end
|
||||
|
@ -161,7 +151,8 @@ describe '#get_application_default' do
|
|||
ENV[CLIENT_SECRET_VAR] = cred_json[:client_secret]
|
||||
ENV[REFRESH_TOKEN_VAR] = cred_json[:refresh_token]
|
||||
ENV[ACCOUNT_TYPE_VAR] = cred_json[:type]
|
||||
expect(Google::Auth.get_application_default(@scope)).to_not be_nil
|
||||
expect(Google::Auth.get_application_default(@scope, options))
|
||||
.to_not be_nil
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -225,7 +216,7 @@ describe '#get_application_default' do
|
|||
File.write(key_path, cred_json_text)
|
||||
ENV[@var_name] = key_path
|
||||
blk = proc do
|
||||
Google::Auth.get_application_default(@scope)
|
||||
Google::Auth.get_application_default(@scope, options)
|
||||
end
|
||||
expect(&blk).to raise_error RuntimeError
|
||||
end
|
||||
|
@ -239,7 +230,7 @@ describe '#get_application_default' do
|
|||
File.write(key_path, cred_json_text)
|
||||
ENV['HOME'] = dir
|
||||
blk = proc do
|
||||
Google::Auth.get_application_default(@scope)
|
||||
Google::Auth.get_application_default(@scope, options)
|
||||
end
|
||||
expect(&blk).to raise_error RuntimeError
|
||||
end
|
||||
|
@ -249,7 +240,7 @@ describe '#get_application_default' do
|
|||
ENV[PRIVATE_KEY_VAR] = cred_json[:private_key]
|
||||
ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
|
||||
blk = proc do
|
||||
Google::Auth.get_application_default(@scope)
|
||||
Google::Auth.get_application_default(@scope, options)
|
||||
end
|
||||
expect(&blk).to raise_error RuntimeError
|
||||
end
|
||||
|
|
|
@ -129,16 +129,21 @@ describe Google::Auth::ServiceAccountCredentials do
|
|||
|
||||
def make_auth_stubs(opts = {})
|
||||
access_token = opts[:access_token] || ''
|
||||
Faraday::Adapter::Test::Stubs.new do |stub|
|
||||
stub.post('/oauth2/v3/token') do |env|
|
||||
params = Addressable::URI.form_unencode(env[:body])
|
||||
_claim, _header = JWT.decode(params.assoc('assertion').last,
|
||||
@key.public_key)
|
||||
want = ['grant_type', 'urn:ietf:params:oauth:grant-type:jwt-bearer']
|
||||
expect(params.assoc('grant_type')).to eq(want)
|
||||
build_access_token_json(access_token)
|
||||
end
|
||||
body = MultiJson.dump('access_token' => access_token,
|
||||
'token_type' => 'Bearer',
|
||||
'expires_in' => 3600)
|
||||
blk = proc do |request|
|
||||
params = Addressable::URI.form_unencode(request.body)
|
||||
_claim, _header = JWT.decode(params.assoc('assertion').last,
|
||||
@key.public_key)
|
||||
end
|
||||
stub_request(:post, 'https://www.googleapis.com/oauth2/v3/token')
|
||||
.with(body: hash_including(
|
||||
'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer'),
|
||||
&blk)
|
||||
.to_return(body: body,
|
||||
status: 200,
|
||||
headers: { 'Content-Type' => 'application/json' })
|
||||
end
|
||||
|
||||
def cred_json_text
|
||||
|
|
|
@ -50,16 +50,21 @@ describe Signet::OAuth2::Client do
|
|||
|
||||
def make_auth_stubs(opts)
|
||||
access_token = opts[:access_token] || ''
|
||||
Faraday::Adapter::Test::Stubs.new do |stub|
|
||||
stub.post('/o/oauth2/token') do |env|
|
||||
params = Addressable::URI.form_unencode(env[:body])
|
||||
_claim, _header = JWT.decode(params.assoc('assertion').last,
|
||||
@key.public_key)
|
||||
want = ['grant_type', 'urn:ietf:params:oauth:grant-type:jwt-bearer']
|
||||
expect(params.assoc('grant_type')).to eq(want)
|
||||
build_access_token_json(access_token)
|
||||
end
|
||||
body = MultiJson.dump('access_token' => access_token,
|
||||
'token_type' => 'Bearer',
|
||||
'expires_in' => 3600)
|
||||
blk = proc do |request|
|
||||
params = Addressable::URI.form_unencode(request.body)
|
||||
_claim, _header = JWT.decode(params.assoc('assertion').last,
|
||||
@key.public_key)
|
||||
end
|
||||
stub_request(:post, 'https://accounts.google.com/o/oauth2/token')
|
||||
.with(body: hash_including(
|
||||
'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer'),
|
||||
&blk)
|
||||
.to_return(body: body,
|
||||
status: 200,
|
||||
headers: { 'Content-Type' => 'application/json' })
|
||||
end
|
||||
|
||||
it_behaves_like 'apply/apply! are OK'
|
||||
|
|
|
@ -65,14 +65,14 @@ describe Google::Auth::UserRefreshCredentials do
|
|||
|
||||
def make_auth_stubs(opts = {})
|
||||
access_token = opts[:access_token] || ''
|
||||
Faraday::Adapter::Test::Stubs.new do |stub|
|
||||
stub.post('/oauth2/v3/token') do |env|
|
||||
params = Addressable::URI.form_unencode(env[:body])
|
||||
want = %w(grant_type refresh_token)
|
||||
expect(params.assoc('grant_type')).to eq(want)
|
||||
build_access_token_json(access_token)
|
||||
end
|
||||
end
|
||||
body = MultiJson.dump('access_token' => access_token,
|
||||
'token_type' => 'Bearer',
|
||||
'expires_in' => 3600)
|
||||
stub_request(:post, 'https://www.googleapis.com/oauth2/v3/token')
|
||||
.with(body: hash_including('grant_type' => 'refresh_token'))
|
||||
.to_return(body: body,
|
||||
status: 200,
|
||||
headers: { 'Content-Type' => 'application/json' })
|
||||
end
|
||||
|
||||
def cred_json_text(missing = nil)
|
||||
|
@ -244,70 +244,50 @@ describe Google::Auth::UserRefreshCredentials do
|
|||
end
|
||||
|
||||
describe 'when revoking a refresh token' do
|
||||
let(:stubs) do
|
||||
Faraday::Adapter::Test::Stubs.new do |stub|
|
||||
stub.get('/o/oauth2/revoke') do |env|
|
||||
expect(env.params['token']).to eql 'refreshtoken'
|
||||
[200]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
let(:connection) do
|
||||
Faraday.new do |c|
|
||||
c.adapter(:test, stubs)
|
||||
end
|
||||
let(:stub) do
|
||||
stub_request(:get, 'https://accounts.google.com/o/oauth2/revoke' \
|
||||
'?token=refreshtoken')
|
||||
.to_return(status: 200,
|
||||
headers: { 'Content-Type' => 'application/json' })
|
||||
end
|
||||
|
||||
before(:example) do
|
||||
@client.revoke!(connection: connection)
|
||||
stub
|
||||
@client.revoke!
|
||||
end
|
||||
|
||||
it_behaves_like 'revoked token'
|
||||
end
|
||||
|
||||
describe 'when revoking an access token' do
|
||||
let(:stubs) do
|
||||
Faraday::Adapter::Test::Stubs.new do |stub|
|
||||
stub.get('/o/oauth2/revoke') do |env|
|
||||
expect(env.params['token']).to eql 'accesstoken'
|
||||
[200]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
let(:connection) do
|
||||
Faraday.new do |c|
|
||||
c.adapter(:test, stubs)
|
||||
end
|
||||
let(:stub) do
|
||||
stub_request(:get, 'https://accounts.google.com/o/oauth2/revoke' \
|
||||
'?token=accesstoken')
|
||||
.to_return(status: 200,
|
||||
headers: { 'Content-Type' => 'application/json' })
|
||||
end
|
||||
|
||||
before(:example) do
|
||||
stub
|
||||
@client.refresh_token = nil
|
||||
@client.access_token = 'accesstoken'
|
||||
@client.revoke!(connection: connection)
|
||||
@client.revoke!
|
||||
end
|
||||
|
||||
it_behaves_like 'revoked token'
|
||||
end
|
||||
|
||||
describe 'when revoking an invalid token' do
|
||||
let(:stubs) do
|
||||
Faraday::Adapter::Test::Stubs.new do |stub|
|
||||
stub.get('/o/oauth2/revoke') do |_env|
|
||||
[400]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
let(:connection) do
|
||||
Faraday.new do |c|
|
||||
c.adapter(:test, stubs)
|
||||
end
|
||||
let(:stub) do
|
||||
stub_request(:get, 'https://accounts.google.com/o/oauth2/revoke' \
|
||||
'?token=refreshtoken')
|
||||
.to_return(status: 400,
|
||||
headers: { 'Content-Type' => 'application/json' })
|
||||
end
|
||||
|
||||
it 'raises an authorization error' do
|
||||
expect { @client.revoke!(connection: connection) }.to raise_error(
|
||||
stub
|
||||
expect { @client.revoke! }.to raise_error(
|
||||
Signet::AuthorizationError)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -39,7 +39,10 @@ $LOAD_PATH.uniq!
|
|||
require 'simplecov'
|
||||
require 'coveralls'
|
||||
|
||||
SimpleCov.formatter = Coveralls::SimpleCov::Formatter
|
||||
SimpleCov.formatters = [
|
||||
Coveralls::SimpleCov::Formatter,
|
||||
SimpleCov::Formatter::HTMLFormatter
|
||||
]
|
||||
SimpleCov.start
|
||||
|
||||
require 'faraday'
|
||||
|
|
Loading…
Reference in New Issue