我正在使用 Microsoft Graph Python SDK 来访问用户许可证信息。这是代码行:
license_details = await graph_client.users.by_user_id(user_id).license_details.get()
但是,这会不断抛出授权错误并显示以下响应:
APIError
Code: 403
message: None
error: MainError(additional_data={}, code='Authorization_RequestDenied', details=None, inner_error=InnerError(additional_data={}, client_request_id='a0dc5684-d627-477b-af2c-1d264039e6de', date=DateTime(2024, 11, 13, 5, 59, 28, tzinfo=Timezone('UTC')), odata_type=None, request_id='f503re17-615b-46f4-afce-fc02bda244a2'), message='Insufficient privileges to complete the operation.', target=None)
我的应用程序拥有所有必要的权限,例如 User.Read.All 和 Directory.Read.All,并获得管理员同意并使用正确的凭据。尽管如此,错误仍然发生。
目标是检索用户的许可证详细信息,但实际上返回了 403 授权错误。访问许可证详细信息是否需要额外的权限? Azure AD 应用程序配置是否存在问题?
预先感谢您的帮助!
请注意,
licenseDetails
API 端点不支持 Application 类型的权限。您可以参考这个MS Document。
最初,当我尝试使用授予 Application 类型权限的客户端凭据流程访问用户的许可证信息时,我也遇到了 同样的错误:
要解决该错误,请通过授予 Deleated 类型的
LicenseAssignment.ReadWrite.All
权限,切换到 deleated 流程,例如交互式或授权代码流程:
在我的例子中,我使用了交互流,其重定向 URI 应为 http://localhost,在启用了公共客户端流的移动和桌面应用程序平台中:
当我运行下面的示例代码并使用管理员帐户登录时,我成功收到包含用户许可证信息的响应,如下所示:
import asyncio
from azure.identity import InteractiveBrowserCredential
from msgraph import GraphServiceClient
CLIENT_ID = 'appID'
TENANT_ID = 'tenantID'
SCOPES = ['LicenseAssignment.ReadWrite.All']
credential = InteractiveBrowserCredential(
client_id=CLIENT_ID,
tenant_id=TENANT_ID
)
graph_client = GraphServiceClient(credential)
async def get_user_license_details(user_id):
try:
license_details_response = await graph_client.users.by_user_id(user_id).license_details.get()
license_details = license_details_response.value
if license_details:
print(f"License details for user {user_id}:")
for license in license_details:
print(f"License SKU ID: {license.sku_id}")
print(f"SKU Part Number: {license.sku_part_number}")
if license.service_plans:
print("Assigned Service Plans:")
for plan in license.service_plans:
print(f" Service Plan ID: {plan.service_plan_id}")
print(f" Service Plan Name: {plan.service_plan_name}")
print(f" Provisioning Status: {plan.provisioning_status}")
print(f" Applies to: {plan.applies_to}")
else:
print("No assigned service plans found.")
else:
print(f"No license details found for user {user_id}.")
except Exception as e:
print(f"Error retrieving license details: {e}")
async def main():
user_id = 'userID'
await get_user_license_details(user_id)
asyncio.run(main())
回复: