ASP.NET 4.6 MVC5中OpenIDConnect的GetExternalLoginInfoAsync返回null求助
ASP.NET 4.6 MVC5 OpenID Connect: 解决
GetExternalLoginInfoAsync()返回null的问题 我帮你分析下当前遇到的问题——核心矛盾其实是自定义路由和OIDC中间件的默认回调处理逻辑冲突了,先给你拆解原因和解决方案:
问题根源梳理
你一开始遇到404,是因为OIDC中间件默认会处理CallbackPath指定的/signin-oidc路径,但你的MVC路由里没对应匹配;但手动添加路由把/signin-oidc指向Account/ExternalLoginCallback后,又跳过了OIDC中间件的认证流程,导致GetExternalLoginInfoAsync()拿不到已经完成的认证上下文,所以返回null。
分步解决方案
1. 移除自定义路由映射
首先删掉你添加的这条路由,OIDC中间件会自动处理CallbackPath对应的请求,不需要手动路由到控制器动作:
// 删掉这段代码 routes.MapRoute( name: "signin-oidc", url: "signin-oidc", defaults: new { controller = "Account", action = "ExternalLoginCallback" });
2. 统一OIDC配置中的路径格式
确保RedirectUri和CallbackPath的路径一致,且不要带多余的尾斜杠,避免路由匹配异常:
var settings = new OpenIdConnectAuthenticationOptions { // ...其他配置 RedirectUri = "https://localhost:44348/signin-oidc", CallbackPath = new PathString("/signin-oidc"), // ...其他配置 };
3. 调整认证中间件的顺序
Cookie认证必须在OIDC认证之前配置,因为OIDC依赖Cookie来保存用户会话:
// 先配置Cookie认证 app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = "Cookies", LoginPath = new PathString("/Account/Login"), }); // 再配置OIDC认证 app.UseOpenIdConnectAuthentication(settings);
4. 优化OIDC配置的获取方式
你手动用WebClient下载配置文件容易出问题,改成让中间件自动发现配置更可靠:
// 替换手动下载配置的代码 var settings = new OpenIdConnectAuthenticationOptions { Authority = "https://orders.data443.com/oauth/", MetadataAddress = "https://orders.data443.com/oauth/openid-configuration.php", // 去掉手动设置的Configuration,让中间件自动拉取 // ...其他配置保持不变 };
5. 修正ExternalLoginCallback的触发逻辑
用户登录应该先触发OIDC挑战,中间件完成认证后再跳转到你的回调动作。示例代码如下:
// AccountController中的ExternalLogin动作(触发挑战) [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public ActionResult ExternalLogin(string provider, string returnUrl) { // 重定向到外部认证提供程序,完成后跳转到指定回调 return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl })); } // ExternalLoginCallback动作(处理认证结果) [AllowAnonymous] public async Task<ActionResult> ExternalLoginCallback(string returnUrl) { var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(); if (loginInfo == null) { return RedirectToAction("Login"); } // 这里添加你的登录逻辑:比如关联本地用户、创建会话等 var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false); switch (result) { case SignInStatus.Success: return RedirectToLocal(returnUrl); default: ViewBag.ReturnUrl = returnUrl; ViewBag.LoginProvider = loginInfo.Login.LoginProvider; return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = loginInfo.Email }); } }
额外排查点
- 确认浏览器中的
OpenIdConnect.nonceCookie存在且有效,没有跨域或路径错误; - 检查
ResponseType = OpenIdConnectResponseType.Code和Scope = "openid email profile"的配置是否正确,这是OIDC认证的必要参数; - 如果你需要验证发行方,把
TokenValidationParameters.ValidateIssuer设为true并指定ValidIssuers,当前设为false要确保符合你的业务场景。
内容的提问来源于stack exchange,提问作者Damien
相关产品推荐
相关产品推荐

