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

如何在.NET Core Web API中为Azure AD客户端凭证流设置模拟用户?

实现客户端凭证流的模拟用户身份设置

可以通过两种方式实现这个需求,在令牌验证后为无用户信息的客户端凭证流请求创建模拟身份:

方法一:扩展JwtBearer令牌验证事件

在配置Microsoft.Identity.Web认证时,直接修改JwtBearer的验证事件,在令牌验证通过后检查并添加模拟用户:

services.AddMicrosoftIdentityWebApiAuthentication(configuration, AzureAdOptions.Options, AzureAdOptions.BearerAuthenticationScheme)
    .ConfigureJwtBearerOptions(options =>
    {
        var originalValidation = options.Events.OnTokenValidated;
        options.Events.OnTokenValidated = async context =>
        {
            // 先执行默认的令牌验证逻辑
            await originalValidation(context);

            // 检查是否没有用户信息(无upn声明或Principal为空)
            if (context.Principal == null || !context.Principal.HasClaim(c => c.Type == "upn"))
            {
                // 从令牌中提取appid声明
                var appId = context.SecurityToken.Claims.FirstOrDefault(c => c.Type == "appid")?.Value;
                if (!string.IsNullOrEmpty(appId))
                {
                    // 创建模拟身份,设置用户名为appid,认证类型与原Scheme一致
                    var simulatedIdentity = new ClaimsIdentity(
                        new[] { new Claim(ClaimTypes.Name, appId) },
                        AzureAdOptions.BearerAuthenticationScheme
                    );
                    context.Principal = new ClaimsPrincipal(simulatedIdentity);
                }
            }
        };
    });

这样处理后,客户端凭证流的请求会生成一个包含Name声明(值为appid)的身份,后续context.User.Identity.IsAuthenticated会返回true,用户名就是客户端的appid。

方法二:使用全局声明转换服务

如果需要更通用的处理逻辑,可实现IClaimsTransformation接口,全局转换声明:

先创建自定义转换类:

public class SimulatedUserClaimsTransformer : IClaimsTransformation
{
    public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        // 只处理无upn声明的场景(客户端凭证流)
        if (principal != null && !principal.HasClaim(c => c.Type == "upn"))
        {
            var appIdClaim = principal.FindFirst("appid");
            if (appIdClaim != null)
            {
                // 克隆原有身份,避免修改原始对象
                var newIdentity = new ClaimsIdentity(
                    principal.Identity as ClaimsIdentity,
                    new[] { new Claim(ClaimTypes.Name, appIdClaim.Value) }
                );
                return Task.FromResult(new ClaimsPrincipal(newIdentity));
            }
        }
        // 有用户信息的场景直接返回原Principal
        return Task.FromResult(principal);
    }
}

然后在服务注册时添加这个转换:

services.AddScoped<IClaimsTransformation, SimulatedUserClaimsTransformer>();

这种方式会对所有认证通过的请求生效,自动为无upn的令牌添加模拟用户名,适合多认证方案的场景。

注意事项

  • 客户端凭证流的令牌默认包含appid声明,对应客户端应用的ID,无需额外配置;
  • 确保模拟身份的AuthenticationType与认证Scheme一致,保证IsAuthenticated返回true;
  • 方法二中克隆原有身份可保留令牌中的其他声明(如角色、权限等),如果不需要可以直接创建全新的ClaimsIdentity。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 15:10:15