跨不同 Microsoft 租户搜索用户信息
Search User Information Across different Microsoft Tenants
我希望能够跨多个租户搜索用户,因此我的想法是创建一个在 HTTP 触发的 Azure 函数上运行的 python 脚本。此 python 脚本可以通过服务主体为不同的租户向 Microsoft Graph API 进行身份验证,然后搜索用户和 return 数据。这是个好主意还是有更好的方法?
让我们讨论成就。
我发现一个multi-tenant
azure ad 应用程序足以通过图表api 查询不同租户中的用户。例如,有 2 个租户,我在 azure ad app 注册中创建了一个多租户应用程序,之后我生成了客户端密码并添加了 api User.Read.All
.
权限
现在我在 'tenant_a' 中有一个应用程序,其客户端 ID 和密码。接下来,在浏览器中访问https://login.microsoftonline.com/{tenant_b}/adminconsent?client_id={client-id}
,在tenant_b中使用admin账号登录后,会出现'permission'window表示同意应用程序在[=]中有权限36=],同意后,您在tenant_a中创建的应用将出现在tenant_b中的Enterprise applications
列表中。
现在我们需要为不同的租户生成访问令牌来调用graph api。需要为每个租户生成访问令牌,因为我尝试使用common
替换请求中的域(https://login.microsoftonline.com/common/oauth2/v2.0/token
),它可以成功生成访问令牌,但令牌不能用于api查询用户信息。查询用户 api 需要用户主体名称作为输入参数。比如我有一个账号是'bob@tenant_b.onmicrosoft.com'的用户,用账号作为参数是可以得到响应的,但是如果我用'bob'作为参数,它就会return 'Resource xxx does not exist...'.
我不是python方面的专家,我只是找到了一个样本并用它测试成功。这是我的代码,它将执行循环查询直到找到用户。如果你想要一个函数,你可以基于它创建一个 http 触发器。
import sys
import json
import logging
import requests
import msal
config = json.load(open(sys.argv[1]))
authorityName = ["<tenant_a>.onmicrosoft.com","<tenant_b>.onmicrosoft.com"]
username = "userone@<tenant_a>.onmicrosoft.com"
for domainName in authorityName:
# Create a preferably long-lived app instance which maintains a token cache.
print("==============:"+config["authority"]+domainName)
app = msal.ConfidentialClientApplication(
"<client_id>", authority="https://login.microsoftonline.com/"+domainName,
client_credential="<client_secret>",
)
# The pattern to acquire a token looks like this.
result = None
# Firstly, looks up a token from cache
# Since we are looking for token for the current app, NOT for an end user,
# notice we give account parameter as None.
result = app.acquire_token_silent(["https://graph.microsoft.com/.default"], account=None)
if not result:
result = app.acquire_token_for_client(scopes=["https://graph.microsoft.com/.default"])
if "access_token" in result:
print("access token===:"+result['access_token'])
# Calling graph using the access token
graph_data = requests.get( # Use token to call downstream service
"https://graph.microsoft.com/v1.0/users/"+username,
headers={'Authorization': 'Bearer ' + result['access_token']}, ).json()
if "error" in graph_data:
print("error===="+json.dumps(graph_data, indent=2))
else:
print(json.dumps(graph_data, indent=2))
break
else:
print(result.get("error"))
print(result.get("error_description"))
print(result.get("correlation_id"))
我希望能够跨多个租户搜索用户,因此我的想法是创建一个在 HTTP 触发的 Azure 函数上运行的 python 脚本。此 python 脚本可以通过服务主体为不同的租户向 Microsoft Graph API 进行身份验证,然后搜索用户和 return 数据。这是个好主意还是有更好的方法?
让我们讨论成就。
我发现一个multi-tenant
azure ad 应用程序足以通过图表api 查询不同租户中的用户。例如,有 2 个租户,我在 azure ad app 注册中创建了一个多租户应用程序,之后我生成了客户端密码并添加了 api User.Read.All
.
现在我在 'tenant_a' 中有一个应用程序,其客户端 ID 和密码。接下来,在浏览器中访问https://login.microsoftonline.com/{tenant_b}/adminconsent?client_id={client-id}
,在tenant_b中使用admin账号登录后,会出现'permission'window表示同意应用程序在[=]中有权限36=],同意后,您在tenant_a中创建的应用将出现在tenant_b中的Enterprise applications
列表中。
现在我们需要为不同的租户生成访问令牌来调用graph api。需要为每个租户生成访问令牌,因为我尝试使用common
替换请求中的域(https://login.microsoftonline.com/common/oauth2/v2.0/token
),它可以成功生成访问令牌,但令牌不能用于api查询用户信息。查询用户 api 需要用户主体名称作为输入参数。比如我有一个账号是'bob@tenant_b.onmicrosoft.com'的用户,用账号作为参数是可以得到响应的,但是如果我用'bob'作为参数,它就会return 'Resource xxx does not exist...'.
我不是python方面的专家,我只是找到了一个样本并用它测试成功。这是我的代码,它将执行循环查询直到找到用户。如果你想要一个函数,你可以基于它创建一个 http 触发器。
import sys
import json
import logging
import requests
import msal
config = json.load(open(sys.argv[1]))
authorityName = ["<tenant_a>.onmicrosoft.com","<tenant_b>.onmicrosoft.com"]
username = "userone@<tenant_a>.onmicrosoft.com"
for domainName in authorityName:
# Create a preferably long-lived app instance which maintains a token cache.
print("==============:"+config["authority"]+domainName)
app = msal.ConfidentialClientApplication(
"<client_id>", authority="https://login.microsoftonline.com/"+domainName,
client_credential="<client_secret>",
)
# The pattern to acquire a token looks like this.
result = None
# Firstly, looks up a token from cache
# Since we are looking for token for the current app, NOT for an end user,
# notice we give account parameter as None.
result = app.acquire_token_silent(["https://graph.microsoft.com/.default"], account=None)
if not result:
result = app.acquire_token_for_client(scopes=["https://graph.microsoft.com/.default"])
if "access_token" in result:
print("access token===:"+result['access_token'])
# Calling graph using the access token
graph_data = requests.get( # Use token to call downstream service
"https://graph.microsoft.com/v1.0/users/"+username,
headers={'Authorization': 'Bearer ' + result['access_token']}, ).json()
if "error" in graph_data:
print("error===="+json.dumps(graph_data, indent=2))
else:
print(json.dumps(graph_data, indent=2))
break
else:
print(result.get("error"))
print(result.get("error_description"))
print(result.get("correlation_id"))