1
0
mirror of https://github.com/bitwarden/server.git synced 2024-11-24 12:35:25 +01:00

EC-198 Added feature flag for 2FA Email for new device login (#1993)

* EC-198 added global setting flag for 2FA email on new device login feature

* EC-198 Removed is development environment check on 2FA email new device login given that we can now rely on the global settings feature flag

* EC-198 Improved IGlobalSettings and UserService code for testing
This commit is contained in:
Federico Maccaroni 2022-05-13 10:48:48 -03:00 committed by GitHub
parent bbb55ef8de
commit 2e2d3075d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 28 additions and 21 deletions

View File

@ -17,9 +17,7 @@ using Bit.Core.Utilities;
using Fido2NetLib;
using Fido2NetLib.Objects;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using File = System.IO.File;
@ -50,11 +48,10 @@ namespace Bit.Core.Services
private readonly IReferenceEventService _referenceEventService;
private readonly IFido2 _fido2;
private readonly ICurrentContext _currentContext;
private readonly GlobalSettings _globalSettings;
private readonly IGlobalSettings _globalSettings;
private readonly IOrganizationService _organizationService;
private readonly IProviderUserRepository _providerUserRepository;
private readonly IDeviceRepository _deviceRepository;
private readonly IWebHostEnvironment _environment;
public UserService(
IUserRepository userRepository,
@ -81,11 +78,10 @@ namespace Bit.Core.Services
IReferenceEventService referenceEventService,
IFido2 fido2,
ICurrentContext currentContext,
GlobalSettings globalSettings,
IGlobalSettings globalSettings,
IOrganizationService organizationService,
IProviderUserRepository providerUserRepository,
IDeviceRepository deviceRepository,
IWebHostEnvironment environment)
IDeviceRepository deviceRepository)
: base(
store,
optionsAccessor,
@ -121,7 +117,6 @@ namespace Bit.Core.Services
_organizationService = organizationService;
_providerUserRepository = providerUserRepository;
_deviceRepository = deviceRepository;
_environment = environment;
}
public Guid? GetProperUserId(ClaimsPrincipal principal)
@ -1422,9 +1417,9 @@ namespace Bit.Core.Services
public async Task<bool> Needs2FABecauseNewDeviceAsync(User user, string deviceIdentifier, string grantType)
{
return user.EmailVerified
return _globalSettings.TwoFactorAuth.EmailOnNewDeviceLogin
&& user.EmailVerified
&& grantType != "authorization_code"
&& !_environment.IsDevelopment()
&& await IsNewDeviceAndNotTheFirstOneAsync(user, deviceIdentifier);
}

View File

@ -69,6 +69,7 @@ namespace Bit.Core.Settings
public virtual AppleIapSettings AppleIap { get; set; } = new AppleIapSettings();
public virtual SsoSettings Sso { get; set; } = new SsoSettings();
public virtual StripeSettings Stripe { get; set; } = new StripeSettings();
public virtual ITwoFactorAuthSettings TwoFactorAuth { get; set; } = new TwoFactorAuthSettings();
public string BuildExternalUri(string explicitValue, string name)
{
@ -480,5 +481,10 @@ namespace Bit.Core.Settings
public string ApiKey { get; set; }
public int MaxNetworkRetries { get; set; } = 2;
}
public class TwoFactorAuthSettings : ITwoFactorAuthSettings
{
public bool EmailOnNewDeviceLogin { get; set; } = true;
}
}
}

View File

@ -1,6 +1,4 @@
using static Bit.Core.Settings.GlobalSettings;
namespace Bit.Core.Settings
namespace Bit.Core.Settings
{
public interface IGlobalSettings
{
@ -10,9 +8,11 @@ namespace Bit.Core.Settings
string LicenseDirectory { get; set; }
string LicenseCertificatePassword { get; set; }
int OrganizationInviteExpirationHours { get; set; }
bool DisableUserRegistration { get; set; }
IInstallationSettings Installation { get; set; }
IFileStorageSettings Attachment { get; set; }
IConnectionStringSettings Storage { get; set; }
IBaseServiceUriSettings BaseServiceUri { get; set; }
ITwoFactorAuthSettings TwoFactorAuth { get; set; }
}
}

View File

@ -0,0 +1,7 @@
namespace Bit.Core.Settings
{
public interface ITwoFactorAuthSettings
{
bool EmailOnNewDeviceLogin { get; set; }
}
}

View File

@ -12,9 +12,7 @@ using Bit.Core.Services;
using Bit.Test.Common.AutoFixture;
using Bit.Test.Common.AutoFixture.Attributes;
using Bit.Test.Common.Helpers;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Hosting;
using NSubstitute;
using NSubstitute.ReceivedExtensions;
using Xunit;
@ -38,8 +36,8 @@ namespace Bit.Core.Test.Services
user.EmailVerified = true;
user.Email = userLicense.Email;
sutProvider.GetDependency<Settings.GlobalSettings>().SelfHosted = true;
sutProvider.GetDependency<Settings.GlobalSettings>().LicenseDirectory = tempDir.Directory;
sutProvider.GetDependency<Settings.IGlobalSettings>().SelfHosted = true;
sutProvider.GetDependency<Settings.IGlobalSettings>().LicenseDirectory = tempDir.Directory;
sutProvider.GetDependency<ILicensingService>()
.VerifyLicense(userLicense)
.Returns(true);
@ -175,6 +173,9 @@ namespace Bit.Core.Test.Services
new Device { Identifier = deviceIdInRepo }
}));
sutProvider.GetDependency<Settings.IGlobalSettings>().TwoFactorAuth.EmailOnNewDeviceLogin.Returns(true);
Assert.True(await sutProvider.Sut.Needs2FABecauseNewDeviceAsync(user, deviceIdToCheck, "password"));
}
@ -246,7 +247,7 @@ namespace Bit.Core.Test.Services
}
[Theory, CustomAutoData(typeof(SutProviderCustomization))]
public async Task Needs2FABecauseNewDeviceAsync_ReturnsFalse_When_Environment_Is_Development(SutProvider<UserService> sutProvider, User user)
public async Task Needs2FABecauseNewDeviceAsync_ReturnsFalse_When_GlobalSettings_2FA_EmailOnNewDeviceLogin_Is_Disabled(SutProvider<UserService> sutProvider, User user)
{
user.Id = Guid.NewGuid();
user.EmailVerified = true;
@ -260,9 +261,7 @@ namespace Bit.Core.Test.Services
new Device { Identifier = deviceIdInRepo }
}));
sutProvider.GetDependency<IWebHostEnvironment>()
.EnvironmentName
.Returns(Environments.Development);
sutProvider.GetDependency<Settings.IGlobalSettings>().TwoFactorAuth.EmailOnNewDeviceLogin.Returns(false);
Assert.False(await sutProvider.Sut.Needs2FABecauseNewDeviceAsync(user, deviceIdToCheck, "password"));
}