使用Microsoft Identity Web时GetAccessTokenForUserAsync未返回自定义Claim
问题
使用Azure AD B2C登录流,在设置授权票据前调用Azure函数添加自定义Claim(userId)。Blazor应用内的Identity用户能正确看到该自定义Claim,但调用下游API时,通过ITokenAcquisition.GetAccessTokenForUserAsync获取的访问令牌不含userId Claim,传入ClaimsPrincipal对象后结果依旧:
var state = await _provider.GetAuthenticationStateAsync(); var principal = state.User; var accessToken = await tokenAcquisition.GetAccessTokenForUserAsync( [$"{configuration["DownstreamApis:MyAPI-API:AppIdUri"]}/{configuration["DownstreamApis:MyAPI:Scope"]}"], user: principal);
同时发现角色也未映射,HttpContext.User中存在这些Claim,但调用GetAccessTokenForUserAsync时未被带入访问令牌。
Blazor中间件配置
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd")) .EnableTokenAcquisitionToCallDownstreamApi() .AddInMemoryTokenCaches(); builder.Services.AddOptions<OpenIdConnectOptions>(OpenIdConnectDefaults.AuthenticationScheme).Configure(oidcOptions => { oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess); });
API中间件配置
builder.Services .AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApi(o => { var b2cConfig = builder.Configuration.GetSection("AzureAdB2C"); var tenantId = b2cConfig.GetValue<string>("TenantId"); var domains = b2cConfig.GetSection("ValidIssuerDomains").Get<List<string>>(); var validIssuers = domains?.Select(domain => $"https://{domain}/{tenantId}/v2.0/"); o.TokenValidationParameters.ValidIssuers = validIssuers; o.TokenValidationParameters.RoleClaimType = "role"; o.TokenValidationParameters.NameClaimType = "sub"; o.IncludeErrorDetails = true; }, options => builder.Configuration.Bind("AzureAdB2C", options));
解决方案
1. 让Azure AD B2C策略将自定义Claim输出到访问令牌
登录Azure门户,进入目标B2C租户,打开对应的用户流或自定义策略:
- 在应用程序声明设置中,将
userId及角色Claim添加到访问令牌的输出声明列表,不要仅添加到ID令牌。 - 保存并发布策略变更。
2. 确认API权限与请求范围正确
- 在Azure AD B2C中,确保Blazor应用已被授予下游API的Delegated类型权限。
- 调用
GetAccessTokenForUserAsync时,验证传入的范围格式为{AppIdUri}/{ScopeName},例如https://yourtenant.onmicrosoft.com/api/access_as_user。
3. 配置TokenAcquisition的Claim映射规则
在Blazor的服务配置中,添加Claim映射,确保用户端的Claim被带入下游API的请求令牌:
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd")) .EnableTokenAcquisitionToCallDownstreamApi(options => { // 映射自定义userId Claim options.ClaimMapping.Add("userId", "userId"); // 映射角色Claim options.ClaimMapping.Add("role", "role"); }) .AddInMemoryTokenCaches();
4. 检查API端的令牌验证配置
确认API的TokenValidationParameters配置正确,确保令牌的Issuer、SigningKey等参数无误,保证自定义Claim能被正常解析。
5. 清理令牌缓存重试
若存在旧令牌缓存,先清除用户的缓存令牌再重新获取:
await tokenAcquisition.RemoveAccountAsync(principal); // 重新调用GetAccessTokenForUserAsync获取新令牌
内容的提问来源于stack exchange,提问作者GH DevOps
相关产品推荐
相关产品推荐

