指定其他Scheme发起Challenge时自定义AuthenticationHandler仍被调用如何处理
问题原因
你遇到的问题根因是自定义认证方案被纳入了全局默认的认证/挑战流程,当你触发任意认证相关逻辑时,所有未被排除在默认策略外的Handler都会被执行。即便你显式指定了本次Challenge使用OIDC方案,只要自定义Handler的HandleAuthenticateAsync返回NoResult,认证中间件就会尝试触发所有已注册方案的挑战逻辑,最终自定义的跳转覆盖了OIDC的跳转。
解决方案
下面给出两种可直接落地的修改方式:
方案1:明确指定全局默认的认证/挑战方案,排除自定义方案
修改启动时的服务注册代码,显式声明所有默认认证相关的方案都使用OIDC的方案,自定义方案仅作为按需调用的独立方案存在:
var authBuilder = services.AddAuthentication(options => { options.DefaultScheme = OpenIdConnectDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; options.DefaultSignInScheme = OpenIdConnectDefaults.AuthenticationScheme; options.DefaultSignOutScheme = OpenIdConnectDefaults.AuthenticationScheme; }) .AddScheme<MyCustomHandlerOptions, MyCustomHandler>("MyCustomScheme", null) .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd")) .EnableTokenAcquisitionToCallDownstreamApi(initialScopes) .AddInMemoryTokenCaches();
这个修改后,全局默认的挑战逻辑只会触发OIDC方案的挑战,自定义方案只有在[Authorize]特性、或者Challenge方法显式指定MyCustomScheme时才会被执行。
方案2:修改自定义Handler的逻辑,仅当显式指定自身方案时才执行跳转
如果不想修改全局注册逻辑,可以直接修改自定义Handler的逻辑,仅在明确调用自身方案时才执行对应操作:
protected override Task HandleChallengeAsync(AuthenticationProperties properties) { // 仅当本次Challenge显式指定了MyCustomScheme时才执行自定义跳转 var isTargetScheme = Context.GetEndpoint()?.Metadata.GetMetadata<IAuthorizeData>()?.AuthenticationSchemes?.Contains("MyCustomScheme") == true || (properties.Items.TryGetValue(".AuthScheme", out var targetScheme) && targetScheme?.ToString() == "MyCustomScheme"); if (isTargetScheme) { Context.Response.Redirect("/MyLoginPage"); } return Task.CompletedTask; } protected override Task<AuthenticateResult> HandleAuthenticateAsync() { // 仅当显式指定自身方案时才执行认证逻辑,否则直接返回NoResult var authorizeData = Context.GetEndpoint()?.Metadata.GetMetadata<IAuthorizeData>(); if (authorizeData?.AuthenticationSchemes?.Contains("MyCustomScheme") != true) { return Task.FromResult(AuthenticateResult.NoResult()); } // 此处保留你原本的自定义认证逻辑 return Task.FromResult(AuthenticateResult.NoResult()); }
验证
修改完成后再访问Account/SignInOidc接口,自定义Handler不会再执行跳转逻辑,会正常跳转到OIDC身份提供方的登录页,同时显式标记[Authorize(AuthenticationSchemes = "MyCustomScheme")]的接口逻辑不受影响。
内容的提问来源于stack exchange,提问作者Dave
相关产品推荐
相关产品推荐

