Microsoft Identity 2 SignInManager 从不 returns VerificationRequired

Microsoft Identity 2 SignInManager never returns VerificationRequired

我正在尝试使用电子邮件中发送的个人识别码添加双因素身份验证。用户仅在上次完成 2FA 步骤 30 天后才需要执行 2FA 步骤。

项目的技术是 ASP.NET MVC 5 使用 EntityFramework 6 和 Microsoft.AspNet.Identity 包的 NuGet 包版本 2.2.2(.Core,.EntityFramework,.Owin ).

我一直遵循本教程中的建议,但将其集成到我公司现有的解决方案中:https://docs.microsoft.com/en-us/aspnet/identity/overview/features-api/two-factor-authentication-using-sms-and-email-with-aspnet-identity

我的问题

SignInManager 从不 returns 使用 PasswordSignIn 时需要验证 当 "TwoFactorEnabled" 标志在每个用户的数据库中设置为 true 时,我假设我应该期待这个登录状态。我不确定是否应该使用它,如果我只希望用户每 2 周进行一次 2FA 验证,因为我的印象是它会要求用户每次都进行一次。要么,要么我应该使用对用户设置的时间戳来确定是否该重新启用 "TwoFactorEnabled" 标志?

我在验证码时无法检索到已验证用户的ID 我认为在执行正常的 PasswordSignIn 之后,服务器将能够检索用户的 ID,例如在验证输入的 pin 码是否正确时:

[HttpPost]
    [AllowAnonymous]
    public async Task<ActionResult> VerifyCode(string pin)
    {
        string userId = await SignInManager.GetVerifiedUserIdAsync().WithCurrentCulture();

        if (userId == null || String.IsNullOrEmpty(pin))
        {
            return View("Error");
        }

        var user = await UserManager.FindByIdAsync(userId);

        if (await UserManager.VerifyTwoFactorTokenAsync(user.Id, "EmailCode", pin))
        {
            await SignInManager.SignInAsync(user, false, false);
            return RedirectToAction("Index", "Dashboards");
        }
        else
        {
            ModelState.AddModelError("", "Invalid code");
        }

        return View();
    }

这有点令人困惑,因为大多数教程都很老,并且使用我以前从未见过的 AuthenticationManager。

如果用户已经 "successfully logged in with username and password",我如何防止他们简单地从验证屏幕跳到其他页面 此时他们不能绕过授权属性吗?

已经有效的方法 我可以让 UserManager 发送一封带有令牌(密码)的电子邮件,如果我输入正确的用户 ID,它将成功验证

我做了什么 我有 standard/default Identity 设置,所以我们几乎使用新 MVC 5 项目附带的标准配置。

Startup.Auth:

// Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.
        app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(10));

        // Enables the application to remember the second login verification factor such as phone or email.
        // Once you check this option, your second step of verification during the login process will be remembered on the device where you logged in from.
        // This is similar to the RememberMe option when you log in.
        app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);

ApplicationUserManager 中的 2FA 提供程序设置:

        manager.RegisterTwoFactorProvider("EmailCode", new EmailTokenProvider<ApplicationUser>
        {
            Subject = "Security Code",
            BodyFormat = "Your security code is {0}"
        });

        manager.EmailService = new EmailService();
        //manager.SmsService = new SmsService();
        var dataProtectionProvider = options.DataProtectionProvider;
        if (dataProtectionProvider != null)
        {
            manager.UserTokenProvider =
                new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
        }

        return manager;

非常感谢您的帮助。

我想我可能已经弄清楚问题出在哪里了。 UserManager 为 GetValidTwoFactorProvidersAsync 返回 0。当用户未确认电子邮件时,似乎会发生这种情况。我尝试为用户确认设置电子邮件,现在返回 RequiresVerification。

当返回 RequiresVerification 时,用户似乎没有完全登录,但我仍然能够使用 SignInManager 的 GetVerifiedUserId 方法在后续代码验证调用中获取用户 ID。

所以现在,当用户登录时,在执行密码登录之前,我只是执行检查以查看用户上次完成 2FA 身份验证的时间。如果超过 30 天,我会在数据库中重新启用 2FA 标志。然后,当执行密码登录时,我将按预期获得 RequiresVerification,并且我可以继续流程的其余部分,否则任何标准 2FA 验证都需要。