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

使用MSAL Python获取机密客户端令牌时无法设置preferred_username声明

守护程序应用中设置preferred_username声明不生效的问题解决

问题根源

你对client_claims参数的用途理解有误。这个参数的作用是向Azure AD声明客户端期望令牌中包含特定声明,或验证声明的取值,而非让客户端直接将自定义声明注入到令牌中。在客户端凭据流(守护程序模式)下,令牌的声明由Azure AD根据应用注册配置生成,客户端无法通过client_claims直接添加或修改声明。

正确实现方式

1. 理解守护程序流的声明特性

守护程序流是无用户上下文的认证方式,preferred_username属于用户相关的声明,默认不会出现在这类令牌中。即使你在应用注册中添加了该可选声明,Azure AD也不会为无用户的客户端凭据令牌生成这个值。

2. 方案一:使用自定义客户端断言注入声明

如果必须在令牌中加入preferred_username,可以通过客户端断言的方式,自行构造包含该声明的JWT并签名,然后将其作为客户端凭据传递给MSAL:

import jwt
import time
from msal import ConfidentialClientApplication

def create_client_assertion(client_id, private_key, thumbprint):
    # 构造JWT payload,添加自定义声明
    payload = {
        "aud": "https://login.microsoftonline.com/[你的租户ID]/v2.0",
        "iss": client_id,
        "sub": client_id,
        "exp": int(time.time()) + 3600,  # 1小时有效期
        "iat": int(time.time()),
        "preferred_username": "Test"  # 自定义声明
    }
    # 使用私钥签名JWT
    assertion = jwt.encode(
        payload,
        private_key,
        algorithm="RS256",
        headers={"x5t": thumbprint}
    )
    return assertion

# 构造客户端断言
client_assertion = create_client_assertion(
    config["client_id"],
    open(config['private_key_file']).read(),
    config["thumbprint"]
)

# 初始化ConfidentialClientApplication,使用客户端断言作为凭据
app = ConfidentialClientApplication(
    config["client_id"],
    authority=config["authority"],
    client_credential=client_assertion
)

# 获取令牌
result = app.acquire_token_for_client(scopes=config["scope"])

3. 方案二:通过企业应用声明映射添加自定义声明

如果你的自定义API是作为企业应用配置的,可以在Azure AD的企业应用设置中,添加声明映射规则,将某个固定值或应用属性映射到preferred_username声明。这种方式不需要修改代码,直接在Azure门户配置即可。

总结

  • client_claims无法用来注入自定义声明,它是客户端对Azure AD生成令牌的声明要求。
  • 守护程序流无用户上下文,如需添加用户相关声明,需通过客户端断言或企业应用声明映射实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 07:30:50