Repository: auth0/auth0-python (language: python)

Issue:
Getting an error coroutine 'AsyncRestClient._request_with_session' was never awaited
### Checklist

- [X] I have looked into the [Readme](https://github.com/auth0/auth0-python#readme) and [Examples](https://github.com/auth0/auth0-python/blob/master/EXAMPLES.md), and have not found a suitable solution or answer.
- [X] I have looked into the [API documentation](https://auth0-python.readthedocs.io/en/latest/) and have not found a suitable solution or answer.
- [X] I have searched the [issues](https://github.com/auth0/auth0-python/issues) and have not found a suitable solution or answer.
- [X] I have searched the [Auth0 Community](https://community.auth0.com) forums and have not found a suitable solution or answer.
- [X] I agree to the terms within the [Auth0 Code of Conduct](https://github.com/auth0/open-source-template/blob/master/CODE-OF-CONDUCT.md).

### Description

I've been noticing some errors in our logs ever since we bumped the Auth0-python lib version to 4.6.0:
```log
2023-11-21 23:42:35   File "/osiris/pkgs/osiris_api_service/providers/auth0/identity_provider_client.py", line 82, in _get_auth0_access_token
2023-11-21 23:42:35     return response["access_token"]
2023-11-21 23:42:35            ~~~~~~~~^^^^^^^^^^^^^^^^
2023-11-21 23:42:35 INFO:     169.254.1.1:28012 - "GET /organizations/5e220319-013b-****-****-2dfeb8ad7cf0/invitations HTTP/1.1" 200 OK
2023-11-21 23:42:36 TypeError: 'coroutine' object is not subscriptable
2023-11-21 23:44:42 sys:1: RuntimeWarning: coroutine 'AsyncRestClient._request_with_session' was never awaited
2023-11-21 23:44:42 RuntimeWarning: Enable tracemalloc to get the object allocation traceback
```

I don't have it captured in a test to reproduce it, but I'll share our authentication code.

### Reproduction

```python
AsyncGetToken = asyncify(authentication.GetToken)

...

    @property
    async def client(self) -> AsyncAuth0:
        """
        This property method returns an instance of AsyncAuth0. If the instance
        does not exist, it creates a new one using the domain and access
        token obtained from the _get_auth0_access_token method.
        """
        if self._client is None:
            auth0_token = await self._get_auth0_access_token()
            self._client = AsyncAuth0(self.domain, auth0_token)

        return self._client


    async def _get_auth0_access_token(self) -> str:
        """
        Performs the Auth0 authentication and returns the access token.
        """
        get_token = AsyncGetToken(self.domain, self.client_id, self.client_secret)
        response = await get_token.client_credentials_async(f"https://{self.domain}/api/v2/")

        return response["access_token"] # <--- fails here with TypeError: 'coroutine' object is not subscriptable
```

### Additional context

_No response_

### auth0-python version

4.6.0

### Python version

3.11.4


Discussion / hints:
Not sure, but I think the error is referring to this: https://github.com/auth0/auth0-python/blob/21add3471ccadc1ab1b8def3ea049a8820e644a1/auth0/rest_async.py#L87-L93

Fix patch:
diff --git a/auth0/rest_async.py b/auth0/rest_async.py
index 0581b812..0c4e2851 100644
--- a/auth0/rest_async.py
+++ b/auth0/rest_async.py
@@ -86,11 +86,11 @@ async def _request(self, *args: Any, **kwargs: Any) -> Any:
         kwargs["timeout"] = self.timeout
         if self._session is not None:
             # Request with re-usable session
-            return self._request_with_session(self.session, *args, **kwargs)
+            return await self._request_with_session(self._session, *args, **kwargs)
         else:
             # Request without re-usable session
             async with aiohttp.ClientSession() as session:
-                return self._request_with_session(session, *args, **kwargs)
+                return await self._request_with_session(session, *args, **kwargs)
 
     async def get(
         self,


Test patch:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index d839ea47..fdcd08cd 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -72,8 +72,15 @@ jobs:
           poetry self add "poetry-dynamic-versioning[plugin]"
 
       - name: Run tests
+        if: ${{ matrix.python-version != '3.7' }}
         run: |
           poetry run pytest --cov=auth0 --cov-report=term-missing:skip-covered --cov-report=xml
+
+      - name: Run tests 3.7
+        # Skip async tests in 3.7
+        if: ${{ matrix.python-version == '3.7' }}
+        run: |
+          poetry run pytest auth0/test
         # bwrap ${{ env.BUBBLEWRAP_ARGUMENTS }} bash
 
       # - name: Run lint
diff --git a/auth0/test_async/test_async_auth0.py b/auth0/test_async/test_async_auth0.py
index 46a6a765..753666b5 100644
--- a/auth0/test_async/test_async_auth0.py
+++ b/auth0/test_async/test_async_auth0.py
@@ -22,13 +22,13 @@ def callback(url, **kwargs):
     return callback, mock
 
 
-class TestAuth0(unittest.TestCase):
+class TestAuth0(unittest.IsolatedAsyncioTestCase):
     @pytest.mark.asyncio
     @aioresponses()
     async def test_get(self, mocked):
         callback, mock = get_callback()
 
-        await mocked.get(clients, callback=callback)
+        mocked.get(clients, callback=callback)
 
         auth0 = Auth0(domain="example.com", token="jwt")
 
@@ -48,8 +48,8 @@ async def test_shared_session(self, mocked):
         callback, mock = get_callback()
         callback2, mock2 = get_callback()
 
-        await mocked.get(clients, callback=callback)
-        await mocked.put(factors, callback=callback2)
+        mocked.get(clients, callback=callback)
+        mocked.put(factors, callback=callback2)
 
         async with Auth0(domain="example.com", token="jwt") as auth0:
             self.assertEqual(await auth0.clients.all_async(), payload)
diff --git a/auth0/test_async/test_async_token_verifier.py b/auth0/test_async/test_async_token_verifier.py
index 9b02a13b..7559c693 100644
--- a/auth0/test_async/test_async_token_verifier.py
+++ b/auth0/test_async/test_async_token_verifier.py
@@ -55,12 +55,12 @@ def get_pem_bytes(rsa_public_key):
     )
 
 
-class TestAsyncAsymmetricSignatureVerifier(unittest.TestCase):
+class TestAsyncAsymmetricSignatureVerifier(unittest.IsolatedAsyncioTestCase):
     @pytest.mark.asyncio
     @aioresponses()
     async def test_async_asymmetric_verifier_fetches_key(self, mocked):
         callback, mock = get_callback(200, JWKS_RESPONSE_SINGLE_KEY)
-        await mocked.get(JWKS_URI, callback=callback)
+        mocked.get(JWKS_URI, callback=callback)
 
         verifier = AsyncAsymmetricSignatureVerifier(JWKS_URI)
 
@@ -69,7 +69,7 @@ async def test_async_asymmetric_verifier_fetches_key(self, mocked):
         self.assertEqual(get_pem_bytes(key), RSA_PUB_KEY_1_PEM)
 
 
-class TestAsyncJwksFetcher(unittest.TestCase):
+class TestAsyncJwksFetcher(unittest.IsolatedAsyncioTestCase):
     @pytest.mark.asyncio
     @aioresponses()
     @unittest.mock.patch(
@@ -81,8 +81,8 @@ async def test_async_get_jwks_json_twice_on_cache_expired(
         fetcher = AsyncJwksFetcher(JWKS_URI, cache_ttl=100)
 
         callback, mock = get_callback(200, JWKS_RESPONSE_SINGLE_KEY)
-        await mocked.get(JWKS_URI, callback=callback)
-        await mocked.get(JWKS_URI, callback=callback)
+        mocked.get(JWKS_URI, callback=callback)
+        mocked.get(JWKS_URI, callback=callback)
 
         key_1 = await fetcher.get_key("test-key-1")
         expected_key_1_pem = get_pem_bytes(key_1)
@@ -119,8 +119,8 @@ async def test_async_get_jwks_json_once_on_cache_hit(self, mocked):
         fetcher = AsyncJwksFetcher(JWKS_URI, cache_ttl=1)
 
         callback, mock = get_callback(200, JWKS_RESPONSE_MULTIPLE_KEYS)
-        await mocked.get(JWKS_URI, callback=callback)
-        await mocked.get(JWKS_URI, callback=callback)
+        mocked.get(JWKS_URI, callback=callback)
+        mocked.get(JWKS_URI, callback=callback)
 
         key_1 = await fetcher.get_key("test-key-1")
         key_2 = await fetcher.get_key("test-key-2")
@@ -144,7 +144,7 @@ async def test_async_fetches_jwks_json_forced_on_cache_miss(self, mocked):
         fetcher = AsyncJwksFetcher(JWKS_URI, cache_ttl=1)
 
         callback, mock = get_callback(200, {"keys": [RSA_PUB_KEY_1_JWK]})
-        await mocked.get(JWKS_URI, callback=callback)
+        mocked.get(JWKS_URI, callback=callback)
 
         # Triggers the first call
         key_1 = await fetcher.get_key("test-key-1")
@@ -161,7 +161,7 @@ async def test_async_fetches_jwks_json_forced_on_cache_miss(self, mocked):
         self.assertEqual(mock.call_count, 1)
 
         callback, mock = get_callback(200, JWKS_RESPONSE_MULTIPLE_KEYS)
-        await mocked.get(JWKS_URI, callback=callback)
+        mocked.get(JWKS_URI, callback=callback)
 
         # Triggers the second call
         key_2 = await fetcher.get_key("test-key-2")
@@ -183,7 +183,7 @@ async def test_async_fetches_jwks_json_once_on_cache_miss(self, mocked):
         fetcher = AsyncJwksFetcher(JWKS_URI, cache_ttl=1)
 
         callback, mock = get_callback(200, JWKS_RESPONSE_SINGLE_KEY)
-        await mocked.get(JWKS_URI, callback=callback)
+        mocked.get(JWKS_URI, callback=callback)
 
         with self.assertRaises(Exception) as err:
             await fetcher.get_key("missing-key")
@@ -206,8 +206,8 @@ async def test_async_fails_to_fetch_jwks_json_after_retrying_twice(self, mocked)
         fetcher = AsyncJwksFetcher(JWKS_URI, cache_ttl=1)
 
         callback, mock = get_callback(500, {})
-        await mocked.get(JWKS_URI, callback=callback)
-        await mocked.get(JWKS_URI, callback=callback)
+        mocked.get(JWKS_URI, callback=callback)
+        mocked.get(JWKS_URI, callback=callback)
 
         with self.assertRaises(Exception) as err:
             await fetcher.get_key("id1")
@@ -225,12 +225,12 @@ async def test_async_fails_to_fetch_jwks_json_after_retrying_twice(self, mocked)
         self.assertEqual(mock.call_count, 2)
 
 
-class TestAsyncTokenVerifier(unittest.TestCase):
+class TestAsyncTokenVerifier(unittest.IsolatedAsyncioTestCase):
     @pytest.mark.asyncio
     @aioresponses()
     async def test_RS256_token_signature_passes(self, mocked):
         callback, mock = get_callback(200, {"keys": [PUBLIC_KEY]})
-        await mocked.get(JWKS_URI, callback=callback)
+        mocked.get(JWKS_URI, callback=callback)
 
         issuer = "https://tokens-test.auth0.com/"
         audience = "tokens-test-123"
@@ -261,7 +261,7 @@ async def test_RS256_token_signature_fails(self, mocked):
         callback, mock = get_callback(
             200, {"keys": [RSA_PUB_KEY_1_JWK]}
         )  # different pub key
-        await mocked.get(JWKS_URI, callback=callback)
+        mocked.get(JWKS_URI, callback=callback)
 
         issuer = "https://tokens-test.auth0.com/"
         audience = "tokens-test-123"
diff --git a/auth0/test_async/test_asyncify.py b/auth0/test_async/test_asyncify.py
index 2c0317e6..acc3f54d 100644
--- a/auth0/test_async/test_asyncify.py
+++ b/auth0/test_async/test_asyncify.py
@@ -54,12 +54,12 @@ def callback(url, **kwargs):
     return callback, mock
 
 
-class TestAsyncify(unittest.TestCase):
+class TestAsyncify(unittest.IsolatedAsyncioTestCase):
     @pytest.mark.asyncio
     @aioresponses()
     async def test_get(self, mocked):
         callback, mock = get_callback()
-        await mocked.get(clients, callback=callback)
+        mocked.get(clients, callback=callback)
         c = asyncify(Clients)(domain="example.com", token="jwt")
         self.assertEqual(await c.all_async(), payload)
         mock.assert_called_with(
@@ -74,7 +74,7 @@ async def test_get(self, mocked):
     @aioresponses()
     async def test_post(self, mocked):
         callback, mock = get_callback()
-        await mocked.post(clients, callback=callback)
+        mocked.post(clients, callback=callback)
         c = asyncify(Clients)(domain="example.com", token="jwt")
         data = {"client": 1}
         self.assertEqual(await c.create_async(data), payload)
@@ -90,7 +90,7 @@ async def test_post(self, mocked):
     @aioresponses()
     async def test_post_auth(self, mocked):
         callback, mock = get_callback()
-        await mocked.post(token, callback=callback)
+        mocked.post(token, callback=callback)
         c = asyncify(GetToken)("example.com", "cid", client_secret="clsec")
         self.assertEqual(
             await c.login_async(username="usrnm", password="pswd"), payload
@@ -116,7 +116,7 @@ async def test_post_auth(self, mocked):
     @aioresponses()
     async def test_user_info(self, mocked):
         callback, mock = get_callback()
-        await mocked.get(user_info, callback=callback)
+        mocked.get(user_info, callback=callback)
         c = asyncify(Users)(domain="example.com")
         self.assertEqual(
             await c.userinfo_async(access_token="access-token-example"), payload
@@ -133,7 +133,7 @@ async def test_user_info(self, mocked):
     @aioresponses()
     async def test_file_post(self, mocked):
         callback, mock = get_callback()
-        await mocked.post(users_imports, callback=callback)
+        mocked.post(users_imports, callback=callback)
         j = asyncify(Jobs)(domain="example.com", token="jwt")
         users = TemporaryFile()
         self.assertEqual(await j.import_users_async("connection-1", users), payload)
@@ -158,7 +158,7 @@ async def test_file_post(self, mocked):
     @aioresponses()
     async def test_patch(self, mocked):
         callback, mock = get_callback()
-        await mocked.patch(clients, callback=callback)
+        mocked.patch(clients, callback=callback)
         c = asyncify(Clients)(domain="example.com", token="jwt")
         data = {"client": 1}
         self.assertEqual(await c.update_async("client-1", data), payload)
@@ -174,7 +174,7 @@ async def test_patch(self, mocked):
     @aioresponses()
     async def test_put(self, mocked):
         callback, mock = get_callback()
-        await mocked.put(factors, callback=callback)
+        mocked.put(factors, callback=callback)
         g = asyncify(Guardian)(domain="example.com", token="jwt")
         data = {"factor": 1}
         self.assertEqual(await g.update_factor_async("factor-1", data), payload)
@@ -190,7 +190,7 @@ async def test_put(self, mocked):
     @aioresponses()
     async def test_delete(self, mocked):
         callback, mock = get_callback()
-        await mocked.delete(clients, callback=callback)
+        mocked.delete(clients, callback=callback)
         c = asyncify(Clients)(domain="example.com", token="jwt")
         self.assertEqual(await c.delete_async("client-1"), payload)
         mock.assert_called_with(
@@ -206,7 +206,7 @@ async def test_delete(self, mocked):
     @aioresponses()
     async def test_shared_session(self, mocked):
         callback, mock = get_callback()
-        await mocked.get(clients, callback=callback)
+        mocked.get(clients, callback=callback)
         async with asyncify(Clients)(domain="example.com", token="jwt") as c:
             self.assertEqual(await c.all_async(), payload)
         mock.assert_called_with(
@@ -221,10 +221,10 @@ async def test_shared_session(self, mocked):
     @aioresponses()
     async def test_rate_limit(self, mocked):
         callback, mock = get_callback(status=429)
-        await mocked.get(clients, callback=callback)
-        await mocked.get(clients, callback=callback)
-        await mocked.get(clients, callback=callback)
-        await mocked.get(clients, payload=payload)
+        mocked.get(clients, callback=callback)
+        mocked.get(clients, callback=callback)
+        mocked.get(clients, callback=callback)
+        mocked.get(clients, payload=payload)
         c = asyncify(Clients)(domain="example.com", token="jwt")
         rest_client = c._async_client.client
         rest_client._skip_sleep = True
@@ -237,21 +237,21 @@ async def test_rate_limit(self, mocked):
     @aioresponses()
     async def test_rate_limit_post(self, mocked):
         callback, mock = get_callback(status=429)
-        await mocked.post(clients, callback=callback)
-        await mocked.post(clients, callback=callback)
-        await mocked.post(clients, callback=callback)
-        await mocked.post(clients, payload=payload)
+        mocked.post(clients, callback=callback)
+        mocked.post(clients, callback=callback)
+        mocked.post(clients, callback=callback)
+        mocked.post(clients, payload=payload)
         c = asyncify(Clients)(domain="example.com", token="jwt")
         rest_client = c._async_client.client
         rest_client._skip_sleep = True
-        self.assertEqual(await c.all_async(), payload)
+        self.assertEqual(await c.create_async({}), payload)
         self.assertEqual(3, mock.call_count)
 
     @pytest.mark.asyncio
     @aioresponses()
     async def test_timeout(self, mocked):
         callback, mock = get_callback()
-        await mocked.get(clients, callback=callback)
+        mocked.get(clients, callback=callback)
         c = asyncify(Clients)(domain="example.com", token="jwt", timeout=(8.8, 9.9))
         self.assertEqual(await c.all_async(), payload)
         mock.assert_called_with(