SignInManager 在 TwoFactorAuthenticatorSignInAsync() 和 TwoFactorSignInAsync() 中始终失败。

huangapple go评论79阅读模式
英文:

SignInManager always fails for TwoFactorAuthenticatorSignInAsync() and TwoFactorSignInAsync()

问题

背景

我正在使用.NET 6构建一个API,在其中尝试实现使用Google Authenticator的双因素身份验证。一切都运行正常,直到我尝试使用认证器应用程序提供的代码进行登录的最后步骤。

代码

双因素身份验证设置 - 第一部分:

[HttpGet("TwoFactorAuthSetup/{email}")]
public async Task<IActionResult> GetTwoFactorAuthSetup(string email)
{
    ...
    var isTwoFactorAuthEnabled = await _userManager.GetTwoFactorEnabledAsync(user);
    var authenticatorKey = await _userManager.GetAuthenticatorKeyAsync(user);

    if (authenticatorKey == null)
    {
        await _userManager.ResetAuthenticatorKeyAsync(user);
        authenticatorKey = await _userManager.GetAuthenticatorKeyAsync(user);
    }
    ...
}

双因素身份验证设置 - 第二部分:

[HttpPost("TwoFactorAuthSetup")]
public async Task<IActionResult> SetupTwoFactorAuth([FromBody] TwoFactorAuthSetupDto model)
{
    var user = await _userManager.FindByEmailAsync(model.Email);

    var isCodeValid = await _userManager
        .VerifyTwoFactorTokenAsync(user,
          _userManager.Options.Tokens.AuthenticatorTokenProvider,
          model.Code);

    if (!isCodeValid)
    {
        return BadRequest("Invalid code");
    }

    await _userManager.SetTwoFactorEnabledAsync(user, true);
    ...
}

双因素身份验证登录:

[HttpPost("login-2fa")]
[AllowAnonymous]
public async Task<IActionResult> LoginWithTwoFactorAuth(TwoFactorAuthSetupDto model)
{
    var user = await _userManager.FindByEmailAsync(model.Email);

    if (user == null)
    {
        return Unauthorized();
    }

    var result = await _signInManager.TwoFactorSignInAsync(_userManager.Options.Tokens.AuthenticatorTokenProvider, model.Code, true, false);
    var result2 = await _signInManager.TwoFactorAuthenticatorSignInAsync(model.Code, true, false);
}

双因素身份验证设置的第一部分和第二部分按预期运行;我能够在我的应用程序中成功设置authenticatorKey,并且控制器能够接受6位代码。

问题出现在尝试使用认证器应用程序登录时。无论是result还是result2最终都为Succeeded = false。当我尝试使用_userManager.VerifyTwoFactorTokenAsync方法时,它确实显示我使用的代码是有效的。我不确定该如何继续。

英文:

Background

I'm building an API with .NET 6 where I'm currently trying to implement two factor authentication using Google Authenticator. It seems to be working fine up until the final part where I actually try to sign in using the code provided by the authenticator app.

Code

2FA Setup - Part 1:

[HttpGet("TwoFactorAuthSetup/{email}")]
public async Task<IActionResult> GetTwoFactorAuthSetup(string email)
{
    ...
    var isTwoFactorAuthEnabled = await _userManager.GetTwoFactorEnabledAsync(user);
    var authenticatorKey = await _userManager.GetAuthenticatorKeyAsync(user);
    //var authenticatorKey = await _userManager.GenerateNewAuthenticatorKey(user);

    if (authenticatorKey == null)
    {
        await _userManager.ResetAuthenticatorKeyAsync(user);
        authenticatorKey = await _userManager.GetAuthenticatorKeyAsync(user);
    }
    ...

2FA Setup - Part 2:

[HttpPost("TwoFactorAuthSetup")]
public async Task<IActionResult> SetupTwoFactorAuth([FromBody] TwoFactorAuthSetupDto model)
{
    var user = await _userManager.FindByEmailAsync(model.Email);

    var isCodeValid = await _userManager
        .VerifyTwoFactorTokenAsync(user,
          _userManager.Options.Tokens.AuthenticatorTokenProvider,
          model.Code);

    if (!isCodeValid)
    {
        return BadRequest("Invalid code");
    }

    await _userManager.SetTwoFactorEnabledAsync(user, true);
    ...

2FA Login:

[HttpPost("login-2fa")]
[AllowAnonymous]
public async Task<IActionResult> LoginWithTwoFactorAuth(TwoFactorAuthSetupDto model)
{
    var user = await _userManager.FindByEmailAsync(model.Email);
    //user = await _signInManager.GetTwoFactorAuthenticationUserAsync();

    if (user == null)
    {
        return Unauthorized();
    }

    //var isValid = await _userManager.VerifyTwoFactorTokenAsync(user, _userManager.Options.Tokens.AuthenticatorTokenProvider, model.Code);
    var result = await _signInManager.TwoFactorSignInAsync(_userManager.Options.Tokens.AuthenticatorTokenProvider, model.Code, true, false);
    var result2 = await _signInManager.TwoFactorAuthenticatorSignInAsync( model.Code, true, false);

Both 2FA Setup - Part 1 and 2FA Setup - Part 2 work as expected; I'm able to successfully setup the authenticatorKey in my app, and the 6-digit code gets accepted by my controller.

The issue arises when trying to sign in using the authenticator app. Both result and result2 always end up with Succeeded = false. When I try to use the _userManager.VerifyTwoFactorTokenAsync method instead, it does show me that the code I use is valid. I'm unsure of how to proceed.

答案1

得分: 1

我弄清楚了。如果你有类似的问题,请考虑以下两个步骤:

  • 使用 _signInManager.PasswordSignInAsync 登录用户。这会生成一个 cookie,以便在用户选择记住我时记住用户。

  • 使用 var user = _signInManager.GetTwoFactorAuthenticationUserAsync() 来检查 Identity.TwoFactorUserId cookie 的存在。

我之前犯了一些错误:

  • 我使用了 _signInManager.CheckPasswordSignInAsync 而不是 _signInManager.PasswordSignInAsync
  • 我错误地使用了 var user = await _userManager.FindByEmailAsync(model.Email); 来获取需要执行两因素身份验证登录的用户。这存在安全风险。我后来用 await _signInManager.GetTwoFactorAuthenticationUserAsync() 替换了这一行。

通过上述更改,现在它按预期工作。

英文:

I figured it out. In case you have a similar issue, consider the following two steps -

  • Use _signInManager.PasswordSignInAsync to sign in the user. This drops a cookie that helps remember the user in case they had ticked the remember me.

  • Use var user = _signInManager.GetTwoFactorAuthenticationuserAsync() which checks for the presence of the Identity.TwoFactorUserId cookie.

I made few mistakes earlier:

  • I used _signInManager.CheckPasswordSignInAsync instead of _signInManager.PasswordSignInAsync.
  • I mistakenly used var user = await _userManager.FindByEmailAsync(model.Email); to get the user for which 2 factor auth login had to be performed. This provides a security risk. I since replaced this line with await _signInManager.GetTwoFactorAuthenticationUserAsync().

With the changes mentioned above it now works as intended.

huangapple
  • 本文由 发表于 2023年5月21日 06:01:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76297515.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定