ASP.NET Core多身份验证配置问题:第二种OIDC方案失效
ASP.NET Core 多OpenID Connect身份验证回调路由异常问题
当前为ASP.NET Core应用配置了两种OpenID Connect身份验证方案,配置代码如下:
services.AddAuthentication(options => { options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultScheme = "FIRST_OR_SECOND"; options.DefaultChallengeScheme = "FIRST_OR_SECOND"; }).AddOpenIdConnect("FIRST", options => { options.Authority = "https://domain.login.com/domain.onmicrosoft.com/FIRST_SIGNIN/v2.0"; options.ClientId = _webConfig.FIRST.ClientId; options.ClientSecret = _webConfig.FIRST.ClientSecret; options.Scope.Add(_webConfig.FIRST.ClientId); // 其他配置... options.Events = new OpenIdConnectEvents { OnRedirectToIdentityProvider = async ctxt => {...}, OnMessageReceived = async ctxt => {...} // 其他事件... }; }).AddOpenIdConnect("SECOND", options => { options.Authority = "https://domain.login.com/domain.onmicrosoft.com/SECOND_SIGNIN/v2.0"; options.ClientId = _webConfig.SECOND.ClientId; options.ClientSecret = _webConfig.SECOND.ClientSecret; options.Scope.Add(_webConfig.SECOND.ClientId); // 其他配置... options.Events = new OpenIdConnectEvents { OnRedirectToIdentityProvider = async ctxt => {...}, OnMessageReceived = async ctxt => {...} // 其他事件... }; }).AddPolicyScheme("FIRST_OR_SECOND", "FIRST_OR_SECOND", options => { options.ForwardDefaultSelector = context => { string path = context.Request.Path; if (!string.IsNullOrEmpty(path) && path.Contains("/SECOND_LOGIN")) { return "SECOND"; } return "FIRST"; }; }).AddCookie(options => { options.Cookie.SameSite = SameSiteMode.None; options.SlidingExpiration = true; });
问题现象
- 第一种验证方案可正常工作,第二种方案无法完成回调;交换两个
AddOpenIdConnect的注册顺序后,问题反转(原第二种正常,第一种异常) - 核心异常:第二种方案的
OnRedirectToIdentityProvider事件能正常触发,但身份提供商返回回调消息时,请求被导向第一种方案的OnMessageReceived事件
解决方案
1. 为每个OIDC方案配置独立回调路径
ASP.NET Core默认会将所有OIDC回调请求匹配到第一个注册的OIDC方案,因此需要为每个方案指定唯一的CallbackPath:
// 第一种方案配置 .AddOpenIdConnect("FIRST", options => { // 原有配置... options.CallbackPath = "/signin-first"; // 专属回调路径 // 事件配置... }) // 第二种方案配置 .AddOpenIdConnect("SECOND", options => { // 原有配置... options.CallbackPath = "/signin-second"; // 专属回调路径 // 事件配置... })
同时需要登录身份提供商后台(如Azure AD),将对应应用的回调URL更新为:
- 第一种方案:
https://你的应用域名/signin-first - 第二种方案:
https://你的应用域名/signin-second
2. 明确指定回调处理的验证方案
如果无法修改回调路径,可在自定义回调Action中明确指定使用的验证方案:
[HttpGet("/SECOND_LOGIN/callback")] public async Task<IActionResult> SecondLoginCallback() { // 明确使用SECOND方案验证回调 var authResult = await HttpContext.AuthenticateAsync("SECOND"); if (authResult.Succeeded) { // 将用户信息写入Cookie await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, authResult.Principal); return RedirectToAction("Index", "Home"); } return BadRequest("登录验证失败"); }
此方式需将身份提供商的回调URL修改为指向该自定义Action路径。
3. 验证PolicyScheme转发逻辑
PolicyScheme的ForwardDefaultSelector主要用于挑战(Challenge)阶段的方案选择,回调请求需要直接匹配对应OIDC方案,因此独立回调路径是最可靠的解决方式,避免转发逻辑干扰回调处理。
内容的提问来源于stack exchange,提问作者mameli
相关产品推荐
相关产品推荐

