Fix an issue with non-dict values in flow exchange.
The OAuth2 for Devices implementation picked up an incidental change that failed to treat dicts and dict-like objects the same way. This is particularly painful in environments like App Engine, where `self.request.params` is a common dict-like value to pass in. This restores the previous behavior, and adds a test.
This commit is contained in:
@@ -1767,10 +1767,10 @@ class OAuth2WebServerFlow(Flow):
|
||||
|
||||
Args:
|
||||
|
||||
code: string, dict or None. For a non-device flow, this is
|
||||
either the response code as a string, or a dictionary of
|
||||
query parameters to the redirect_uri. For a device flow,
|
||||
this should be None.
|
||||
code: string, a dict-like object, or None. For a non-device
|
||||
flow, this is either the response code as a string, or a
|
||||
dictionary of query parameters to the redirect_uri. For a
|
||||
device flow, this should be None.
|
||||
http: httplib2.Http, optional http instance to use when fetching
|
||||
credentials.
|
||||
device_flow_info: DeviceFlowInfo, return value from step1 in the
|
||||
@@ -1793,7 +1793,7 @@ class OAuth2WebServerFlow(Flow):
|
||||
|
||||
if code is None:
|
||||
code = device_flow_info.device_code
|
||||
elif isinstance(code, dict):
|
||||
elif not isinstance(code, basestring):
|
||||
if 'code' not in code:
|
||||
raise FlowExchangeError(code.get(
|
||||
'error', 'No code was supplied in the query parameters.'))
|
||||
|
||||
@@ -90,6 +90,7 @@ class HttpMockSequence(object):
|
||||
"""
|
||||
self._iterable = iterable
|
||||
self.follow_redirects = True
|
||||
self.requests = []
|
||||
|
||||
def request(self, uri,
|
||||
method='GET',
|
||||
@@ -98,6 +99,7 @@ class HttpMockSequence(object):
|
||||
redirections=1,
|
||||
connection_type=None):
|
||||
resp, content = self._iterable.pop(0)
|
||||
self.requests.append({'uri': uri, 'body': body, 'headers': headers})
|
||||
if content == 'echo_request_headers':
|
||||
content = headers
|
||||
elif content == 'echo_request_headers_as_json':
|
||||
|
||||
@@ -875,6 +875,34 @@ class OAuth2WebServerFlowTest(unittest.TestCase):
|
||||
self.assertEqual('8xLOxBtZp8', credentials.refresh_token)
|
||||
self.assertEqual('dummy_revoke_uri', credentials.revoke_uri)
|
||||
|
||||
def test_exchange_dictlike(self):
|
||||
class FakeDict(object):
|
||||
def __init__(self, d):
|
||||
self.d = d
|
||||
|
||||
def __getitem__(self, name):
|
||||
return self.d[name]
|
||||
|
||||
def __contains__(self, name):
|
||||
return name in self.d
|
||||
|
||||
code = 'some random code'
|
||||
not_a_dict = FakeDict({'code': code})
|
||||
http = HttpMockSequence([
|
||||
({'status': '200'},
|
||||
"""{ "access_token":"SlAV32hkKG",
|
||||
"expires_in":3600,
|
||||
"refresh_token":"8xLOxBtZp8" }"""),
|
||||
])
|
||||
|
||||
credentials = self.flow.step2_exchange(not_a_dict, http=http)
|
||||
self.assertEqual('SlAV32hkKG', credentials.access_token)
|
||||
self.assertNotEqual(None, credentials.token_expiry)
|
||||
self.assertEqual('8xLOxBtZp8', credentials.refresh_token)
|
||||
self.assertEqual('dummy_revoke_uri', credentials.revoke_uri)
|
||||
request_code = urlparse.parse_qs(http.requests[0]['body'])['code'][0]
|
||||
self.assertEqual(code, request_code)
|
||||
|
||||
def test_urlencoded_exchange_success(self):
|
||||
http = HttpMockSequence([
|
||||
({'status': '200'}, 'access_token=SlAV32hkKG&expires_in=3600'),
|
||||
|
||||
Reference in New Issue
Block a user