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分配的角色:
- 进入Web应用的App Registration → 令牌配置 → 添加可选声明
- 选择
ID令牌类型,勾选roles声明并保存 - 进入API的App Registration → 公开API → 找到已授权的Web应用条目,确保勾选
id_token作为允许的令牌类型 - 确认API的角色分配已生效(用户/组已关联对应角色)
配置完成后,用户登录时Id Token会包含roles声明,AuthorizationView可直接识别。
方法2:自定义认证状态提供者,读取AccessToken角色
重写Blazor默认的MsalAuthenticationStateProvider,让其从AccessToken中提取角色并添加到用户身份声明中:
- 创建自定义状态提供者类:
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; } }
- 在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
相关产品推荐
相关产品推荐

