【发布时间】:2021-04-02 07:24:08
【问题描述】:
我正在尝试从客户的 Microsoft Dyanmics 365 CRM API 下载一些数据。下面是我用 Python 3.7 编写的代码,使用 MSAL (Microsoft Authentication Library) for Python。
import msal
import requests
class Downloader:
AUTHORITY = 'https://login.microsoftonline.com/common'
SCOPES = ["https://admin.services.crm.dynamics.com/user_impersonation"]
def __init__(self, client_id, client_credential, refresh_token):
self.client_id = client_id
self.client_credential = client_credential
self.refresh_token = refresh_token
def download(self):
application = msal.ConfidentialClientApplication(
client_id=self.client_id,
client_credential=self.client_credential,
authority=self.AUTHORITY,
token_cache=None)
response = application.acquire_token_by_refresh_token(self.refresh_token, self.SCOPES)
instances = requests.get(
'https://globaldisco.crm.dynamics.com/api/discovery/v1.0/Instances',
headers={'Authorization': 'Bearer ' + response['access_token']},
)
return response
当我运行download() 方法时,我成功获得了一个包含访问令牌的response,但是当我使用它来获取instances 时,我得到了HTTP 状态代码401 拒绝访问。
我的问题是:为什么会收到 401 Access Denied 以及如何修复我的代码以获得 200 OK?
更多数据:
-
client_id和client_credential标识了我设置的多租户 Azure 应用注册。此应用注册尚未验证。它配置了以下 API 权限(范围):
https://admin.services.crm.dynamics.com/user_impersonationhttps://graph.microsoft.com/User.Read
-
refresh_token是基于Quickstart: Add sign-in with Microsoft to a Python web app 生成的。快速入门通过设置一个小型 Flask Web 应用程序,人们可以通过 Microsoft Identity 登录并授予我的应用程序注册权限,以便在以后访问 Dynamics 365 CRM API 时模拟他们。我已将 Flask 应用设置为使用我的应用注册和上述两个范围。 -
因为我的应用注册尚未验证,我让目标 Tenet 的管理员通过 Flask 应用登录,批准并同意我的应用注册由 Tenet 组织使用。我已经尝试过他们的刷新令牌和另一个非管理员的刷新令牌。两者都产生 401。
-
tenet org(我的客户身份所属的组织)已链接到 Dynamics 365 帐户。
更新:
当我在我的客户(即原则的)Azure 门户中的 Enterprise Applications 下查看我的应用注册时,我可以在 Common Data Serviceuser_impersonation 权限下看到>管理员同意选项卡,但用户同意选项卡中缺少它。
我试图弄清楚这是否可以解释为什么用户被拒绝访问以及如何将缺少的权限添加到用户同意。
【问题讨论】:
标签: python oauth microsoft-dynamics msal dynamics-365