diff --git a/lib/googleauth/compute_engine.rb b/lib/googleauth/compute_engine.rb index 9b14e0a4..06031101 100644 --- a/lib/googleauth/compute_engine.rb +++ b/lib/googleauth/compute_engine.rb @@ -88,16 +88,20 @@ def on_gce?(options = {}) def fetch_access_token(options = {}) c = options[:connection] || Faraday.default_connection c.headers = { 'Metadata-Flavor' => 'Google' } - resp = c.get(COMPUTE_AUTH_TOKEN_URI) - case resp.status - when 200 - Signet::OAuth2.parse_credentials(resp.body, - resp.headers['content-type']) - when 404 - raise(Signet::AuthorizationError, NO_METADATA_SERVER_ERROR) - else - msg = "Unexpected error code #{resp.status}" + UNEXPECTED_ERROR_SUFFIX - raise(Signet::AuthorizationError, msg) + + retry_with_error do + resp = c.get(COMPUTE_AUTH_TOKEN_URI) + case resp.status + when 200 + Signet::OAuth2.parse_credentials(resp.body, + resp.headers['content-type']) + when 404 + raise(Signet::AuthorizationError, NO_METADATA_SERVER_ERROR) + else + msg = "Unexpected error code #{resp.status}" \ + "#{UNEXPECTED_ERROR_SUFFIX}" + raise(Signet::AuthorizationError, msg) + end end end end diff --git a/lib/googleauth/signet.rb b/lib/googleauth/signet.rb index f7433ff7..02927aa2 100644 --- a/lib/googleauth/signet.rb +++ b/lib/googleauth/signet.rb @@ -77,6 +77,27 @@ def notify_refresh_listeners block.call(self) end end + + def retry_with_error(max_retry_count = 5) + retry_count = 0 + + begin + yield + rescue => e + if e.is_a?(Signet::AuthorizationError) || e.is_a?(Signet::ParseError) + raise e + end + + if retry_count < max_retry_count + retry_count += 1 + sleep retry_count * 0.3 + retry + else + msg = "Unexpected error: #{e.inspect}" + raise(Signet::AuthorizationError, msg) + end + end + end end end end diff --git a/lib/googleauth/user_refresh.rb b/lib/googleauth/user_refresh.rb index 14c19906..65d310f7 100644 --- a/lib/googleauth/user_refresh.rb +++ b/lib/googleauth/user_refresh.rb @@ -92,15 +92,18 @@ def initialize(options = {}) # Revokes the credential def revoke!(options = {}) c = options[:connection] || Faraday.default_connection - resp = c.get(REVOKE_TOKEN_URI, token: refresh_token || access_token) - case resp.status - when 200 - self.access_token = nil - self.refresh_token = nil - self.expires_at = 0 - else - raise(Signet::AuthorizationError, - "Unexpected error code #{resp.status}") + + retry_with_error do + resp = c.get(REVOKE_TOKEN_URI, token: refresh_token || access_token) + case resp.status + when 200 + self.access_token = nil + self.refresh_token = nil + self.expires_at = 0 + else + raise(Signet::AuthorizationError, + "Unexpected error code #{resp.status}") + end end end diff --git a/spec/googleauth/compute_engine_spec.rb b/spec/googleauth/compute_engine_spec.rb index c98fec29..f12d0ef9 100644 --- a/spec/googleauth/compute_engine_spec.rb +++ b/spec/googleauth/compute_engine_spec.rb @@ -77,6 +77,20 @@ def make_auth_stubs(opts = {}) .to raise_error Signet::AuthorizationError expect(stub).to have_been_requested end + + it 'should fail with Signet::AuthorizationError if request times out' do + allow_any_instance_of(Faraday::Connection).to receive(:get) + .and_raise(Faraday::TimeoutError) + expect { @client.fetch_access_token! } + .to raise_error Signet::AuthorizationError + end + + it 'should fail with Signet::AuthorizationError if request fails' do + allow_any_instance_of(Faraday::Connection).to receive(:get) + .and_raise(Faraday::ConnectionFailed, nil) + expect { @client.fetch_access_token! } + .to raise_error Signet::AuthorizationError + end end end diff --git a/spec/googleauth/user_refresh_spec.rb b/spec/googleauth/user_refresh_spec.rb index d80f6ba0..cc81476a 100644 --- a/spec/googleauth/user_refresh_spec.rb +++ b/spec/googleauth/user_refresh_spec.rb @@ -293,4 +293,20 @@ def cred_json_text(missing = nil) ) end end + + describe 'when erros occured with request' do + it 'should fail with Signet::AuthorizationError if request times out' do + allow_any_instance_of(Faraday::Connection).to receive(:get) + .and_raise(Faraday::TimeoutError) + expect { @client.revoke! } + .to raise_error Signet::AuthorizationError + end + + it 'should fail with Signet::AuthorizationError if request fails' do + allow_any_instance_of(Faraday::Connection).to receive(:get) + .and_raise(Faraday::ConnectionFailed, nil) + expect { @client.revoke! } + .to raise_error Signet::AuthorizationError + end + end end