集成Microsoft Identity、OpenID与JWT认证的问题排查
问题分析与解决方案
问题出在PolicyScheme的转发逻辑破坏了OpenID外部登录的默认流程,同时缺少了外部登录必需的DefaultSignInScheme配置,导致Identity无法处理外部身份与本地用户的关联。以下是具体修复步骤:
1. 恢复关键的SignInScheme配置
外部登录流程依赖IdentityConstants.ExternalScheme临时存储外部认证成功后的用户信息,用于后续关联本地账号。需要在认证配置中恢复该设置:
builder.Services.AddAuthentication(options => { options.DefaultScheme = "Identity_or_JWT"; options.DefaultChallengeScheme = "Identity_or_JWT"; options.DefaultSignInScheme = IdentityConstants.ExternalScheme; // 恢复此配置,关键! })
2. 调整PolicyScheme的转发逻辑,优先处理OIDC回调请求
原来的转发逻辑仅通过Endpoint名称判断外部登录请求,无法覆盖OIDC回调场景。需要直接检测OIDC回调路径,确保回调请求由OpenIDConnect处理程序直接处理:
.AddPolicyScheme("Identity_or_JWT", "Identity_or_JWT", options => { options.ForwardDefaultSelector = context => { string? authorization = context.Request.Headers[HeaderNames.Authorization]; // 读取配置中的OIDC回调路径,默认是/signin-oidc var oidcCallbackPath = builder.Configuration["OIDC:CallbackPath"] ?? "/signin-oidc"; // 优先处理OIDC回调请求,确保外部认证流程完整执行 if (context.Request.Path.StartsWithSegments(oidcCallbackPath)) { return OpenIdConnectDefaults.AuthenticationScheme; } if (string.IsNullOrEmpty(authorization)) { // 处理外部登录发起请求(如/ExternalLogin) var endpoint = context.GetEndpoint(); if (endpoint?.DisplayName?.Contains("ExternalLogin") == true) { return IdentityConstants.ExternalScheme; } else { return IdentityConstants.ApplicationScheme; } } return "Bearer"; }; })
3. 确认OIDC配置的正确性
确保appsettings.json中的OIDC配置包含正确的回调路径,与代码中的判断一致:
"OIDC": { "CallbackPath": "/signin-oidc", // 其他OIDC配置(Authority、ClientId等) }
修复原理
DefaultSignInScheme设置为ExternalScheme后,OpenID认证成功时,Identity会将外部用户信息临时存储到Cookie中,供后续的ExternalLoginCallback方法读取,用于关联本地用户。- 新增的OIDC回调路径判断,确保认证回调请求不被PolicyScheme转发到其他认证方案,完整执行OpenIDConnect的认证流程,触发Identity的外部账号关联逻辑(查找已有关联用户或跳转注册表单)。
修改后,三种认证方式可同时正常工作:
- 本地账号登录:通过
IdentityConstants.ApplicationScheme处理 - JWT接口认证:通过
Bearer方案处理 - OpenID外部登录:完整执行认证→临时存储外部身份→关联本地用户的流程
内容的提问来源于stack exchange,提问作者Rhywden
相关产品推荐
相关产品推荐

