.NET API中多Azure OpenID认证配置问题排查
问题描述
尝试为两个客户端配置Azure OpenID认证:一个无需客户端密钥,另一个需要密钥。单独使用任意一种认证方式均正常(说明Azure应用注册配置无误),但无法在同一后端应用中同时启用两种认证。
现有服务配置代码
Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme).AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd"), OpenIdConnectDefaults.AuthenticationScheme); Services.AddAuthentication().AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureFormApi"), "FormAPI", "ClientFormAPI"); Services.AddControllersWithViews(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle Services.AddEndpointsApiExplorer(); Services.AddSwaggerGen(); Services.AddAuthorization();
无密钥客户端接口(多配置下可正常工作)
[Authorize] [HttpPost] [Route("Download/CellSouche")] [HasPermission(Contrats.Models.Permissions.cellsouches)] public FileContentResult Download(DTOFormDataSelected formItems) { var aa = _formBO.Download(formItems); return aa; }
需要密钥的客户端接口及错误情况
- 当使用如下配置时:
[Authorize(AuthenticationSchemes = "AzureFormApi")] [Route("api/[controller]")] [ApiController] public class ExternalFormsController : ControllerBase { [HttpGet] [Route("testapi")] public IActionResult testapi() { return Ok("test"); } }
调用接口返回错误:The 'ClientId' option must be provided
- 当将认证方案改为
FormApi时:
[Authorize(AuthenticationSchemes = "FormApi")] [Route("api/[controller]")] [ApiController] public class ExternalFormsController : ControllerBase { [HttpGet] [Route("testapi")] public IActionResult testapi() { return Ok("test"); } }
调用接口返回错误:
No authentication handler is registered for the scheme 'FormApi'. The registered schemes are: OpenIdConnect, ClientFormAPI. Did you forget to call AddAuthentication().AddSomeAuthHandler?
尝试过调整服务配置顺序等方式,仅单独配置一种认证时才能正常工作,请问问题出在服务配置还是路由配置中?
问题分析
问题出在服务配置上,核心有两个错误:
- 重复调用
AddAuthentication()会覆盖之前的配置,导致第一个认证方案的部分配置丢失,同时第二个认证的配置无法正确关联到对应配置节。 AddMicrosoftIdentityWebApi的参数使用错误:第二个参数是认证方案名称,第三个是JWT承载方案名称,控制器中引用的方案名和注册的不匹配(大小写或名称完全不符),导致找不到对应的认证处理器。
解决方案
1. 修正服务配置代码
只调用一次AddAuthentication设置默认方案,链式添加两个认证配置,确保每个方案正确关联配置节和名称:
// 设置默认认证方案为OpenIdConnect(对应无密钥客户端) Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) // 添加第一个认证:无密钥客户端,使用默认方案 .AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd"), OpenIdConnectDefaults.AuthenticationScheme) // 添加第二个认证:需要密钥的客户端,指定认证方案名称为"AzureFormApi" .AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureFormApi"), "AzureFormApi"); Services.AddControllersWithViews(); Services.AddEndpointsApiExplorer(); Services.AddSwaggerGen(); Services.AddAuthorization();
2. 修正控制器的认证方案引用
确保控制器上的AuthenticationSchemes和注册的方案名称完全一致:
[Authorize(AuthenticationSchemes = "AzureFormApi")] [Route("api/[controller]")] [ApiController] public class ExternalFormsController : ControllerBase { [HttpGet] [Route("testapi")] public IActionResult testapi() { return Ok("test"); } }
补充说明
- 若无需自定义JWT承载方案名称,可省略
AddMicrosoftIdentityWebApi的第三个参数,方法会默认生成对应承载方案。 - 确保
appsettings.json中的AzureAd和AzureFormApi配置节包含完整必填项(如ClientId、TenantId),需要密钥的客户端还需配置ClientSecret。
内容的提问来源于stack exchange,提问作者CaptnKebec
相关产品推荐
相关产品推荐

