.NET Core部署Azure服务器后无法生成Token问题排查
问题详情
在.NET Core项目中基于Microsoft Identity Web实现身份认证,Startup.cs配置代码如下:
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(Configuration, "AzureAd") .EnableTokenAcquisitionToCallDownstreamApi(new string[] { "user.read" }) .AddInMemoryTokenCaches();
业务逻辑中通过以下代码获取AccessToken:
var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(new[] { clientId+"/.default" });
本地运行时可正常获取Token并使用,但部署到Azure服务器后,Token返回Null,同时抛出如下异常:
One or more errors occurred. (Value cannot be null. (Parameter 'headers'))
System.AggregateException: One or more errors occurred. (Value cannot be null. (Parameter 'headers'))
---> System.ArgumentNullException: Value cannot be null. (Parameter 'headers')
at Microsoft.Identity.Web.Throws.ArgumentNullException(String paramName)
at Microsoft.Identity.Web.AppServicesAuthenticationInformation.GetIdToken(IDictionary2 headers) at Microsoft.Identity.Web.AppServicesAuthenticationTokenAcquisition.GetAuthenticationResultForUserAsync(IEnumerable1 scopes, String authenticationScheme, String tenantId, String userFlow, ClaimsPrincipal user, TokenAcquisitionOptions tokenAcquisitionOptions)
--- End of inner exception stack trace ---
解决方案
1. 禁用Azure App Service内置身份认证适配
部署到Azure后,Microsoft Identity Web会自动尝试适配App Service内置的身份认证机制,若未配置该机制会导致请求头为空触发异常。可通过以下方式禁用适配:
- 显式添加标准TokenAcquisition服务,覆盖App Service适配版本:
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(Configuration, "AzureAd") .EnableTokenAcquisitionToCallDownstreamApi(new string[] { "user.read" }) .AddInMemoryTokenCaches() .AddTokenAcquisition(); - 直接配置禁用App Service身份认证检测:
services.Configure<MicrosoftIdentityOptions>(options => { options.DisableAppServiceAuthentication = true; });
2. 正确配置Azure App Service内置身份认证
若需保留App Service内置身份认证,需完成以下配置:
- 登录Azure门户,进入目标App Service的「身份认证」设置,启用Microsoft Entra ID身份提供者,确保配置的客户端ID、租户ID与项目中
AzureAd配置节完全一致。 - 将「未认证请求」的处理方式设置为「重定向到登录页」,避免匿名请求导致身份头缺失。
- 配置完成后,原获取Token的代码可保持不变。
3. 替换内存缓存为分布式缓存
本地使用的内存缓存在Azure多实例环境下可能存在一致性问题,可改用分布式缓存(如Redis、SQL Server):
// 示例:使用Redis分布式缓存 services.AddStackExchangeRedisCache(options => { options.Configuration = Configuration.GetConnectionString("Redis"); }); services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(Configuration, "AzureAd") .EnableTokenAcquisitionToCallDownstreamApi(new string[] { "user.read" }) .AddDistributedTokenCaches();
内容的提问来源于stack exchange,提问作者user2845758

