mirror of
https://github.com/bitwarden/server.git
synced 2025-07-02 16:42:50 -05:00
Enforce 2fa policy (#654)
This commit is contained in:
@ -960,7 +960,8 @@ namespace Bit.Core.Services
|
||||
await _mailService.SendOrganizationInviteEmailAsync(org.Name, orgUser, token);
|
||||
}
|
||||
|
||||
public async Task<OrganizationUser> AcceptUserAsync(Guid organizationUserId, User user, string token)
|
||||
public async Task<OrganizationUser> AcceptUserAsync(Guid organizationUserId, User user, string token,
|
||||
IUserService userService)
|
||||
{
|
||||
var orgUser = await _organizationUserRepository.GetByIdAsync(organizationUserId);
|
||||
if(orgUser == null)
|
||||
@ -1005,6 +1006,16 @@ namespace Bit.Core.Services
|
||||
throw new BadRequestException("Invalid token.");
|
||||
}
|
||||
|
||||
if(!await userService.TwoFactorIsEnabledAsync(user))
|
||||
{
|
||||
var policies = await _policyRepository.GetManyByOrganizationIdAsync(orgUser.OrganizationId);
|
||||
if(policies.Any(p => p.Type == PolicyType.TwoFactorAuthentication && p.Enabled))
|
||||
{
|
||||
throw new BadRequestException("You cannot join this organization until you enable " +
|
||||
"two-step login on your user account.");
|
||||
}
|
||||
}
|
||||
|
||||
orgUser.Status = OrganizationUserStatusType.Accepted;
|
||||
orgUser.UserId = user.Id;
|
||||
orgUser.Email = null;
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Table;
|
||||
@ -25,7 +26,8 @@ namespace Bit.Core.Services
|
||||
_policyRepository = policyRepository;
|
||||
}
|
||||
|
||||
public async Task SaveAsync(Policy policy)
|
||||
public async Task SaveAsync(Policy policy, IUserService userService, IOrganizationService organizationService,
|
||||
Guid? savingUserId)
|
||||
{
|
||||
var org = await _organizationRepository.GetByIdAsync(policy.OrganizationId);
|
||||
if(org == null)
|
||||
@ -43,6 +45,28 @@ namespace Bit.Core.Services
|
||||
{
|
||||
policy.CreationDate = now;
|
||||
}
|
||||
else if(policy.Enabled)
|
||||
{
|
||||
var currentPolicy = await _policyRepository.GetByIdAsync(policy.Id);
|
||||
if(!currentPolicy?.Enabled ?? true)
|
||||
{
|
||||
if(currentPolicy.Type == Enums.PolicyType.TwoFactorAuthentication)
|
||||
{
|
||||
var orgUsers = await _organizationUserRepository.GetManyDetailsByOrganizationAsync(
|
||||
policy.OrganizationId);
|
||||
foreach(var orgUser in orgUsers.Where(ou =>
|
||||
ou.Status != Enums.OrganizationUserStatusType.Invited &&
|
||||
ou.Type != Enums.OrganizationUserType.Owner))
|
||||
{
|
||||
if(orgUser.UserId != savingUserId && !await userService.TwoFactorIsEnabledAsync(orgUser))
|
||||
{
|
||||
await organizationService.DeleteUserAsync(policy.OrganizationId, orgUser.Id,
|
||||
savingUserId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
policy.RevisionDate = DateTime.UtcNow;
|
||||
await _policyRepository.UpsertAsync(policy);
|
||||
await _eventService.LogPolicyEventAsync(policy, Enums.EventType.Policy_Updated);
|
||||
|
@ -43,6 +43,7 @@ namespace Bit.Core.Services
|
||||
private readonly IEventService _eventService;
|
||||
private readonly IApplicationCacheService _applicationCacheService;
|
||||
private readonly IPaymentService _paymentService;
|
||||
private readonly IPolicyRepository _policyRepository;
|
||||
private readonly IDataProtector _organizationServiceDataProtector;
|
||||
private readonly CurrentContext _currentContext;
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
@ -69,6 +70,7 @@ namespace Bit.Core.Services
|
||||
IApplicationCacheService applicationCacheService,
|
||||
IDataProtectionProvider dataProtectionProvider,
|
||||
IPaymentService paymentService,
|
||||
IPolicyRepository policyRepository,
|
||||
CurrentContext currentContext,
|
||||
GlobalSettings globalSettings)
|
||||
: base(
|
||||
@ -97,6 +99,7 @@ namespace Bit.Core.Services
|
||||
_eventService = eventService;
|
||||
_applicationCacheService = applicationCacheService;
|
||||
_paymentService = paymentService;
|
||||
_policyRepository = policyRepository;
|
||||
_organizationServiceDataProtector = dataProtectionProvider.CreateProtector(
|
||||
"OrganizationServiceDataProtector");
|
||||
_currentContext = currentContext;
|
||||
@ -638,7 +641,8 @@ namespace Bit.Core.Services
|
||||
await _eventService.LogUserEventAsync(user.Id, EventType.User_Updated2fa);
|
||||
}
|
||||
|
||||
public async Task DisableTwoFactorProviderAsync(User user, TwoFactorProviderType type)
|
||||
public async Task DisableTwoFactorProviderAsync(User user, TwoFactorProviderType type,
|
||||
IOrganizationService organizationService)
|
||||
{
|
||||
var providers = user.GetTwoFactorProviders();
|
||||
if(!providers?.ContainsKey(type) ?? true)
|
||||
@ -650,6 +654,25 @@ namespace Bit.Core.Services
|
||||
user.SetTwoFactorProviders(providers);
|
||||
await SaveUserAsync(user);
|
||||
await _eventService.LogUserEventAsync(user.Id, EventType.User_Disabled2fa);
|
||||
|
||||
if(!await TwoFactorIsEnabledAsync(user))
|
||||
{
|
||||
var policies = await _policyRepository.GetManyByUserIdAsync(user.Id);
|
||||
var twoFactorPolicies = policies.Where(p => p.Type == PolicyType.TwoFactorAuthentication && p.Enabled);
|
||||
if(twoFactorPolicies.Any())
|
||||
{
|
||||
var userOrgs = await _organizationUserRepository.GetManyByUserAsync(user.Id);
|
||||
var ownerOrgs = userOrgs.Where(o => o.Type == OrganizationUserType.Owner)
|
||||
.Select(o => o.Id).ToHashSet();
|
||||
foreach(var policy in twoFactorPolicies)
|
||||
{
|
||||
if(!ownerOrgs.Contains(policy.OrganizationId))
|
||||
{
|
||||
await organizationService.DeleteUserAsync(policy.OrganizationId, user.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> RecoverTwoFactorAsync(string email, string masterPassword, string recoveryCode)
|
||||
|
Reference in New Issue
Block a user