azure-sdk-for-python icon indicating copy to clipboard operation
azure-sdk-for-python copied to clipboard

Async issues with `.get_token()` in Credential classes

Open phobson opened this issue 1 year ago • 5 comments

  • azure-identity:
  • 1.15, 1.14, 1.2:
  • Windows & WSL:
  • Python Version, 3.11:

Describe the bug Every time I try to use a DefaultAzureCredential, AzureCliCredential, etc, I get the the error:

AttributeError: 'coroutine' object has no attribute 'token'
sys:1: RuntimeWarning: coroutine '{credential_class}.get_token' was never awaited

An AzureSasCredential from azure.core,credentials works fine.

To Reproduce Steps to reproduce the behavior:

  1. Create any table in Azure storage
  2. Populate with 2 or 3 rows of data
  3. Generate a SAS token for the table and save as an environment variable called AZURE_STORAGE_SAS_TOKEN
  4. Run the following script:
# cred_test.py
import os

from dotenv import load_dotenv

from azure.core.credentials import AzureSasCredential
from azure.identity.aio import DefaultAzureCredential, AzureCliCredential, ChainedTokenCredential
from azure.data.tables import TableServiceClient

load_dotenv()


def fetch(creds):
    table_service_client = TableServiceClient(
        endpoint="https://hecdatawarehousestorage.table.core.windows.net",
        credential=creds,
    )
    table_client = table_service_client.get_table_client(table_name="stations")
    rows = table_client.query_entities(query_filter="")
    return list(rows)


if __name__ == "__main__":
    sas_cred = AzureSasCredential(os.getenv("AZURE_STORAGE_SAS_TOKEN"))
    cli_cred = AzureCliCredential()
    def_cred = DefaultAzureCredential()

    chain = ChainedTokenCredential(sas_cred, cli_cred)

    for creds in [sas_cred, cli_cred, def_cred, chain]:
        try:
            rows = fetch(creds)
            print(f"sucess with {creds=}")
        except AttributeError as e:
            print(f"failure with {creds=} raising {e}")

That prints to the terminal:

sucess with creds=<azure.core.credentials.AzureSasCredential object at 0x000001C299A7BFD0>
failure with creds=<azure.identity.aio._credentials.azure_cli.AzureCliCredential object at 0x000001C29C5ECC10> raising 'coroutine' object has no attribute 'token'
failure with creds=<azure.identity.aio._credentials.default.DefaultAzureCredential object at 0x000001C299AB1A10> raising 'coroutine' object has no attribute 'token'
failure with creds=<azure.identity.aio._credentials.chained.ChainedTokenCredential object at 0x000001C29D294B90> raising 'coroutine' object has no attribute 'token'

sys:1: RuntimeWarning: coroutine 'AzureCliCredential.get_token' was never awaited
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
sys:1: RuntimeWarning: coroutine 'DefaultAzureCredential.get_token' was never awaited
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
sys:1: RuntimeWarning: coroutine 'ChainedTokenCredential.get_token' was never awaited
RuntimeWarning: Enable tracemalloc to get the object allocation traceback

Expected behavior

I would have thought that the chained credential would have succeeded since we can see that the AzureSasCredential works by itself.

Screenshots None

Additional context I get the same errors trying to read from blob storage. But if I use fsspec/adlfs, and let them figure out the creds themselves, it seems to work.

phobson avatar Mar 10 '24 07:03 phobson

Thank you for the feedback @phobson. I see that you are using the async versions of the credentials with the sync TableServiceClient.

does this modified sample still produce the error for you ?

# cred_test.py
import os

from dotenv import load_dotenv

from azure.core.credentials import AzureSasCredential
from azure.identity import DefaultAzureCredential, AzureCliCredential, ChainedTokenCredential
from azure.data.tables import TableServiceClient

load_dotenv()


def fetch(creds):
    table_service_client = TableServiceClient(
        endpoint="https://hecdatawarehousestorage.table.core.windows.net",
        credential=creds,
    )
    table_client = table_service_client.get_table_client(table_name="stations")
    rows = table_client.query_entities(query_filter="")
    return list(rows)


