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

Blazor Wasm中如何正确使用AppRegistration API角色?

问题描述
  • 分别为Blazor Wasm Web应用和Function API应用创建了App Registration
  • 在API的App Registration中创建了User.Read、User.WriteRead两个角色,以及API.ACCESS范围;已为Web应用注册配置对应权限,登录后可正常获取令牌,调用API时scp字段显示正常
  • 创建HR组并为其分配API的User.Read角色,添加用户后发现:登录时Id Token和AccessToken中均无角色信息;首次调用API后,AccessToken才会出现User.Read角色,API可借此验证Get User接口权限
  • 需求:在Blazor中通过AuthorizationView隐藏Get User按钮,但AuthorizationView仅读取Id Token,而登录时Id Token无角色信息,调用API后获取的AccessToken也不被其识别
  • 当前临时方案:在Web应用注册中创建同名的User.Read角色并分配给组,但多API场景下重复配置过于繁琐,寻求更优方案或操作纠错

相关配置代码:

services.AddMsalAuthentication(options =>
{
    options.ProviderOptions.Authentication.Authority = azureEntraSettings.Authority;
    options.ProviderOptions.Authentication.ClientId = azureEntraSettings.ClientId;
    options.ProviderOptions.Authentication.ValidateAuthority = azureEntraSettings.ValidateAuthority;
    options.ProviderOptions.LoginMode = azureEntraSettings.LoginMode ?? "Redirect";

    foreach (var application in azureEntraSettings.Applications)
        foreach (var scope in application.Value.Scopes)
            options.ProviderOptions.AdditionalScopesToConsent.Add(scope);
});
解决方案

方法1:配置Id Token包含API角色信息

通过Web应用的App Registration配置,让Id Token直接携带API分配的角色:

  1. 进入Web应用的App Registration → 令牌配置 → 添加可选声明
  2. 选择ID令牌类型,勾选roles声明并保存
  3. 进入API的App Registration → 公开API → 找到已授权的Web应用条目,确保勾选id_token作为允许的令牌类型
  4. 确认API的角色分配已生效(用户/组已关联对应角色)

配置完成后,用户登录时Id Token会包含roles声明,AuthorizationView可直接识别。

方法2:自定义认证状态提供者,读取AccessToken角色

重写Blazor默认的MsalAuthenticationStateProvider,让其从AccessToken中提取角色并添加到用户身份声明中:

  1. 创建自定义状态提供者类:
public class CustomMsalAuthenticationStateProvider : MsalAuthenticationStateProvider
{
    public CustomMsalAuthenticationStateProvider(ILoggerFactory loggerFactory, 
        MsalProviderOptions options, 
        IAccessTokenProviderAccessor accessTokenProviderAccessor) 
        : base(loggerFactory, options, accessTokenProviderAccessor)
    {
    }

    public override async Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        var state = await base.GetAuthenticationStateAsync();
        if (state.User.Identity.IsAuthenticated)
        {
            var accessTokenResult = await AccessTokenProvider.RequestAccessToken(
                new AccessTokenRequestOptions
                {
                    Scopes = new[] { "api://{你的API客户端ID}/API.ACCESS" }
                });

            if (accessTokenResult.TryGetToken(out var accessToken))
            {
                var jwtToken = new JwtSecurityTokenHandler().ReadJwtToken(accessToken.Value);
                var apiRoles = jwtToken.Claims.Where(c => c.Type == "roles").Select(c => c.Value);
                
                var claimsIdentity = state.User.Identity as ClaimsIdentity;
                foreach (var role in apiRoles)
                {
                    if (!claimsIdentity.HasClaim(c => c.Type == "roles" && c.Value == role))
                    {
                        claimsIdentity.AddClaim(new Claim("roles", role));
                    }
                }
            }
        }
        return state;
    }
}
  1. 在Program.cs中替换默认的认证状态提供者:
builder.Services.AddMsalAuthentication(options =>
{
    // 保留原配置内容
});
builder.Services.AddScoped<AuthenticationStateProvider, CustomMsalAuthenticationStateProvider>();

修改后,AuthorizationView即可识别到AccessToken中的角色信息,无需重复配置Web应用角色。

方法3:登录时直接请求API角色范围

调整Web应用的认证配置,在登录阶段直接请求API的角色对应的范围,让AccessToken在登录时就包含角色信息:

  • 在AdditionalScopesToConsent中添加API的具体角色范围(如api://{你的API客户端ID}/User.Read),而不仅仅是通用的API.ACCESS范围
  • 登录时会同时获取包含角色的AccessToken,后续通过方法2的自定义提供者即可让AuthorizationView识别角色

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 20:27:33