From b574bc2a986ac5008e2a7b13a83cb32742888f43 Mon Sep 17 00:00:00 2001 From: Craig Citro Date: Tue, 17 Feb 2015 08:40:44 -0800 Subject: [PATCH] Fall back to using an access_token for revocation. According to the [OAuth2 docs](https://developers.google.com/accounts/docs/OAuth2WebServer#tokenrevoke), we can use either the refresh token or access token when revoking a token. If we've lost the refresh token for some reason, we should fall back to revoking via access token. (Note that if the access token has expired, this will still raise, which is the correct behavior.) Fixes #132. --- oauth2client/client.py | 6 +++--- tests/test_oauth2client.py | 8 ++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/oauth2client/client.py b/oauth2client/client.py index 0f1a41b98..f3ec3a344 100644 --- a/oauth2client/client.py +++ b/oauth2client/client.py @@ -811,16 +811,16 @@ def _do_refresh_request(self, http_request): raise AccessTokenRefreshError(error_msg) def _revoke(self, http_request): - """Revokes the refresh_token and deletes the store if available. + """Revokes this credential and deletes the stored copy (if it exists). Args: http_request: callable, a callable that matches the method signature of httplib2.Http.request, used to make the revoke request. """ - self._do_revoke(http_request, self.refresh_token) + self._do_revoke(http_request, self.refresh_token or self.access_token) def _do_revoke(self, http_request, token): - """Revokes the credentials and deletes the store if available. + """Revokes this credential and deletes the stored copy (if it exists). Args: http_request: callable, a callable that matches the method signature of diff --git a/tests/test_oauth2client.py b/tests/test_oauth2client.py index fb44de477..ad51370d5 100644 --- a/tests/test_oauth2client.py +++ b/tests/test_oauth2client.py @@ -560,6 +560,14 @@ def test_token_revoke_failure(self): self, '400', revoke_raise=True, valid_bool_value=False, token_attr='refresh_token') + def test_token_revoke_fallback(self): + original_credentials = self.credentials.to_json() + self.credentials.refresh_token = None + _token_revoke_test_helper( + self, '200', revoke_raise=False, + valid_bool_value=True, token_attr='access_token') + self.credentials = self.credentials.from_json(original_credentials) + def test_non_401_error_response(self): http = HttpMockSequence([ ({'status': '400'}, b''),