.NET 8中DownstreamAPI无法完成身份验证的问题排查
.NET 8 Blazor应用调用受Microsoft Identity保护的API时令牌异常问题
我用Microsoft Identity保护了自己的.NET 8 Blazor应用,想调用同样受保护的API获取数据。使用DownstreamAPI代表用户发送请求,遵循了微软一份基于.NET 7的教程配置(该教程在.NET 7中可正常运行),但在.NET 8中出现问题。
配置代码
Program.cs
JwtSecurityTokenHandler.DefaultMapInboundClaims = false; builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(builder.Configuration) .EnableTokenAcquisitionToCallDownstreamApi( new string[] { builder.Configuration.GetSection("DownstreamApi:Scopes:Read").Get<string>()!, builder.Configuration.GetSection("DownstreamApi:Scopes:Write").Get<string>()! } ) .AddDownstreamApi("DownstreamApi", builder.Configuration.GetSection("DownstreamApi")) .AddInMemoryTokenCaches(); builder.Services.AddControllersWithViews() .AddMicrosoftIdentityUI(); builder.Services.AddAuthorization(options => { // By default, all incoming requests will be authorized according to the default policy options.FallbackPolicy = options.DefaultPolicy; }); // Add services to the container. builder.Services.AddRazorPages();
Appsettings.json
{ "AzureAd": { "Authority": "https://login.microsoftonline.com/<DIRECTORY>/", "ClientId": "<CLIENT_ID>", "CallbackPath": "/signin-oidc", "SignedOutCallbackPath ": "/signout-oidc", "ClientCredentials": [ { "SourceType": "ClientSecret", "ClientSecret": "<CLIENT_SECRET>" } ] }, "DownstreamApi": { "Scopes": { "Read": "api://<CLIENT_ID>/ToDoList.Read", "Write": "api://<CLIENT_ID>/ToDoList.ReadWrite" }, "BaseUrl": "https://localhost:7281" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*" }
请求代码
@inject IDownstreamApi DownstreamApi; ... @code { ... private async Task GetFromApi() { try { Console.WriteLine("Getting token"); var auth = await DownstreamApi.CallApiForUserAsync( ServiceName, options => options.RelativePath = "/api/authTest"); Console.WriteLine(auth.StatusCode); Console.WriteLine(auth.Content.ReadAsStringAsync().Result); } catch (Exception ex) { Console.WriteLine(ex.Message); } } }
问题现象
发送给API的Bearer令牌存在异常,通过jwt.io解析后对比:
- .NET 7(正常令牌):包含正确的
aud(受众为API的Client ID)、scp(对应申请的权限范围)等声明 - .NET 8(无效令牌):
aud为00000003-0000-0000-c000-000000000000(Microsoft Graph的ID),且缺失目标API的权限范围声明
解决方案
1. 修正请求的服务名称
调用CallApiForUserAsync时传入的ServiceName必须和AddDownstreamApi配置的名称完全一致(即"DownstreamApi"),否则框架会默认请求Microsoft Graph的令牌。修正后的请求代码:
var auth = await DownstreamApi.CallApiForUserAsync( "DownstreamApi", options => options.RelativePath = "/api/authTest");
2. 更新Microsoft Identity包版本
确保项目引用的Microsoft.Identity.Web和Microsoft.Identity.Web.UI包为最新稳定版,.NET 8对身份验证组件有兼容性调整,旧版本可能出现配置映射错误。
3. 移除冗余的客户端凭据配置
Appsettings.json中AzureAd节点的ClientCredentials用于客户端模式调用,而代表用户调用API需要的是用户委托令牌,该配置会干扰令牌获取逻辑,移除后配置如下:
"AzureAd": { "Authority": "https://login.microsoftonline.com/<DIRECTORY>/", "ClientId": "<CLIENT_ID>", "CallbackPath": "/signin-oidc", "SignedOutCallbackPath ": "/signout-oidc" }
4. 显式指定令牌获取配置
如果上述方法无效,可显式指定目标API和范围,避免框架自动推断错误:
var scopes = new string[] { builder.Configuration.GetSection("DownstreamApi:Scopes:Read").Get<string>()!, builder.Configuration.GetSection("DownstreamApi:Scopes:Write").Get<string>()! }; builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(builder.Configuration) .EnableTokenAcquisitionToCallDownstreamApi(scopes) .AddDownstreamApi("DownstreamApi", builder.Configuration.GetSection("DownstreamApi")) .AddInMemoryTokenCaches() .AddTokenAcquisition(options => { options.TargetApi = builder.Configuration["DownstreamApi:BaseUrl"]; options.Scopes = scopes; });
内容的提问来源于stack exchange,提问作者Tim567
相关产品推荐
相关产品推荐

