diff --git a/oauth2client/client.py b/oauth2client/client.py index 704c61034..0a1aff9a0 100644 --- a/oauth2client/client.py +++ b/oauth2client/client.py @@ -836,6 +836,10 @@ def _do_revoke(self, http, token): token_revoke_uri = _helpers.update_query_params( self.revoke_uri, query_params) resp, content = transport.request(http, token_revoke_uri) + if resp.status == http_client.METHOD_NOT_ALLOWED: + body = urllib.parse.urlencode(query_params) + resp, content = transport.request(http, token_revoke_uri, + method='POST', body=body) if resp.status == http_client.OK: self.invalid = True else: diff --git a/tests/test_client.py b/tests/test_client.py index a3268ba84..786b818ad 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -819,8 +819,8 @@ def locked_delete(self): self.delete_called = True -def _token_revoke_test_helper(testcase, status, revoke_raise, - valid_bool_value, token_attr): +def _token_revoke_test_helper(testcase, revoke_raise, valid_bool_value, + token_attr, http_mock): current_store = getattr(testcase.credentials, 'store', None) dummy_store = DummyDeleteStorage() @@ -834,12 +834,11 @@ def do_revoke_stub(http, token): return actual_do_revoke(http, token) testcase.credentials._do_revoke = do_revoke_stub - http = http_mock.HttpMock(headers={'status': status}) if revoke_raise: testcase.assertRaises(client.TokenRevokeError, - testcase.credentials.revoke, http) + testcase.credentials.revoke, http_mock) else: - testcase.credentials.revoke(http) + testcase.credentials.revoke(http_mock) testcase.assertEqual(getattr(testcase.credentials, token_attr), testcase.token_from_revoke) @@ -922,21 +921,38 @@ def test_token_refresh_failure(self): self.assertEqual(None, self.credentials.token_response) def test_token_revoke_success(self): + http = http_mock.HttpMock(headers={'status': http_client.OK}) _token_revoke_test_helper( - self, '200', revoke_raise=False, - valid_bool_value=True, token_attr='refresh_token') + self, revoke_raise=False, valid_bool_value=True, + token_attr='refresh_token', http_mock=http) def test_token_revoke_failure(self): + http = http_mock.HttpMock(headers={'status': http_client.BAD_REQUEST}) _token_revoke_test_helper( - self, '400', revoke_raise=True, - valid_bool_value=False, token_attr='refresh_token') + self, revoke_raise=True, valid_bool_value=False, + token_attr='refresh_token', http_mock=http) def test_token_revoke_fallback(self): original_credentials = self.credentials.to_json() self.credentials.refresh_token = None + + http = http_mock.HttpMock(headers={'status': http_client.OK}) + _token_revoke_test_helper( + self, revoke_raise=False, valid_bool_value=True, + token_attr='access_token', http_mock=http) + self.credentials = self.credentials.from_json(original_credentials) + + def test_token_revoke_405(self): + original_credentials = self.credentials.to_json() + self.credentials.refresh_token = None + + http = http_mock.HttpMockSequence([ + ({'status': http_client.METHOD_NOT_ALLOWED}, b''), + ({'status': http_client.OK}, b''), + ]) _token_revoke_test_helper( - self, '200', revoke_raise=False, - valid_bool_value=True, token_attr='access_token') + self, revoke_raise=False, valid_bool_value=True, + token_attr='access_token', http_mock=http) self.credentials = self.credentials.from_json(original_credentials) def test_non_401_error_response(self): @@ -1483,14 +1499,16 @@ def test_token_refresh_success(self): resp, content = transport.request(http, 'http://example.com') def test_token_revoke_success(self): + http = http_mock.HttpMock(headers={'status': http_client.OK}) _token_revoke_test_helper( - self, '200', revoke_raise=False, - valid_bool_value=True, token_attr='access_token') + self, revoke_raise=False, valid_bool_value=True, + token_attr='access_token', http_mock=http) def test_token_revoke_failure(self): + http = http_mock.HttpMock(headers={'status': http_client.BAD_REQUEST}) _token_revoke_test_helper( - self, '400', revoke_raise=True, - valid_bool_value=False, token_attr='access_token') + self, revoke_raise=True, valid_bool_value=False, + token_attr='access_token', http_mock=http) def test_non_401_error_response(self): http = http_mock.HttpMock(headers={'status': http_client.BAD_REQUEST}) @@ -1543,14 +1561,16 @@ def test_assertion_refresh(self): self.assertEqual(b'Bearer 1/3w', content[b'Authorization']) def test_token_revoke_success(self): + http = http_mock.HttpMock(headers={'status': http_client.OK}) _token_revoke_test_helper( - self, '200', revoke_raise=False, - valid_bool_value=True, token_attr='access_token') + self, revoke_raise=False, valid_bool_value=True, + token_attr='access_token', http_mock=http) def test_token_revoke_failure(self): + http = http_mock.HttpMock(headers={'status': http_client.BAD_REQUEST}) _token_revoke_test_helper( - self, '400', revoke_raise=True, - valid_bool_value=False, token_attr='access_token') + self, revoke_raise=True, valid_bool_value=False, + token_attr='access_token', http_mock=http) def test_sign_blob_abstract(self): credentials = client.AssertionCredentials(None)