You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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.nonce Cookie存在且有效,没有跨域或路径错误;
  • 检查ResponseType = OpenIdConnectResponseType.Code和Scope = "openid email profile"的配置是否正确,这是OIDC认证的必要参数;
  • 如果你需要验证发行方,把TokenValidationParameters.ValidateIssuer设为true并指定ValidIssuers,当前设为false要确保符合你的业务场景。

内容的提问来源于stack exchange,提问作者Damien

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 12:47:41