问题描述
我想使用 Python 使用 Power BI API 端点 update dataflow 在我们的 Power BI 租户中重命名数据流,但我收到授权错误。
按照我的Microsoft guidance:
- 创建 Azure 应用
- 授予
Dataflow.ReadWrite.All
权限 - 将服务主体添加到安全组
- 更新了 Power BI 租赁设置以允许新的安全组运行 Power BI API
- 授予安全组和服务主体访问工作区的权限
当我运行下面的代码时,我收到 <Response [401]>
,但是我为其他端点(例如 get dataflow 或 refresh dataflow)编写的类似代码工作正常。如果我从 Azure 应用程序中删除所有 Power BI API 权限,它仍然能够运行 get 和 refresh 调用。这就像代码正在使用工作区的用户权限而不是应用权限。
非常感谢任何帮助。
谢谢
Python
import adal
import requests
TENANT_ID = "abc-123"
CLIENT_ID = "def-456"
CLIENT_SECRET = "ghi-789"
WORKSPACE_ID = "jkl-987"
DATAFLOW_ID = "mno-654"
authority_url = "https://login.microsoftonline.com/"+TENANT_ID
context = adal.AuthenticationContext(authority_url)
token = context.acquire_token_with_client_credentials(
resource="https://analysis.windows.net/powerbi/api",client_id=CLIENT_ID,client_secret=CLIENT_SECRET,)
access_token = token.get("accesstoken")
token_type = token.get("tokenType")
tokenString = "{} {}".format(token_type,access_token)
header = {"Authorization": tokenString}
newName = "This is a new name"
body = {"name": newName}
refresh_url = "https://api.powerbi.com/v1.0/myorg/groups/{}/dataflows/{}".format(WORKSPACE_ID,DATAFLOW_ID) #get all Meta for specific dataflow
r = requests.patch(url=refresh_url,headers=header,json = body)
print(r)
解决方法
根据您在评论中提供的描述,您似乎启用了 MFA。所以当你使用username/password流时,它会被阻塞。
因此您可以使用 auth code 流来获取访问令牌。您需要使用方法acquire_token_with_authorization_code(authorization_code,redirect_uri,resource,client_id,client_secret=None,code_verifier=None)。我想你知道方法中除了 authorization_code
之外的所有参数。您可以参考此 document 了解如何获取。
使用参数请求url跟随url,它将重定向到您在请求中指定的重定向uri并跟随一个名为code=...
的参数。 code
的值为 authorization_code
。
这里我提供我的请求样本(使用身份验证代码流)供您参考:
我请求网址:https://login.microsoftonline.com/xxxxx/oauth2/v2.0/authorize?client_id=xxxxx&response_type=code&redirect_uri=https://hurytest&response_mode=query&scope=https://graph.microsoft.com/.default&state=12345&nonce=67890
它会要求我登录。登录后,它将重定向到带有 https://hurytest/
的 uri code
。
code
是 authorization code
。您可以使用代码进行下一步。
顺便说一下,请注意请求的scope
和resource
。我在示例中使用 v2.0 端点,因此我使用 scope
而不是 resource
,但我注意到您在代码中使用了 resource
(v1.0 端点使用 resource
).