diff --git a/src/Admin/Views/Users/Index.cshtml b/src/Admin/Views/Users/Index.cshtml index e55f5c8107..98847d5096 100644 --- a/src/Admin/Views/Users/Index.cshtml +++ b/src/Admin/Views/Users/Index.cshtml @@ -69,7 +69,7 @@ { } - @if(await user.TwoFactorIsEnabledAsync(userService)) + @if(await userService.TwoFactorIsEnabledAsync(user)) { } diff --git a/src/Admin/Views/Users/_ViewInformation.cshtml b/src/Admin/Views/Users/_ViewInformation.cshtml index 7244dd6829..67cb8eba98 100644 --- a/src/Admin/Views/Users/_ViewInformation.cshtml +++ b/src/Admin/Views/Users/_ViewInformation.cshtml @@ -14,7 +14,7 @@
@(Model.User.EmailVerified ? "Yes" : "No")
Using 2FA
-
@(await Model.User.TwoFactorIsEnabledAsync(userService) ? "Yes" : "No")
+
@(await userService.TwoFactorIsEnabledAsync(Model.User) ? "Yes" : "No")
Items
@Model.CipherCount
diff --git a/src/Api/Controllers/AccountsController.cs b/src/Api/Controllers/AccountsController.cs index a475918e3b..7400197952 100644 --- a/src/Api/Controllers/AccountsController.cs +++ b/src/Api/Controllers/AccountsController.cs @@ -307,7 +307,7 @@ namespace Bit.Api.Controllers var organizationUserDetails = await _organizationUserRepository.GetManyDetailsByUserAsync(user.Id, OrganizationUserStatusType.Confirmed); var response = new ProfileResponseModel(user, organizationUserDetails, - await user.TwoFactorIsEnabledAsync(_userService)); + await _userService.TwoFactorIsEnabledAsync(user)); return response; } @@ -332,7 +332,7 @@ namespace Bit.Api.Controllers } await _userService.SaveUserAsync(model.ToUser(user)); - var response = new ProfileResponseModel(user, null, await user.TwoFactorIsEnabledAsync(_userService)); + var response = new ProfileResponseModel(user, null, await _userService.TwoFactorIsEnabledAsync(user)); return response; } @@ -462,7 +462,7 @@ namespace Bit.Api.Controllers await _userService.SignUpPremiumAsync(user, model.PaymentToken, model.AdditionalStorageGb.GetValueOrDefault(0), license); - return new ProfileResponseModel(user, null, await user.TwoFactorIsEnabledAsync(_userService)); + return new ProfileResponseModel(user, null, await _userService.TwoFactorIsEnabledAsync(user)); } [HttpGet("billing")] diff --git a/src/Api/Controllers/SyncController.cs b/src/Api/Controllers/SyncController.cs index b272ec340d..ad961da52c 100644 --- a/src/Api/Controllers/SyncController.cs +++ b/src/Api/Controllers/SyncController.cs @@ -69,7 +69,7 @@ namespace Bit.Api.Controllers collectionCiphersGroupDict = collectionCiphers.GroupBy(c => c.CipherId).ToDictionary(s => s.Key); } - var userTwoFactorEnabled = await user.TwoFactorIsEnabledAsync(_userService); + var userTwoFactorEnabled = await _userService.TwoFactorIsEnabledAsync(user); var response = new SyncResponseModel(_globalSettings, user, userTwoFactorEnabled, organizationUserDetails, folders, collections, ciphers, collectionCiphersGroupDict, excludeDomains); return response; diff --git a/src/Api/web.config b/src/Api/web.config index ac273d18b2..4dcf28ca24 100644 --- a/src/Api/web.config +++ b/src/Api/web.config @@ -4,7 +4,9 @@ - + + + diff --git a/src/Core/Identity/AuthenticatorTokenProvider.cs b/src/Core/Identity/AuthenticatorTokenProvider.cs index e7bcd789ec..bccfc9f713 100644 --- a/src/Core/Identity/AuthenticatorTokenProvider.cs +++ b/src/Core/Identity/AuthenticatorTokenProvider.cs @@ -25,8 +25,8 @@ namespace Bit.Core.Identity { return false; } - return await user.TwoFactorProviderIsEnabledAsync(TwoFactorProviderType.Authenticator, - _serviceProvider.GetRequiredService()); + return await _serviceProvider.GetRequiredService() + .TwoFactorProviderIsEnabledAsync(TwoFactorProviderType.Authenticator, user); } public Task GenerateAsync(string purpose, UserManager manager, User user) diff --git a/src/Core/Identity/DuoWebTokenProvider.cs b/src/Core/Identity/DuoWebTokenProvider.cs index a651bed5e7..aff9cff938 100644 --- a/src/Core/Identity/DuoWebTokenProvider.cs +++ b/src/Core/Identity/DuoWebTokenProvider.cs @@ -37,7 +37,7 @@ namespace Bit.Core.Identity return false; } - return await user.TwoFactorProviderIsEnabledAsync(TwoFactorProviderType.Duo, userService); + return await userService.TwoFactorProviderIsEnabledAsync(TwoFactorProviderType.Duo, user); } public async Task GenerateAsync(string purpose, UserManager manager, User user) diff --git a/src/Core/Identity/ReadOnlyDatabaseIdentityUserStore.cs b/src/Core/Identity/ReadOnlyDatabaseIdentityUserStore.cs index adacc3a86e..751477e23a 100644 --- a/src/Core/Identity/ReadOnlyDatabaseIdentityUserStore.cs +++ b/src/Core/Identity/ReadOnlyDatabaseIdentityUserStore.cs @@ -24,7 +24,7 @@ namespace Bit.Core.Identity CancellationToken cancellationToken = default(CancellationToken)) { var user = await _userRepository.GetByEmailAsync(normalizedEmail); - return user?.ToIdentityUser(await user.TwoFactorIsEnabledAsync(_userService)); + return user?.ToIdentityUser(await _userService.TwoFactorIsEnabledAsync(user)); } public override async Task FindByIdAsync(string userId, @@ -36,7 +36,7 @@ namespace Bit.Core.Identity } var user = await _userRepository.GetByIdAsync(userIdGuid); - return user?.ToIdentityUser(await user.TwoFactorIsEnabledAsync(_userService)); + return user?.ToIdentityUser(await _userService.TwoFactorIsEnabledAsync(user)); } } } diff --git a/src/Core/Identity/U2fTokenProvider.cs b/src/Core/Identity/U2fTokenProvider.cs index 2822d1c017..70d6872a1f 100644 --- a/src/Core/Identity/U2fTokenProvider.cs +++ b/src/Core/Identity/U2fTokenProvider.cs @@ -47,7 +47,7 @@ namespace Bit.Core.Identity return false; } - return await user.TwoFactorProviderIsEnabledAsync(TwoFactorProviderType.U2f, userService); + return await userService.TwoFactorProviderIsEnabledAsync(TwoFactorProviderType.U2f, user); } public async Task GenerateAsync(string purpose, UserManager manager, User user) diff --git a/src/Core/Identity/UserStore.cs b/src/Core/Identity/UserStore.cs index 33096fa0b2..be0dab2002 100644 --- a/src/Core/Identity/UserStore.cs +++ b/src/Core/Identity/UserStore.cs @@ -169,7 +169,7 @@ namespace Bit.Core.Identity public async Task GetTwoFactorEnabledAsync(User user, CancellationToken cancellationToken) { - return await user.TwoFactorIsEnabledAsync(_serviceProvider.GetRequiredService()); + return await _serviceProvider.GetRequiredService().TwoFactorIsEnabledAsync(user); } public Task SetSecurityStampAsync(User user, string stamp, CancellationToken cancellationToken) diff --git a/src/Core/Identity/YubicoOtpTokenProvider.cs b/src/Core/Identity/YubicoOtpTokenProvider.cs index 1bd19487ef..fdcbff77b3 100644 --- a/src/Core/Identity/YubicoOtpTokenProvider.cs +++ b/src/Core/Identity/YubicoOtpTokenProvider.cs @@ -37,7 +37,7 @@ namespace Bit.Core.Identity return false; } - return await user.TwoFactorProviderIsEnabledAsync(TwoFactorProviderType.YubiKey, userService); + return await userService.TwoFactorProviderIsEnabledAsync(TwoFactorProviderType.YubiKey, user); } public Task GenerateAsync(string purpose, UserManager manager, User user) diff --git a/src/Core/IdentityServer/ResourceOwnerPasswordValidator.cs b/src/Core/IdentityServer/ResourceOwnerPasswordValidator.cs index f1a29ca39f..6c02fc2ec8 100644 --- a/src/Core/IdentityServer/ResourceOwnerPasswordValidator.cs +++ b/src/Core/IdentityServer/ResourceOwnerPasswordValidator.cs @@ -164,7 +164,7 @@ namespace Bit.Core.IdentityServer { foreach(var p in user.GetTwoFactorProviders()) { - if(await user.TwoFactorProviderIsEnabledAsync(p.Key, _userService)) + if(await _userService.TwoFactorProviderIsEnabledAsync(p.Key, user)) { enabledProviders.Add(p); } @@ -279,13 +279,13 @@ namespace Bit.Core.IdentityServer case TwoFactorProviderType.U2f: case TwoFactorProviderType.Remember: if(type != TwoFactorProviderType.Remember && - !(await user.TwoFactorProviderIsEnabledAsync(type, _userService))) + !(await _userService.TwoFactorProviderIsEnabledAsync(type, user))) { return false; } return await _userManager.VerifyTwoFactorTokenAsync(user, type.ToString(), token); case TwoFactorProviderType.Email: - if(!(await user.TwoFactorProviderIsEnabledAsync(type, _userService))) + if(!(await _userService.TwoFactorProviderIsEnabledAsync(type, user))) { return false; } @@ -311,7 +311,7 @@ namespace Bit.Core.IdentityServer case TwoFactorProviderType.U2f: case TwoFactorProviderType.Email: case TwoFactorProviderType.YubiKey: - if(!(await user.TwoFactorProviderIsEnabledAsync(type, _userService))) + if(!(await _userService.TwoFactorProviderIsEnabledAsync(type, user))) { return null; } diff --git a/src/Core/Models/Table/User.cs b/src/Core/Models/Table/User.cs index b156108e7a..cffa45add3 100644 --- a/src/Core/Models/Table/User.cs +++ b/src/Core/Models/Table/User.cs @@ -92,48 +92,6 @@ namespace Bit.Core.Models.Table _twoFactorProviders = providers; } - public async Task TwoFactorProviderIsEnabledAsync(TwoFactorProviderType provider, - IUserService userService) - { - var providers = GetTwoFactorProviders(); - if(providers == null || !providers.ContainsKey(provider) || !providers[provider].Enabled) - { - return false; - } - - if(!TwoFactorProvider.RequiresPremium(provider)) - { - return true; - } - - return await userService.CanAccessPremium(this); - } - - public async Task TwoFactorIsEnabledAsync(IUserService userService) - { - var providers = GetTwoFactorProviders(); - if(providers == null) - { - return false; - } - - foreach(var p in providers) - { - if(p.Value?.Enabled ?? false) - { - if(!TwoFactorProvider.RequiresPremium(p.Key)) - { - return true; - } - if(await userService.CanAccessPremium(this)) - { - return true; - } - } - } - return false; - } - public TwoFactorProvider GetTwoFactorProvider(TwoFactorProviderType provider) { var providers = GetTwoFactorProviders(); diff --git a/src/Core/Services/IUserService.cs b/src/Core/Services/IUserService.cs index a69fd10ca1..a64d24d895 100644 --- a/src/Core/Services/IUserService.cs +++ b/src/Core/Services/IUserService.cs @@ -55,5 +55,7 @@ namespace Bit.Core.Services Task GenerateLicenseAsync(User user, BillingInfo billingInfo = null); Task CheckPasswordAsync(User user, string password); Task CanAccessPremium(User user); + Task TwoFactorIsEnabledAsync(User user); + Task TwoFactorProviderIsEnabledAsync(TwoFactorProviderType provider, User user); } } diff --git a/src/Core/Services/Implementations/UserService.cs b/src/Core/Services/Implementations/UserService.cs index 0748743317..0ebf0daf65 100644 --- a/src/Core/Services/Implementations/UserService.cs +++ b/src/Core/Services/Implementations/UserService.cs @@ -916,6 +916,47 @@ namespace Bit.Core.Services orgAbilities[o.Id].UsersGetPremium && orgAbilities[o.Id].Enabled); } + public async Task TwoFactorIsEnabledAsync(User user) + { + var providers = user.GetTwoFactorProviders(); + if(providers == null) + { + return false; + } + + foreach(var p in providers) + { + if(p.Value?.Enabled ?? false) + { + if(!TwoFactorProvider.RequiresPremium(p.Key)) + { + return true; + } + if(await CanAccessPremium(user)) + { + return true; + } + } + } + return false; + } + + public async Task TwoFactorProviderIsEnabledAsync(TwoFactorProviderType provider, User user) + { + var providers = user.GetTwoFactorProviders(); + if(providers == null || !providers.ContainsKey(provider) || !providers[provider].Enabled) + { + return false; + } + + if(!TwoFactorProvider.RequiresPremium(provider)) + { + return true; + } + + return await CanAccessPremium(user); + } + private async Task UpdatePasswordHash(User user, string newPassword, bool validatePassword = true, bool refreshStamp = true) {