Microsoft Identity 2 SignInManager 从不返回 VerificationRequired

Posted

技术标签:

【中文标题】Microsoft Identity 2 SignInManager 从不返回 VerificationRequired【英文标题】:Microsoft Identity 2 SignInManager never returns VerificationRequired 【发布时间】:2019-08-11 00:11:13 【问题描述】:

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

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

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

我的问题

SignInManager 在使用 PasswordSignIn 时从不返回 RequiresVerification 我假设当每个用户在数据库中将“TwoFactorEnabled”标志设置为 true 时,我应该期待这种登录状态。我不确定我是否应该使用它,如果我只希望用户每两周通过一次 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。

如果用户已经“使用用户名和密码成功登录”,我如何防止用户直接从验证屏幕跳到其他页面 他们现在不能绕过 Authorization 属性吗?

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

我做了什么 我有标准/默认身份设置,所以我们几乎使用新 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;

非常感谢您的任何帮助。

【问题讨论】:

只是为了确认:在您的浏览器中设置了第一级身份验证后的cookies吗?如果应用程序使用 google chrome 在开发模式下运行,您将无法为 localhost 域设置 cookie。你需要有一个注册表控制的域。这是 chrome 中的一个已知安全问题。尝试在其他浏览器上运行。参考问题:bugs.chromium.org/p/chromium/issues/detail?id=56211 另一方面,您可以在 proect 属性中将应用程序的 SSL 设置为 true,并将 https 链接复制到您的 Web 属性以规避问题,以便能够在 chrome 中工作 @bhanu.cs 我现在要做的是: 1. 用户在 AJAX 请求中将用户名和密码发送到名为 login 的 JsonResult 方法。 2. 在此方法中,我使用 SignInManager 执行登录。我将 SignInStatus 和 ApplicationUser 传递给打开 SignInStatus 的方法。 3.如果 SignInStatus 为 Success,我现在只需检查用户的声明值,其中包含日期。如果日期超过 30 天,我会向他们发送一个密码并重定向到验证代码页面,他们必须在其中输入密码。此外,如果是这种情况,我没有为用户设置任何会话变量,但我已经执行了 PasswordSignIn,这可能有问题?当他们提交他们的 pin 码时,我只设置了一个包含他们的 UserId 的 Session 变量。 哦,我明白了,这是您想到的一个聪明的解决方法。但是在第 3 步中,由于 2FA 已启用,SignInManager 返回 RequireVerification 状态,并且在 2FA 完成之前不会生成 auth cookie(尽管生成了其他中间 cookie,但我不确定这一点),这将使您无法通过身份验证。您是否考虑过这个案例?简而言之,如果在提供电话代码或电子邮件代码之前启用 2FA,您可能无法通过身份验证。 【参考方案1】:

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

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

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

【讨论】:

以上是关于Microsoft Identity 2 SignInManager 从不返回 VerificationRequired的主要内容,如果未能解决你的问题,请参考以下文章

The identity used to sign the executable is no longer valid.

Xcode真机调试失败:The identity used to sign the executable is no longer valid

修改AD FS

更新 Microsoft.AspNet.Identity.Owin 2.2.0 后启动时处理 Ninject 内核

the identity used to sign the executable is no longer valid.解决方法

Microsoft.AspNet.Identity 2.0 用账号或者邮件作为登陆方式