AzureAD / microsoft-authentication-library-for-python

Microsoft Authentication Library (MSAL) for Python makes it easy to authenticate to Microsoft Entra ID. General docs are available here https://learn.microsoft.com/entra/msal/python/ Stable APIs are documented here https://msal-python.readthedocs.io. Questions can be asked on www.stackoverflow.com with tag "msal" + "python".
https://stackoverflow.com/questions/tagged/azure-ad-msal+python
Other
754 stars 191 forks source link

Cannot get Azure subscriptions #703

Closed soda92 closed 1 month ago

soda92 commented 1 month ago

I use the following code:

import msal
import requests
import sys
import json

data = json.load(open("parameters.json"))

config = {
    "authority": f"https://login.microsoftonline.com/{data['tenant']}",
    "client_id": data["client_id"],
    "client_secret": data["client_secret"],
    "scopes": [
        "https://management.azure.com/.default",
    ]
}

app = msal.ConfidentialClientApplication(
    config["client_id"],
    authority=config["authority"],
    client_credential=config["client_secret"],
)

result = app.acquire_token_for_client(scopes=config["scopes"])

if "access_token" in result:
    print("success")
else:
    print(result.get("error"))
    print(result.get("error_description"))
    print(result.get("correlation_id"))
    sys.exit(-1)

headers = {
    "Authorization": f"Bearer {result['access_token']}"
}

response = requests.get(
    headers=headers, url="https://management.azure.com/subscriptions?api-version=2019-08-01")

if response.status_code == 200:
    print(response.content)
else:
    print(response.status_code)

However, I cannot get desired result:

success
b'{"value":[],"count":{"type":"Total","value":0}}'

I can get subsriptions using token captured from browser: image

The permissions are already granted. image

I tried to add ""https://management.azure.com//user_impersonation" to scope, but it fails with error:

AADSTS1002012: The provided value for scope https://management.azure.com//user_impersonation is not valid. Client credential flows must have a scope value with /.default suffixed to the resource identifier (application ID URI).

I reads about the "OBO" flow, but my app isn't supposed to need user interactions.

Ask: Does I miss something in the auth flow or permissions?

soda92 commented 1 month ago

moved to https://stackoverflow.com/questions/78505840/cannot-get-azure-subscriptions-using-msal-and-requests-in-python-through-rest

bgavrilMS commented 1 month ago

Hi @soda92 - let's keep this open as a question. The MSAL team is more likely to help on GH issues than on SO questions.

bgavrilMS commented 1 month ago

So, if I understand correctly you want to call an Azure Resource Manager API. This API needs to be called by a service principal (denoted by the app + secret) not by a user. OBO is indeed used for user flows (for client calls web api which calls another downstream api).

For service principal authentication, you correctly use the acquire_token_for_client API. The scope in this case is always the resource\.default so https://management.azure.com/.default is correct.

So I think you have an AuthZ problem, because AAD does issue an app token back to you for ARM. However, after authenticating the service principal (denoted by the app + secret), ARM does not seem to populate the response as you expect. Most likely because you need to configure RBAC.

I see that you are getting some help in SO with RBAC and AuthZ. Please post back if a solution is found. Thanks!

soda92 commented 1 month ago

It was solved in SO. I will post the answer here later

soda92 commented 1 month ago

I granted the Reader role for the application in the subscription, then it works

image

Note that the app was not shown by default, we need to enter application name in the search bar