Async issues with `.get_token()` in Credential classes
- 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:
- Create any table in Azure storage
- Populate with 2 or 3 rows of data
- Generate a SAS token for the table and save as an environment variable called
AZURE_STORAGE_SAS_TOKEN - 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.
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}")
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.
@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.
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.
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.
I'm closing this. Thanks for the responses, everyone.