Auto-refresh OAuth 2 tokens & retry request on 401 response
This commit is contained in:
parent
1cf7975319
commit
3d157007f6
|
@ -5,6 +5,8 @@
|
|||
* :api_method in request can no longer be a string
|
||||
* Deprecated ResumableUpload.send_* methods.
|
||||
* Reduce memory utilization when uploading large files
|
||||
* Automatic refresh of OAuth 2 credentials & retry of request when 401 errors
|
||||
are returned
|
||||
* Simplify internal request processing.
|
||||
|
||||
# 0.4.7
|
||||
|
|
|
@ -540,6 +540,15 @@ module Google
|
|||
request.authorization = options[:authorization] || self.authorization unless options[:authenticated] == false
|
||||
|
||||
result = request.send(connection)
|
||||
if result.status == 401 && authorization.respond_to?(:refresh_token)
|
||||
begin
|
||||
authorization.fetch_access_token!
|
||||
result = request.send(connection)
|
||||
rescue Signet::AuthorizationError
|
||||
# Ignore since we want the original error
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
require 'jwt'
|
||||
require 'signet/oauth_2/client'
|
||||
require 'delegate'
|
||||
|
||||
module Google
|
||||
class APIClient
|
||||
|
@ -117,7 +118,21 @@ module Google
|
|||
authorization.grant_type = 'urn:ietf:params:oauth:grant-type:jwt-bearer'
|
||||
authorization.extension_parameters = { :assertion => assertion }
|
||||
authorization.fetch_access_token!(options)
|
||||
return authorization
|
||||
return JWTAuthorization.new(authorization, self, person)
|
||||
end
|
||||
end
|
||||
|
||||
class JWTAuthorization < DelegateClass(Signet::OAuth2::Client)
|
||||
def initialize(authorization, asserter, person = nil)
|
||||
@asserter = asserter
|
||||
@person = person
|
||||
super(authorization)
|
||||
end
|
||||
|
||||
def fetch_access_token!(options={})
|
||||
new_authorization = @asserter.authorize(@person, options)
|
||||
__setobj__(new_authorization)
|
||||
self
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -52,5 +52,39 @@ describe Google::APIClient::JWTAsserter do
|
|||
auth.access_token.should == "1/abcdef1234567890"
|
||||
conn.verify
|
||||
end
|
||||
|
||||
it 'should be refreshable' do
|
||||
conn = stub_connection do |stub|
|
||||
stub.post('/o/oauth2/token') do |env|
|
||||
params = Addressable::URI.form_unencode(env[:body])
|
||||
JWT.decode(params.assoc("assertion").last, @key.public_key)
|
||||
params.assoc("grant_type").should == ['grant_type','urn:ietf:params:oauth:grant-type:jwt-bearer']
|
||||
[200, {}, '{
|
||||
"access_token" : "1/abcdef1234567890",
|
||||
"token_type" : "Bearer",
|
||||
"expires_in" : 3600
|
||||
}']
|
||||
end
|
||||
stub.post('/o/oauth2/token') do |env|
|
||||
params = Addressable::URI.form_unencode(env[:body])
|
||||
JWT.decode(params.assoc("assertion").last, @key.public_key)
|
||||
params.assoc("grant_type").should == ['grant_type','urn:ietf:params:oauth:grant-type:jwt-bearer']
|
||||
[200, {}, '{
|
||||
"access_token" : "1/0987654321fedcba",
|
||||
"token_type" : "Bearer",
|
||||
"expires_in" : 3600
|
||||
}']
|
||||
end
|
||||
end
|
||||
asserter = Google::APIClient::JWTAsserter.new('client1', 'scope1 scope2', @key)
|
||||
auth = asserter.authorize(nil, { :connection => conn })
|
||||
auth.should_not == nil?
|
||||
auth.access_token.should == "1/abcdef1234567890"
|
||||
|
||||
auth.fetch_access_token!(:connection => conn)
|
||||
auth.access_token.should == "1/0987654321fedcba"
|
||||
|
||||
conn.verify
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue