1
0
mirror of https://github.com/bitwarden/server.git synced 2025-02-22 02:51:33 +01:00

CheckPoliciesOnTwoFactorRemoval for 2fa recovery (#659)

This commit is contained in:
Kyle Spearrin 2020-02-28 10:23:19 -05:00 committed by GitHub
parent ae893c72bd
commit 71d9ffdd9d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 30 additions and 21 deletions

View File

@ -359,7 +359,8 @@ namespace Bit.Api.Controllers
[AllowAnonymous]
public async Task PostRecover([FromBody]TwoFactorRecoveryRequestModel model)
{
if(!await _userService.RecoverTwoFactorAsync(model.Email, model.MasterPasswordHash, model.RecoveryCode))
if(!await _userService.RecoverTwoFactorAsync(model.Email, model.MasterPasswordHash, model.RecoveryCode,
_organizationService))
{
await Task.Delay(2000);
throw new BadRequestException(string.Empty, "Invalid information. Try again.");

View File

@ -39,7 +39,8 @@ namespace Bit.Core.Services
Task UpdateTwoFactorProviderAsync(User user, TwoFactorProviderType type);
Task DisableTwoFactorProviderAsync(User user, TwoFactorProviderType type,
IOrganizationService organizationService);
Task<bool> RecoverTwoFactorAsync(string email, string masterPassword, string recoveryCode);
Task<bool> RecoverTwoFactorAsync(string email, string masterPassword, string recoveryCode,
IOrganizationService organizationService);
Task<string> GenerateUserTokenAsync(User user, string tokenProvider, string purpose);
Task<IdentityResult> DeleteAsync(User user);
Task<IdentityResult> DeleteAsync(User user, string token);

View File

@ -668,28 +668,12 @@ namespace Bit.Core.Services
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.OrganizationId).ToHashSet();
foreach(var policy in twoFactorPolicies)
{
if(!ownerOrgs.Contains(policy.OrganizationId))
{
await organizationService.DeleteUserAsync(policy.OrganizationId, user.Id);
var organization = await _organizationRepository.GetByIdAsync(policy.OrganizationId);
await _mailService.SendOrganizationUserRemovedForPolicyTwoStepEmailAsync(
organization.Name, user.Email);
}
}
}
await CheckPoliciesOnTwoFactorRemovalAsync(user, organizationService);
}
}
public async Task<bool> RecoverTwoFactorAsync(string email, string masterPassword, string recoveryCode)
public async Task<bool> RecoverTwoFactorAsync(string email, string masterPassword, string recoveryCode,
IOrganizationService organizationService)
{
var user = await _userRepository.GetByEmailAsync(email);
if(user == null)
@ -713,6 +697,7 @@ namespace Bit.Core.Services
await SaveUserAsync(user);
await _mailService.SendRecoverTwoFactorEmail(user.Email, DateTime.UtcNow, _currentContext.IpAddress);
await _eventService.LogUserEventAsync(user.Id, EventType.User_Recovered2fa);
await CheckPoliciesOnTwoFactorRemovalAsync(user, organizationService);
return true;
}
@ -1094,5 +1079,27 @@ namespace Bit.Core.Services
user.TwoFactorRecoveryCode = CoreHelpers.SecureRandomString(32, upper: false, special: false);
}
}
private async Task CheckPoliciesOnTwoFactorRemovalAsync(User user, IOrganizationService organizationService)
{
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.OrganizationId).ToHashSet();
foreach(var policy in twoFactorPolicies)
{
if(!ownerOrgs.Contains(policy.OrganizationId))
{
await organizationService.DeleteUserAsync(policy.OrganizationId, user.Id);
var organization = await _organizationRepository.GetByIdAsync(policy.OrganizationId);
await _mailService.SendOrganizationUserRemovedForPolicyTwoStepEmailAsync(
organization.Name, user.Email);
}
}
}
}
}
}