if __name__ == "__main__":
    sas_cred = AzureSasCredential(os.getenv("AZURE_STORAGE_SAS_TOKEN"))
    cli_cred = AzureCliCredential()
    def_cred = DefaultAzureCredential()

    chain = ChainedTokenCredential(sas_cred, cli_cred)

    for creds in [sas_cred, cli_cred, def_cred, chain]:
        try:
            rows = fetch(creds)
            print(f"sucess with {creds=}")
        except AttributeError as e:
            print(f"failure with {creds=} raising {e}")

kashifkhan avatar Mar 11 '24 15:03 kashifkhan

Hi @phobson. Thank you for opening this issue and giving us the opportunity to assist. To help our team better understand your issue and the details of your scenario please provide a response to the question asked above or the information requested above. This will help us more accurately address your issue.

github-actions[bot] avatar Mar 11 '24 15:03 github-actions[bot]

@kashifkhan thanks for the response. I didn't even realize that aio was the async submodule. However, I still get similar results.

However, I noted that if I remove the AzureSasCredential from the chain, the error changes to permissions mismatch -- I'm not on my main machine, so I can believe that's a correct error.

This leads me to think that azure.core.credentials.AzureSasCredential simply isn't compatible with azure.indentity credentials. Now that I type that out, it makes perfect sense.

My hunch is that this is user error and this issue can be closed.

Output:

Restarted .venv (Python 3.10.13)

* sucess with creds=<azure.core.credentials.AzureSasCredential object at 0x7fe7d276a590>
* failure with creds=<azure.identity._credentials.azure_cli.AzureCliCredential object at 0x7fe7d2768e50> raising This request is not 

authorized to perform this operation using this permission.
RequestId:11b13066-5002-004f-3235-749784000000
Time:2024-03-12T04:24:45.2212117Z
ErrorCode:AuthorizationPermissionMismatch
Content: {"odata.error":{"code":"AuthorizationPermissionMismatch","message":{"lang":"en-US","value":"This request is not authorized to perform this operation using this permission.\nRequestId:11b13066-5002-004f-3235-749784000000\nTime:2024-03-12T04:24:45.2212117Z"}}}
ChainedTokenCredential failed to retrieve a token from the included credentials.
Attempted credentials:
	AzureSasCredential: 'AzureSasCredential' object has no attribute 'get_token'
To mitigate this issue, please refer to the troubleshooting guidelines here at https://aka.ms/azsdk/python/identity/defaultazurecredential/troubleshoot.

* failure with creds=<azure.identity._credentials.default.DefaultAzureCredential object at 0x7fe7d276b940> raising This request is not authorized to perform this operation using this permission.
RequestId:67c57455-b002-0047-1e35-748d8b000000
Time:2024-03-12T04:24:46.7297907Z
ErrorCode:AuthorizationPermissionMismatch
Content: {"odata.error":{"code":"AuthorizationPermissionMismatch","message":{"lang":"en-US","value":"This request is not authorized to perform this operation using this permission.\nRequestId:67c57455-b002-0047-1e35-748d8b000000\nTime:2024-03-12T04:24:46.7297907Z"}}}

* failure with creds=<azure.identity._credentials.chained.ChainedTokenCredential object at 0x7fe7d4acf460> raising ChainedTokenCredential failed to retrieve a token from the included credentials.
Attempted credentials:
	AzureSasCredential: 'AzureSasCredential' object has no attribute 'get_token'
To mitigate this issue, please refer to the troubleshooting guidelines here at https://aka.ms/azsdk/python/identity/defaultazurecredential/troubleshoot.

phobson avatar Mar 12 '24 04:03 phobson

Hey @phobson. Your hunch is correct in that AzureSasCredential isn't compatible. The azure-identity package deals with token credentials, or credentials that implement the TokenCredential protocol (and thus have get_token methods). Since that's the case, AzureSasCredential won't work in a ChainedTokenCredential credential chain.

pvaneck avatar Mar 12 '24 18:03 pvaneck

Hi @phobson. Thank you for opening this issue and giving us the opportunity to assist. We believe that this has been addressed. If you feel that further discussion is needed, please add a comment with the text "/unresolve" to remove the "issue-addressed" label and continue the conversation.

github-actions[bot] avatar Mar 12 '24 18:03 github-actions[bot]

I'm closing this. Thanks for the responses, everyone.

phobson avatar Mar 19 '24 20:03 phobson