Store original encoded and signed identity JWT in OAuth2Credentials (#680)

This commit is contained in:
Clancy Childs
2016-11-28 19:09:30 +00:00
committed by Jon Wayne Parrott
parent 2da8ccde3f
commit f7f656d6aa
2 changed files with 15 additions and 4 deletions

View File

@@ -451,7 +451,7 @@ class OAuth2Credentials(Credentials):
def __init__(self, access_token, client_id, client_secret, refresh_token, def __init__(self, access_token, client_id, client_secret, refresh_token,
token_expiry, token_uri, user_agent, revoke_uri=None, token_expiry, token_uri, user_agent, revoke_uri=None,
id_token=None, token_response=None, scopes=None, id_token=None, token_response=None, scopes=None,
token_info_uri=None): token_info_uri=None, id_token_jwt=None):
"""Create an instance of OAuth2Credentials. """Create an instance of OAuth2Credentials.
This constructor is not usually called by the user, instead This constructor is not usually called by the user, instead
@@ -474,8 +474,11 @@ class OAuth2Credentials(Credentials):
because some providers (e.g. wordpress.com) include because some providers (e.g. wordpress.com) include
extra fields that clients may want. extra fields that clients may want.
scopes: list, authorized scopes for these credentials. scopes: list, authorized scopes for these credentials.
token_info_uri: string, the URI for the token info endpoint. Defaults token_info_uri: string, the URI for the token info endpoint.
to None; scopes can not be refreshed if this is None. Defaults to None; scopes can not be refreshed if
this is None.
id_token_jwt: string, the encoded and signed identity JWT. The
decoded version of this is stored in id_token.
Notes: Notes:
store: callable, A callable that when passed a Credential store: callable, A callable that when passed a Credential
@@ -493,6 +496,7 @@ class OAuth2Credentials(Credentials):
self.user_agent = user_agent self.user_agent = user_agent
self.revoke_uri = revoke_uri self.revoke_uri = revoke_uri
self.id_token = id_token self.id_token = id_token
self.id_token_jwt = id_token_jwt
self.token_response = token_response self.token_response = token_response
self.scopes = set(_helpers.string_to_scopes(scopes or [])) self.scopes = set(_helpers.string_to_scopes(scopes or []))
self.token_info_uri = token_info_uri self.token_info_uri = token_info_uri
@@ -621,6 +625,7 @@ class OAuth2Credentials(Credentials):
data['user_agent'], data['user_agent'],
revoke_uri=data.get('revoke_uri', None), revoke_uri=data.get('revoke_uri', None),
id_token=data.get('id_token', None), id_token=data.get('id_token', None),
id_token_jwt=data.get('id_token_jwt', None),
token_response=data.get('token_response', None), token_response=data.get('token_response', None),
scopes=data.get('scopes', None), scopes=data.get('scopes', None),
token_info_uri=data.get('token_info_uri', None)) token_info_uri=data.get('token_info_uri', None))
@@ -786,8 +791,10 @@ class OAuth2Credentials(Credentials):
self.token_expiry = None self.token_expiry = None
if 'id_token' in d: if 'id_token' in d:
self.id_token = _extract_id_token(d['id_token']) self.id_token = _extract_id_token(d['id_token'])
self.id_token_jwt = d['id_token']
else: else:
self.id_token = None self.id_token = None
self.id_token_jwt = None
# On temporary refresh errors, the user does not actually have to # On temporary refresh errors, the user does not actually have to
# re-authorize, so we unflag here. # re-authorize, so we unflag here.
self.invalid = False self.invalid = False
@@ -2059,15 +2066,17 @@ class OAuth2WebServerFlow(Flow):
token_expiry = delta + _UTCNOW() token_expiry = delta + _UTCNOW()
extracted_id_token = None extracted_id_token = None
id_token_jwt = None
if 'id_token' in d: if 'id_token' in d:
extracted_id_token = _extract_id_token(d['id_token']) extracted_id_token = _extract_id_token(d['id_token'])
id_token_jwt = d['id_token']
logger.info('Successfully retrieved access token') logger.info('Successfully retrieved access token')
return OAuth2Credentials( return OAuth2Credentials(
access_token, self.client_id, self.client_secret, access_token, self.client_id, self.client_secret,
refresh_token, token_expiry, self.token_uri, self.user_agent, refresh_token, token_expiry, self.token_uri, self.user_agent,
revoke_uri=self.revoke_uri, id_token=extracted_id_token, revoke_uri=self.revoke_uri, id_token=extracted_id_token,
token_response=d, scopes=self.scope, id_token_jwt=id_token_jwt, token_response=d, scopes=self.scope,
token_info_uri=self.token_info_uri) token_info_uri=self.token_info_uri)
else: else:
logger.info('Failed to retrieve access token: %s', content) logger.info('Failed to retrieve access token: %s', content)

View File

@@ -1479,6 +1479,7 @@ class BasicCredentialsTests(unittest.TestCase):
http = self.credentials.authorize(http) http = self.credentials.authorize(http)
resp, content = transport.request(http, 'http://example.com') resp, content = transport.request(http, 'http://example.com')
self.assertEqual(self.credentials.id_token, body) self.assertEqual(self.credentials.id_token, body)
self.assertEqual(self.credentials.id_token_jwt, jwt.decode())
class AccessTokenCredentialsTests(unittest.TestCase): class AccessTokenCredentialsTests(unittest.TestCase):
@@ -2085,6 +2086,7 @@ class OAuth2WebServerFlowTest(unittest.TestCase):
credentials = self.flow.step2_exchange(code='some random code', credentials = self.flow.step2_exchange(code='some random code',
http=http) http=http)
self.assertEqual(credentials.id_token, body) self.assertEqual(credentials.id_token, body)
self.assertEqual(credentials.id_token_jwt, jwt.decode())
class FlowFromCachedClientsecrets(unittest.TestCase): class FlowFromCachedClientsecrets(unittest.TestCase):