如何在 ASP.NET Core Identity 中结合外部登录和双因素身份验证?

How can I combine external logins and two-factor authentication in ASP.NET Core Identity?

我正在为使用 ASP.NET Core 3.1 构建的简单 Web 应用程序实施身份验证和授权。到目前为止,ASP.NET Core Identity 满足要求,除了一个:外部登录的默认实现(在本例中,Google)似乎不适用于双因素身份验证的默认实现。

当我使用本地帐户(配置了 2FA)登录时,系统提示我输入 TOTP 令牌。当我使用Google账号登录时,没有提示输入第二个因素。我花了几天时间对此进行研究(例如 docs.microsoft.com、Google 以及此处的 SO),但没有发现任何有用的信息。如何让 ASP.NET 核心身份对使用 Google 登录的用户使用双因素身份验证?

先决条件:

  • 使用 ASP.NET Core Identity 的 ASP.NET Core 项目,其中一个或多个外部登录提供程序已经配置并正常工作,例如Google.

下面是我如何让它工作的。

  1. 使用Scaffold Identity procedure to override the Account/ExternalLogin page. (I also added that page to the Wayback Machine。谢谢,互联网档案馆!)
  2. 打开 ExternalLogin.cshtml.cs 文件并找到 OnGetCallbackAsync 方法。
  3. 找到对 _signInManager.ExternalLoginSignInAsync() 的调用并将 bypassTwoFactor 参数从 true 更改为 false。
  4. 找到检查 ExternalLoginSignInAsync() 结果的条件语句,并添加此代码:

        if (result.RequiresTwoFactor)
        {
            return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = false });
        }
    

把它们放在一起,你应该有这样的东西:

    // Sign in the user with this external login provider if the user already has a login.
    var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor : false);
    if (result.Succeeded)
    {
        _logger.LogInformation("{Name} logged in with {LoginProvider} provider.", info.Principal.Identity.Name, info.LoginProvider);
        return LocalRedirect(returnUrl);
    }
    if (result.RequiresTwoFactor)
    {
        return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = false });
    }
    if (result.IsLockedOut)
    {
        return RedirectToPage("./Lockout");
    }
    else
    {
        // existing code omitted for brevity
    }

注意:由于我无法找到有关如何执行此操作的任何文档或示例,我承认我的实施可能不是最佳的。如果您知道更好的方法,请分享!