You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从Azure凭证获取用户ID/邮箱:适配用户账户与服务主体

问题:适配各类Azure客户端、可获取UPN/OID的正确Scope是什么?

我们基于Azure ML与Python搭建开发环境,使用azure-identity库的DefaultAzureCredential进行授权,该凭证可匹配CLI或VSCode的登录凭证。希望通过代码获取当前用户的邮箱地址(UPN)或ID(OID),初始代码如下:

from azure.identity import DefaultAzureCredential

credential = DefaultAzureCredential()
token = credential.get_token("https://management.azure.com/", scopes=["user.read"])

current_user_id = ???

后续尝试解析token获取用户信息,更新后的代码如下:

import json
import base64
from azure.identity import DefaultAzureCredential

credential = DefaultAzureCredential()
token = credential.get_token("https://management.azure.com/", scopes=["user.read"])

base64_meta_data = token.token.split(".")[1].encode("utf-8") + b'=='
json_bytes = base64.decodebytes(base64_meta_data)
json_string = json_bytes.decode("utf-8")
json_dict = json.loads(json_string)
current_user_id = json_dict["upn"]
print(f"{current_user_id=}")

但该方法对服务主体无效,获取token时触发报错:

DefaultAzureCredential failed to retrieve a token from the included credentials.
Attempted credentials:
    EnvironmentCredential: Authentication failed: ClientApplication.acquire_token_silent_with_error() got multiple values for argument 'scopes'

请问适配各类客户端、可获取UPN/OID的合适Scope是什么?


解决方案

核心问题分析

  1. 参数调用错误:get_token方法的第一个参数就是scope,无需额外传递resource参数(如https://management.azure.com/),重复传参导致服务主体身份验证报错。
  2. 身份类型差异:用户身份有UPN(邮箱),但服务主体身份没有UPN字段,只有OID(对象ID),需要区分处理。

正确的Scope选择

获取身份信息优先使用Microsoft Graph的scope,而非Azure Management的scope,因为Graph专门用于身份和资源查询:

  • 对于用户身份:https://graph.microsoft.com/user.read(仅获取用户基本信息)
  • 对于服务主体:https://graph.microsoft.com/.default(使用服务主体的默认权限,需提前配置Graph权限)
  • 通用兼容的scope:https://graph.microsoft.com/.default,可同时适配用户和服务主体身份。

修正后的代码

import json
import base64
from azure.identity import DefaultAzureCredential

credential = DefaultAzureCredential()
# 使用正确的scope参数,无需传resource
token = credential.get_token("https://graph.microsoft.com/.default")

# 解析JWT Token的Payload部分
try:
    payload_base64 = token.token.split(".")[1]
    # Base64填充处理
    payload_base64 += "=" * ((4 - len(payload_base64) % 4) % 4)
    payload_bytes = base64.urlsafe_b64decode(payload_base64)
    payload = json.loads(payload_bytes)

    # 区分用户和服务主体
    if "upn" in payload:
        current_identity = payload["upn"]
        identity_type = "用户邮箱(UPN)"
    elif "oid" in payload:
        current_identity = payload["oid"]
        identity_type = "服务主体ID(OID)"
    else:
        current_identity = "无法识别的身份类型"
        identity_type = "未知"

    print(f"当前身份类型:{identity_type},值:{current_identity}")
except Exception as e:
    print(f"解析身份信息失败:{str(e)}")

关键说明

  • get_token方法仅需传入scope字符串(或列表),之前的https://management.azure.com/是冗余参数,会导致服务主体身份验证时参数冲突。
  • 服务主体的JWT Token中没有upn字段,只能通过oid获取其唯一ID。
  • 使用https://graph.microsoft.com/.default时,服务主体需在Azure AD中配置对应的Microsoft Graph权限(如Directory.Read.All),否则可能会触发权限不足的错误。

内容的提问来源于stack exchange,提问作者casparjespersen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 05:20:29