我正在设计一个 Python 脚本,可以通过 Microsoft Dynamics CRM API 提取和查询信息和数据。
我希望得到一个刷新令牌,这样我就可以在不频繁登录的情况下长时间获得访问令牌。
def login():
authorization_url = (
f"https://login.microsoftonline.com/{tenant}/oauth2/authorize"
"?response_type=code"
f"&client_id={client_id}"
f"&redirect_uri={redirect_uri}"
"&response_mode=query&prompt=consent"
f"&scope={scope}%2f.default openid profile offline_access"
# f"&scope={scope}"
# f"&scope={scope}"
"&state=12345&sso_reload=true"
f"&code_challenge={code_challenge}"
"&code_challenge_method=S256"
f"&nonce={nonce}"
"&client_info=1"
)
return render_template("login.html", version=__version__, auth_uri = authorization_url)
登录成功后,url跳转到Azure Ad中已经添加的重定向路径。从请求中获取authorization_code并将其带入发布请求刷新代码。
@app.route(app_config.REDIRECT_PATH)
def auth_response():
authorization_code = request.args.get('code')
refresh_token = _get_refresh_token(tenant,
client_id,
client_secret,
authorization_code,
redirect_uri
)
但是,当请求发布刷新令牌时,范围携带offline_access并收到错误请求响应。
scope = 'https://<myid>.api.crm3.dynamics.com/user_impersonation'
data = {
'client_id': client_id,
'scope': f'{scope}%2f.default openid profile offline_access',
'code': authorization_code,
'redirect_uri': redirect_uri,
'grant_type': 'authorization_code',
'client_secret': client_secret,
'code_verifier': code_verifier,
}
response = requests.post(token_endpoint, data=data)
无法获得offline_access的授权来获取刷新令牌:“error_description”:“AADSTS65001:用户或管理员尚未同意使用具有ID的应用程序。
从响应中收到错误文本:
'{"error":"invalid_grant","error_description":"AADSTS65001: 用户或管理员尚未同意使用 ID 为 '320ae26a-b04b-49c6-aa2e-dfc77e734f01' 且名为 'PowerAppAPI' 的应用程序。发送交互此用户和资源的授权请求。跟踪 ID:ecfc933e-e5ae-4675-927e-bbfc16980700 相关 ID:017df973-0078-4c54-8258-163a0fd3705d 时间戳:2023-12-14 21:18:57Z","error_codes": [65001],“时间戳”:“2023-12-14 21:18:57Z”,“trace_id”:“ecfc933e-e5ae-4675-927e-bbfc16980700”,“correlation_id”:“017df973-0078-4c54-8258- 163a0fd3705d","子错误":"consent_required"}'
我已在 Azure AD 的应用程序管理中添加了动态 CRM 和 Microsoft Graph 的权限并授予了我自己。
事实上,当作用域没有声明offline_access时,就可以获取并使用访问令牌。
我是否错过了 Azure AD 中应用程序管理中的任何设置?如何使用访问令牌获取权限?谢谢您的回答
期望请求能够响应并返回当前 Dynamic CRM 或 Microsoft Graph 范围的刷新令牌。
在授权请求和令牌请求中,您正在使用以下方式构建
scope
参数:
f'{scope}%2f.default openid profile offline_access'
当
scope
变量为 https://<myid>.api.crm3.dynamics.com/user_impersonation
时,结果是:
https://<myid>.api.crm3.dynamics.com/user_impersonation%2f.default openid profile offline_access
它由
requests.post()
进行表单编码(最终在 %2f
上进行第二次编码),并发送到 Microsoft Entra ID:
scope=https%3a%2f%2forgca5a56ca.api.crm3.dynamics.com%2fuser_impersonation%252f.default+openid+profile+offline_access
在您的 token 请求中,第一个
scope
值被 Microsoft Entra ID 解释为“资源 user_impersonation%2f.default
处的委派权限 https://<myid>.api.crm3.dynamics.com
”。由于未授予名为 user_impersonation%2f.default
的委派权限,因此此操作失败。
授权请求(首先出现)没有失败的原因是您将该请求发送到 Microsoft Entra ID 的 v1.0 端点,这是较旧的(甚至不再记录)端点。在该端点上:
scope
参数中唯一重要的值是
openid
,它仅用于识别应用程序需要ID令牌。任何其他值都将被完全忽略(包括
email
、
offline_access
、
profile
以及格式错误的 CRM 参数)。
resource
参数中标识。如果未提供该参数,则假定为 Azure AD Graph(
https://graph.windows.net
,已弃用)。
问题:您正在使用 v2.0 端点的参数构建授权请求,但实际上是将其发送到 v1.0 端点:
*解决方案:将您的授权请求发送到 v2.0 端点,如文档所述:
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize
问题*:在您的令牌请求中,您请求 Dynamics CRM 委派权限 user_impersonation%2f.default
,但该权限不存在且未被授予。
解决方案:请求 Dynamics CRM 委派权限 user_impersonation
,该权限确实存在。在您的授权请求和令牌请求中:
f"&scope={scope} openid profile offline_access"