Merge pull request #54 from sqrrrl/0.5-dev

Prep for 0.5 release
This commit is contained in:
Tim Emiola 2015-12-11 21:49:03 -08:00
commit c75d7398ff
15 changed files with 244 additions and 244 deletions

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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'

View File

@ -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

View File

@ -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'