自定义认证策略下Admin控制器触发OnRemoteFailure的原因与解决
ASP.NET Core 8.0多认证方案下OnRemoteFailure事件误触发问题
问题场景
在ASP.NET Core 8.0应用中同时配置了两种认证方案:
- OpenIdConnect(基于IdentityServer4,方案名
SigmaSSO) - Microsoft Identity(Azure AD,方案名
EntraIdOIDC)
预期行为:
- 前端控制器使用
SigmaSSO方案认证 - Admin控制器使用绑定
EntraIdOIDC的AdminSection策略认证
实际问题:访问Admin控制器时,会触发全局配置的OnRemoteFailure事件,导致页面跳转至首页,而该事件仅期望在SigmaSSO相关认证失败时触发。
配置细节
Startup.cs 认证与授权配置
services.AddSingleton<IConfigureOptions<OpenIdConnectOptions>, ConfigureOpenIdConnectOptions>(); services.AddSingleton<IConfigureOptions<MicrosoftIdentityOptions>, ConfigureAzureAdConnectOptions>(); AuthenticationBuilder authBuilder = services.AddAuthentication(options => { options.DefaultScheme = "IS4Cookies"; options.DefaultChallengeScheme = "SigmaSSO"; }); authBuilder.AddCookie("IS4Cookies"); // Add a cookie handler authBuilder.AddOpenIdConnect("SigmaSSO", null); authBuilder.AddMicrosoftIdentityWebApp(Configuration, "AzureAd", "EntraIdOIDC", "EntraId", true); services.AddAuthorization(options => { options.AddPolicy("AdminSection", policy => { policy.AddAuthenticationSchemes("EntraIdOIDC"); policy.RequireAuthenticatedUser(); policy.RequireRole(new List<string>{"PlusAdminUser"}); }); options.AddPolicy("FrontEnd", policy => { policy.AddAuthenticationSchemes("SigmaSSO"); policy.RequireAuthenticatedUser(); }); });
ConfigureOpenIdConnectOptions 事件配置
options.Events = new OpenIdConnectEvents() { OnRemoteFailure = ctx => { ctx.HandleResponse(); ctx.Response.Redirect("/"); return Task.FromResult(0); } };
控制器特性
Admin控制器:
[Area("Admin")] [Authorize(Policy = "AdminSection")]
前端控制器:
[Area("Admin")] [Authorize(Policy = "FrontEnd")]
ConfigureAzureAdConnectOptions 基础配置
options.Instance = "https://login.microsoftonline.com/"; options.Domain = "azure-domain-here"; options.TenantId = "someguid"; options.ClientId = "some-other-guid"; options.CallbackPath = "/signin-oidc"; options.SignInScheme = "AzureCookies"; options.Scope.Add("openid");
问题原因
IConfigureOptions<OpenIdConnectOptions>是全局配置容器,会作用于所有基于OpenIdConnectOptions的认证方案。由于Microsoft Identity的EntraIdOIDC底层也是基于OpenIdConnect实现的,因此全局配置的OnRemoteFailure事件会被EntraIdOIDC方案的认证失败触发,导致访问Admin控制器时出现意外跳转。
解决方法
方法1:仅为SigmaSSO方案配置事件
移除全局的ConfigureOpenIdConnectOptions注册,改为在添加SigmaSSO方案时直接配置事件,确保事件仅作用于目标方案:
// 移除全局注册:services.AddSingleton<IConfigureOptions<OpenIdConnectOptions>, ConfigureOpenIdConnectOptions>(); AuthenticationBuilder authBuilder = services.AddAuthentication(options => { options.DefaultScheme = "IS4Cookies"; options.DefaultChallengeScheme = "SigmaSSO"; }); authBuilder.AddCookie("IS4Cookies"); // 直接在AddOpenIdConnect中配置SigmaSSO专属事件 authBuilder.AddOpenIdConnect("SigmaSSO", null, options => { options.Events = new OpenIdConnectEvents() { OnRemoteFailure = ctx => { ctx.HandleResponse(); ctx.Response.Redirect("/"); return Task.CompletedTask; } }; }); authBuilder.AddMicrosoftIdentityWebApp(Configuration, "AzureAd", "EntraIdOIDC", "EntraId", true);
方法2:在全局配置中过滤方案名称
如果必须使用IConfigureOptions<OpenIdConnectOptions>,则在Configure方法中判断方案名称,仅对SigmaSSO配置事件:
public class ConfigureOpenIdConnectOptions : IConfigureNamedOptions<OpenIdConnectOptions> { public void Configure(string name, OpenIdConnectOptions options) { // 仅为SigmaSSO方案配置事件 if (name == "SigmaSSO") { options.Events = new OpenIdConnectEvents() { OnRemoteFailure = ctx => { ctx.HandleResponse(); ctx.Response.Redirect("/"); return Task.CompletedTask; } }; } } public void Configure(OpenIdConnectOptions options) { // 留空,主要逻辑在命名配置分支中 } }
方法3:排查EntraIdOIDC认证失败原因
检查AdminSection策略的认证流程是否存在实际错误:
- 确认Azure AD中已正确配置
PlusAdminUser角色并分配给目标用户 - 验证
EntraIdOIDC的回调路径、客户端ID、租户ID等配置与Azure AD门户完全一致 - 排查是否存在令牌验证失败、权限不足等真实认证错误,避免不必要的
OnRemoteFailure触发
内容的提问来源于stack exchange,提问作者CarComp
相关产品推荐
相关产品推荐

