1
0
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:
Kyle Spearrin
2020-02-19 14:56:16 -05:00
committed by GitHub
parent 6b6c2d862d
commit 81424a8526
13 changed files with 100 additions and 15 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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)