google-auth-library-python icon indicating copy to clipboard operation
google-auth-library-python copied to clipboard

fix: comment and uncompress data before loads

Open b3g00d opened this issue 4 years ago • 6 comments

source code:

from google.oauth2 import _id_token_async as id_token
from google.auth.transport import _aiohttp_requests as requests


class GoogleClient:
    def __init__(self, client_id):
        self.req = requests.Request()
        self.client_id = client_id

    async def verify_token(self, token):
        id_info = await id_token.verify_token(token, self.req, self.client_id)
        return id_info

import unittest
from unittest import IsolatedAsyncioTestCase


class Test(IsolatedAsyncioTestCase):

    async def test_error_on_fetch_cert(self):
        g_c = GoogleClient("test")
        await g_c.verify_token("test_token")


if __name__ == "__main__":
    unittest.main()

It will raise error at function _fetch_certs because of the response return as a bytes array, but json.dumps(data) is trying to dumps the bytes array

ERROR: test_error_on_fetch_cert (__main__.Test)     
----------------------------------------------------------------------
Traceback (most recent call last):  
  File "/usr/lib/python3.8/unittest/async_case.py", line 65, in _callTestMethod                          
    self._callMaybeAsync(method)
  File "/usr/lib/python3.8/unittest/async_case.py", line 88, in _callMaybeAsync                          
    return self._asyncioTestLoop.run_until_complete(fut)                                              
  File "/usr/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
    return future.result()                                                                               
  File "/usr/lib/python3.8/unittest/async_case.py", line 102, in _asyncioLoopRunner
    ret = await awaitable
  File "core/connections/google_client.py", line 22, in test_error_on_fetch_cert
    await g_c.verify_token("test_token")
  File "core/connections/google_client.py", line 11, in verify_token
    id_info = await id_token.verify_token(token, self.req, self.client_id)
  File "/home/begood/.local/share/virtualenvs/BE-fy1aetm7/lib/python3.8/site-packages/google/oauth2/_id_token_async.py", line 119, in verify_token
    certs = await _fetch_certs(request, certs_url)
  File "/home/begood/.local/share/virtualenvs/BE-fy1aetm7/lib/python3.8/site-packages/google/oauth2/_id_token_async.py", line 98, in _fetch_certs
    return json.loads(json.dumps(data)) 
  File "/usr/lib/python3.8/json/__init__.py", line 231, in dumps    
    return _default_encoder.encode(obj)                                                                  
  File "/usr/lib/python3.8/json/encoder.py", line 199, in encode                                                                                                                                                   
    chunks = self.iterencode(o, _one_shot=True)   
  File "/usr/lib/python3.8/json/encoder.py", line 257, in iterencode                                                                                                                                               
    return _iterencode(o, 0)                                                                             
  File "/usr/lib/python3.8/json/encoder.py", line 179, in default                                                                                                                                                  
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type bytes is not JSON serializable

I looked into the source code, and the response.content() work as expected.

b3g00d avatar Jun 27 '21 09:06 b3g00d

Thanks for your pull request. It looks like this may be your first contribution to a Google open source project (if not, look below for help). Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

:memo: Please visit https://cla.developers.google.com/ to sign.

Once you've signed (or fixed any issues), please reply here with @googlebot I signed it! and we'll verify it.


What to do if you already signed the CLA

Individual signers
Corporate signers

ℹ️ Googlers: Go here for more info.

google-cla[bot] avatar Jun 27 '21 09:06 google-cla[bot]

@googlebot I signed it!

b3g00d avatar Jun 27 '21 10:06 b3g00d

The docstring changes look fine.

For the change to _fetch_certs, two things:

  • Is there a bug report open for which this change is a fix? If not, can you please add one.
  • We almost certainly need to make correspondng changes to tests.

@tseaver updated

b3g00d avatar Jul 29 '21 21:07 b3g00d

@b3g00d

updated

I don't see any further commits here, and I don't see a related issue.

tseaver avatar Aug 03 '21 19:08 tseaver

@b3g00d

updated

I don't see any further commits here, and I don't see a related issue.

Oh, I mean I updated the first comment, should I put it to commit message.

b3g00d avatar Aug 04 '21 11:08 b3g00d

I had the same problem, changing

    data = await response.data.read()

    return json.loads(json.dumps(data))

to

    data = await response.content()

    return json.loads(data.decode('utf-8'))

Here fixes it, this is because auth/transport/_aiohttp_requests.py's _CombinedResponse has

    @property
    def data(self):
        return self._response.content

Which never uses _is_compressed to check for compression (unlike content).

I don't know why json.loads(json.dumps(data)) was there, it seems like a bad form of decoding.

The only test for .data is here which doesn't specify if it should decompress or not, the other tests are for .content() and .raw_content().

UlisseMini avatar Jan 03 '22 01:01 UlisseMini