1
0
mirror of https://github.com/bitwarden/server.git synced 2025-05-20 19:14:32 -05:00

Adjusted two factor recovery model and moved functionality to user service

This commit is contained in:
Kyle Spearrin 2016-11-14 23:32:15 -05:00
parent 54a857f215
commit 4867df0138
4 changed files with 37 additions and 19 deletions

View File

@ -209,30 +209,15 @@ namespace Bit.Api.Controllers
return response; return response;
} }
[HttpPut("two-factor-recover")]
[HttpPost("two-factor-recover")] [HttpPost("two-factor-recover")]
public async Task<TwoFactorResponseModel> PutTwoFactorRecover([FromBody]RecoverTwoFactorRequestModel model) [AllowAnonymous]
public async Task PostTwoFactorRecover([FromBody]RecoverTwoFactorRequestModel model)
{ {
var user = _currentContext.User; if(!await _userService.RecoverTwoFactorAsync(model.Email, model.MasterPasswordHash, model.RecoveryCode))
if(!await _userManager.CheckPasswordAsync(user, model.MasterPasswordHash))
{ {
await Task.Delay(2000); await Task.Delay(2000);
throw new BadRequestException("MasterPasswordHash", "Invalid password."); throw new BadRequestException(string.Empty, "Invalid information. Try again.");
} }
if(string.Compare(user.TwoFactorRecoveryCode, model.RecoveryCode, true) != 0)
{
await Task.Delay(2000);
throw new BadRequestException("RecoveryCode", "Invalid recovery code.");
}
user.TwoFactorProvider = TwoFactorProvider.Authenticator;
user.TwoFactorEnabled = false;
user.TwoFactorRecoveryCode = null;
await _userService.SaveUserAsync(user);
var response = new TwoFactorResponseModel(user);
return response;
} }
[HttpPut("two-factor-regenerate")] [HttpPut("two-factor-regenerate")]

View File

@ -5,6 +5,10 @@ namespace Bit.Api.Models
{ {
public class RecoverTwoFactorRequestModel public class RecoverTwoFactorRequestModel
{ {
[Required]
[EmailAddress]
[StringLength(50)]
public string Email { get; set; }
[Required] [Required]
public string MasterPasswordHash { get; set; } public string MasterPasswordHash { get; set; }
[Required] [Required]

View File

@ -17,6 +17,7 @@ namespace Bit.Core.Services
Task<IdentityResult> ChangePasswordAsync(User user, string currentMasterPasswordHash, string newMasterPasswordHash, IEnumerable<Cipher> ciphers); Task<IdentityResult> ChangePasswordAsync(User user, string currentMasterPasswordHash, string newMasterPasswordHash, IEnumerable<Cipher> ciphers);
Task<IdentityResult> RefreshSecurityStampAsync(User user, string masterPasswordHash); Task<IdentityResult> RefreshSecurityStampAsync(User user, string masterPasswordHash);
Task GetTwoFactorAsync(User user, Enums.TwoFactorProvider provider); Task GetTwoFactorAsync(User user, Enums.TwoFactorProvider provider);
Task<bool> RecoverTwoFactorAsync(string email, string masterPassword, string recoveryCode);
Task<IdentityResult> DeleteAsync(User user); Task<IdentityResult> DeleteAsync(User user);
} }
} }

View File

@ -10,6 +10,7 @@ using OtpSharp;
using Base32; using Base32;
using System.Linq; using System.Linq;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Bit.Core.Enums;
namespace Bit.Core.Services namespace Bit.Core.Services
{ {
@ -249,6 +250,33 @@ namespace Bit.Core.Services
await SaveUserAsync(user); await SaveUserAsync(user);
} }
public async Task<bool> RecoverTwoFactorAsync(string email, string masterPassword, string recoveryCode)
{
var user = await _userRepository.GetByEmailAsync(email);
if(user == null)
{
// No user exists. Do we want to send an email telling them this in the future?
return false;
}
if(!await base.CheckPasswordAsync(user, masterPassword))
{
return false;
}
if(string.Compare(user.TwoFactorRecoveryCode, recoveryCode, true) != 0)
{
return false;
}
user.TwoFactorProvider = TwoFactorProvider.Authenticator;
user.TwoFactorEnabled = false;
user.TwoFactorRecoveryCode = null;
await SaveUserAsync(user);
return true;
}
private async Task<IdentityResult> UpdatePasswordHash(User user, string newPassword, bool validatePassword = true) private async Task<IdentityResult> UpdatePasswordHash(User user, string newPassword, bool validatePassword = true)
{ {
if(validatePassword) if(validatePassword)