1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-01 08:02:49 -05:00

feat(2FA): [PM-17129] Login with 2FA Recovery Code

* feat(2FA): [PM-17129] Login with 2FA Recovery Code - Login with Recovery Code working.

* feat(2FA): [PM-17129] Login with 2FA Recovery Code - Feature flagged implementation.

* style(2FA): [PM-17129] Login with 2FA Recovery Code - Code cleanup.

* test(2FA): [PM-17129] Login with 2FA Recovery Code - Tests.
This commit is contained in:
Patrick-Pimentel-Bitwarden
2025-02-13 15:51:36 -05:00
committed by GitHub
parent 465549b812
commit ac6bc40d85
10 changed files with 220 additions and 76 deletions

View File

@ -1,4 +1,5 @@
using Bit.Core.AdminConsole.Entities;
using Bit.Core;
using Bit.Core.AdminConsole.Entities;
using Bit.Core.Auth.Enums;
using Bit.Core.Auth.Identity.TokenProviders;
using Bit.Core.Auth.Models.Business.Tokenables;
@ -328,7 +329,7 @@ public class TwoFactorAuthenticationValidatorTests
_userManager.TWO_FACTOR_PROVIDERS = ["email"];
// Act
var result = await _sut.VerifyTwoFactor(
var result = await _sut.VerifyTwoFactorAsync(
user, null, TwoFactorProviderType.U2f, token);
// Assert
@ -348,7 +349,7 @@ public class TwoFactorAuthenticationValidatorTests
_userManager.TWO_FACTOR_PROVIDERS = ["email"];
// Act
var result = await _sut.VerifyTwoFactor(
var result = await _sut.VerifyTwoFactorAsync(
user, null, TwoFactorProviderType.Email, token);
// Assert
@ -368,7 +369,7 @@ public class TwoFactorAuthenticationValidatorTests
_userManager.TWO_FACTOR_PROVIDERS = ["OrganizationDuo"];
// Act
var result = await _sut.VerifyTwoFactor(
var result = await _sut.VerifyTwoFactorAsync(
user, null, TwoFactorProviderType.OrganizationDuo, token);
// Assert
@ -394,7 +395,7 @@ public class TwoFactorAuthenticationValidatorTests
_userManager.TWO_FACTOR_TOKEN_VERIFIED = true;
// Act
var result = await _sut.VerifyTwoFactor(user, null, providerType, token);
var result = await _sut.VerifyTwoFactorAsync(user, null, providerType, token);
// Assert
Assert.True(result);
@ -419,7 +420,7 @@ public class TwoFactorAuthenticationValidatorTests
_userManager.TWO_FACTOR_TOKEN_VERIFIED = false;
// Act
var result = await _sut.VerifyTwoFactor(user, null, providerType, token);
var result = await _sut.VerifyTwoFactorAsync(user, null, providerType, token);
// Assert
Assert.False(result);
@ -445,13 +446,56 @@ public class TwoFactorAuthenticationValidatorTests
organization.Enabled = true;
// Act
var result = await _sut.VerifyTwoFactor(
var result = await _sut.VerifyTwoFactorAsync(
user, organization, providerType, token);
// Assert
Assert.True(result);
}
[Theory]
[BitAutoData(TwoFactorProviderType.RecoveryCode)]
public async void VerifyTwoFactorAsync_RecoveryCode_ValidToken_ReturnsTrue(
TwoFactorProviderType providerType,
User user,
Organization organization)
{
var token = "1234";
user.TwoFactorRecoveryCode = token;
_userService.RecoverTwoFactorAsync(Arg.Is(user), Arg.Is(token)).Returns(true);
_featureService.IsEnabled(FeatureFlagKeys.RecoveryCodeLogin).Returns(true);
// Act
var result = await _sut.VerifyTwoFactorAsync(
user, organization, providerType, token);
// Assert
Assert.True(result);
}
[Theory]
[BitAutoData(TwoFactorProviderType.RecoveryCode)]
public async void VerifyTwoFactorAsync_RecoveryCode_InvalidToken_ReturnsFalse(
TwoFactorProviderType providerType,
User user,
Organization organization)
{
// Arrange
var token = "1234";
user.TwoFactorRecoveryCode = token;
_userService.RecoverTwoFactorAsync(Arg.Is(user), Arg.Is(token)).Returns(false);
_featureService.IsEnabled(FeatureFlagKeys.RecoveryCodeLogin).Returns(true);
// Act
var result = await _sut.VerifyTwoFactorAsync(
user, organization, providerType, token);
// Assert
Assert.False(result);
}
private static UserManagerTestWrapper<User> SubstituteUserManager()
{
return new UserManagerTestWrapper<User>(