msgraph-sdk-python-core icon indicating copy to clipboard operation
msgraph-sdk-python-core copied to clipboard

Authenticating with CLI Credentials does not work

Open soffensive opened this issue 3 years ago • 4 comments

Is your feature request related to a problem? Please describe. I want to authenticate via CLI credentials but the library does not allow this at the moment.

So far I am using Azure AD Graph Management client as follows:

from azure.common.credentials import get_azure_cli_credentials
from azure.graphrbac import GraphRbacManagementClient

cred, _, tenant_id = get_azure_cli_credentials(
    resource='https://graph.windows.net',
    with_tenant=True)
client = GraphRbacManagementClient(cred, tenant_id)

This works reasonably well, but AAD graph will be deprecated and the get_azure_cli_credentials already is deprecated. So I went for the following approach:

from msgraph.core import GraphClient
from azure.identity import AzureCliCredential


azure_cli = AzureCliCredential()

client = GraphClient(credential=azure_cli)
result = client.get('/me')
print(result.json())

When trying to execute this, the following error message is shown:

AzureCliCredential.get_token failed: Please run 'az login' to set up an account
Traceback (most recent call last):
  File "/home/blub/cloud/environ/lib/python3.9/site-packages/azure/identity/_credentials/azure_cli.py", line 122, in _run_command
    return subprocess.check_output(args, **kwargs)
  File "/usr/lib/python3.9/subprocess.py", line 424, in check_output
    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
  File "/usr/lib/python3.9/subprocess.py", line 528, in run
    raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '['/bin/sh', '-c', 'az account get-access-token --output json --resource .default']' returned non-zero exit status 1.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/media/sf_share/scripts/azure_cli_creds_ms_graph.py", line 8, in <module>
    result = client.get('/me')
  File "/home/blub/cloud/environ/lib/python3.9/site-packages/msgraph/core/_graph_client.py", line 46, in wrapper
    return func(*args, **kwargs)
  File "/home/blub/cloud/environ/lib/python3.9/site-packages/msgraph/core/_graph_client.py", line 93, in get
    return self.graph_session.get(self._graph_url(url), **kwargs)
  File "/home/blub/cloud/environ/lib/python3.9/site-packages/requests/sessions.py", line 555, in get
    return self.request('GET', url, **kwargs)
  File "/home/blub/cloud/environ/lib/python3.9/site-packages/requests/sessions.py", line 542, in request
    resp = self.send(prep, **send_kwargs)
  File "/home/blub/cloud/environ/lib/python3.9/site-packages/requests/sessions.py", line 655, in send
    r = adapter.send(request, **kwargs)
  File "/home/blub/cloud/environ/lib/python3.9/site-packages/msgraph/core/middleware/middleware.py", line 44, in send
    return self._first_middleware.send(request, **kwargs)
  File "/home/blub/cloud/environ/lib/python3.9/site-packages/msgraph/core/middleware/authorization.py", line 20, in send
    {'Authorization': 'Bearer {}'.format(self._get_access_token(context))}
  File "/home/blub/cloud/environ/lib/python3.9/site-packages/msgraph/core/middleware/authorization.py", line 32, in _get_access_token
    return self.credential.get_token(*self.get_scopes(context))[0]
  File "/home/blub/cloud/environ/lib/python3.9/site-packages/azure/identity/_internal/decorators.py", line 27, in wrapper
    token = fn(*args, **kwargs)
  File "/home/blub/cloud/environ/lib/python3.9/site-packages/azure/identity/_credentials/azure_cli.py", line 57, in get_token
    output = _run_command(COMMAND_LINE.format(resource))
  File "/home/blub/cloud/environ/lib/python3.9/site-packages/azure/identity/_credentials/azure_cli.py", line 128, in _run_command
    raise CredentialUnavailableError(message=NOT_LOGGED_IN)
azure.identity._exceptions.CredentialUnavailableError: Please run 'az login' to set up an account

Although the CLI is authenticated and I get a valid access token when executing: az account get-access-token --output json

It seems the resource .default is causing problems here.

Describe the solution you'd like Make the library fully compatible with CLI credentials.

Describe alternatives you've considered I am using Device Code credentials, which works fine but requires me to authenticate always anew, so it is not a solution.

Additional context Add any other context or screenshots about the feature request here.

soffensive avatar Sep 21 '21 13:09 soffensive

Hi @soffensive . Thank you for the clear and well explained issue.

Indeed this problem seems to be caused by the underlying call made to the Azure Cli. The desired call to get an access token for use with MS Graph API should be az account get-access-token --resource-type ms-graph. This requires an update to the implementation of the AzureCliCredential class of the azure-identity library, which is outside the scope of this project. I would suggest you create this issue on the azure-identity repository here and use the Azure.Identity label.

As a side note, we are working on our own Microsoft Graph CLI. We will definitely consider adding support for this authentication scenario. Thanks.

samwelkanda avatar Sep 25 '21 05:09 samwelkanda

Thanks for your swift response, I opened the issue here: https://github.com/Azure/azure-sdk-for-python/issues/20877

soffensive avatar Sep 26 '21 15:09 soffensive

Since the project I'm working on will possibly run into the same issue, I had to test this. I found out that adding explicit scopes to GraphClient() seems to work fine, and the following returns my user, having initially authenticated with Azure CLI:

client = GraphClient(credential=AzureCliCredential(), scopes=["https://graph.microsoft.com"])
result = client.get('/me')
print(result.json())

Is this a valid workaround, or are there subtle differences between this (which, as far as I can tell, ends up passing --resource https://graph.microsoft.com to az account get-access-token) and --resource-type ms-graph (as described in the previous comment)?

fhoy avatar Nov 15 '21 20:11 fhoy

Thanks @fhoy, this was a big help Adding scopes to the GraphClient class worked for me using the DefaultAzureCredential class from azure.identity.

creds = DefaultAzureCredential() client = GraphClient(credential=creds, scopes=['https://graph.microsoft.com']) result = client.get('/me') print(result.json())

mb01r avatar May 31 '22 14:05 mb01r

thanks for reporting this issue, we have since released a new version of the SDK which this issue doesn't apply to. We encourage you to migrate to the new version and open a new issue if you still need help

baywet avatar Apr 25 '24 15:04 baywet