1
0
mirror of https://github.com/bitwarden/server.git synced 2024-11-22 12:15:36 +01:00

dont cycle security token on re-hash

This commit is contained in:
Kyle Spearrin 2018-04-17 08:10:17 -04:00
parent 6e7bc8369d
commit e350ef650a
7 changed files with 42 additions and 23 deletions

View File

@ -25,7 +25,6 @@ namespace Bit.Api.Controllers
private readonly ICipherService _cipherService; private readonly ICipherService _cipherService;
private readonly IOrganizationUserRepository _organizationUserRepository; private readonly IOrganizationUserRepository _organizationUserRepository;
private readonly ILicensingService _licenseService; private readonly ILicensingService _licenseService;
private readonly UserManager<User> _userManager;
private readonly GlobalSettings _globalSettings; private readonly GlobalSettings _globalSettings;
public AccountsController( public AccountsController(
@ -33,13 +32,11 @@ namespace Bit.Api.Controllers
ICipherService cipherService, ICipherService cipherService,
IOrganizationUserRepository organizationUserRepository, IOrganizationUserRepository organizationUserRepository,
ILicensingService licenseService, ILicensingService licenseService,
UserManager<User> userManager,
GlobalSettings globalSettings) GlobalSettings globalSettings)
{ {
_userService = userService; _userService = userService;
_cipherService = cipherService; _cipherService = cipherService;
_organizationUserRepository = organizationUserRepository; _organizationUserRepository = organizationUserRepository;
_userManager = userManager;
_licenseService = licenseService; _licenseService = licenseService;
_globalSettings = globalSettings; _globalSettings = globalSettings;
} }
@ -79,7 +76,7 @@ namespace Bit.Api.Controllers
throw new UnauthorizedAccessException(); throw new UnauthorizedAccessException();
} }
if(!await _userManager.CheckPasswordAsync(user, model.MasterPasswordHash)) if(!await _userService.CheckPasswordAsync(user, model.MasterPasswordHash))
{ {
await Task.Delay(2000); await Task.Delay(2000);
throw new BadRequestException("MasterPasswordHash", "Invalid password."); throw new BadRequestException("MasterPasswordHash", "Invalid password.");
@ -323,7 +320,7 @@ namespace Bit.Api.Controllers
throw new UnauthorizedAccessException(); throw new UnauthorizedAccessException();
} }
if(!await _userManager.CheckPasswordAsync(user, model.MasterPasswordHash)) if(!await _userService.CheckPasswordAsync(user, model.MasterPasswordHash))
{ {
ModelState.AddModelError("MasterPasswordHash", "Invalid password."); ModelState.AddModelError("MasterPasswordHash", "Invalid password.");
await Task.Delay(2000); await Task.Delay(2000);

View File

@ -25,7 +25,6 @@ namespace Bit.Api.Controllers
private readonly ICollectionCipherRepository _collectionCipherRepository; private readonly ICollectionCipherRepository _collectionCipherRepository;
private readonly ICipherService _cipherService; private readonly ICipherService _cipherService;
private readonly IUserService _userService; private readonly IUserService _userService;
private readonly UserManager<User> _userManager;
private readonly CurrentContext _currentContext; private readonly CurrentContext _currentContext;
private readonly GlobalSettings _globalSettings; private readonly GlobalSettings _globalSettings;
@ -34,7 +33,6 @@ namespace Bit.Api.Controllers
ICollectionCipherRepository collectionCipherRepository, ICollectionCipherRepository collectionCipherRepository,
ICipherService cipherService, ICipherService cipherService,
IUserService userService, IUserService userService,
UserManager<User> userManager,
CurrentContext currentContext, CurrentContext currentContext,
GlobalSettings globalSettings) GlobalSettings globalSettings)
{ {
@ -42,7 +40,6 @@ namespace Bit.Api.Controllers
_collectionCipherRepository = collectionCipherRepository; _collectionCipherRepository = collectionCipherRepository;
_cipherService = cipherService; _cipherService = cipherService;
_userService = userService; _userService = userService;
_userManager = userManager;
_currentContext = currentContext; _currentContext = currentContext;
_globalSettings = globalSettings; _globalSettings = globalSettings;
} }
@ -381,7 +378,7 @@ namespace Bit.Api.Controllers
throw new UnauthorizedAccessException(); throw new UnauthorizedAccessException();
} }
if(!await _userManager.CheckPasswordAsync(user, model.MasterPasswordHash)) if(!await _userService.CheckPasswordAsync(user, model.MasterPasswordHash))
{ {
ModelState.AddModelError("MasterPasswordHash", "Invalid password."); ModelState.AddModelError("MasterPasswordHash", "Invalid password.");
await Task.Delay(2000); await Task.Delay(2000);

View File

@ -32,7 +32,6 @@ namespace Bit.Api.Controllers
private readonly CurrentContext _currentContext; private readonly CurrentContext _currentContext;
private readonly GlobalSettings _globalSettings; private readonly GlobalSettings _globalSettings;
private readonly ApiSettings _apiSettings; private readonly ApiSettings _apiSettings;
private readonly UserManager<User> _userManager;
public OrganizationsController( public OrganizationsController(
IOrganizationRepository organizationRepository, IOrganizationRepository organizationRepository,
@ -41,15 +40,13 @@ namespace Bit.Api.Controllers
IUserService userService, IUserService userService,
CurrentContext currentContext, CurrentContext currentContext,
GlobalSettings globalSettings, GlobalSettings globalSettings,
IOptions<ApiSettings> apiSettings, IOptions<ApiSettings> apiSettings)
UserManager<User> userManager)
{ {
_organizationRepository = organizationRepository; _organizationRepository = organizationRepository;
_organizationUserRepository = organizationUserRepository; _organizationUserRepository = organizationUserRepository;
_organizationService = organizationService; _organizationService = organizationService;
_userService = userService; _userService = userService;
_currentContext = currentContext; _currentContext = currentContext;
_userManager = userManager;
_globalSettings = globalSettings; _globalSettings = globalSettings;
_apiSettings = apiSettings.Value; _apiSettings = apiSettings.Value;
} }
@ -359,7 +356,7 @@ namespace Bit.Api.Controllers
throw new UnauthorizedAccessException(); throw new UnauthorizedAccessException();
} }
if(!await _userManager.CheckPasswordAsync(user, model.MasterPasswordHash)) if(!await _userService.CheckPasswordAsync(user, model.MasterPasswordHash))
{ {
await Task.Delay(2000); await Task.Delay(2000);
throw new BadRequestException("MasterPasswordHash", "Invalid password."); throw new BadRequestException("MasterPasswordHash", "Invalid password.");

View File

@ -246,7 +246,7 @@ namespace Bit.Api.Controllers
var user = await _userManager.FindByEmailAsync(model.Email.ToLowerInvariant()); var user = await _userManager.FindByEmailAsync(model.Email.ToLowerInvariant());
if(user != null) if(user != null)
{ {
if(await _userManager.CheckPasswordAsync(user, model.MasterPasswordHash)) if(await _userService.CheckPasswordAsync(user, model.MasterPasswordHash))
{ {
await _userService.SendTwoFactorEmailAsync(user); await _userService.SendTwoFactorEmailAsync(user);
return; return;
@ -336,7 +336,7 @@ namespace Bit.Api.Controllers
throw new UnauthorizedAccessException(); throw new UnauthorizedAccessException();
} }
if(!await _userManager.CheckPasswordAsync(user, masterPasswordHash)) if(!await _userService.CheckPasswordAsync(user, masterPasswordHash))
{ {
await Task.Delay(2000); await Task.Delay(2000);
throw new BadRequestException("MasterPasswordHash", "Invalid password."); throw new BadRequestException("MasterPasswordHash", "Invalid password.");

View File

@ -69,7 +69,7 @@ namespace Bit.Core.IdentityServer
} }
var user = await _userManager.FindByEmailAsync(context.UserName.ToLowerInvariant()); var user = await _userManager.FindByEmailAsync(context.UserName.ToLowerInvariant());
if(user == null || !await _userManager.CheckPasswordAsync(user, context.Password)) if(user == null || !await _userService.CheckPasswordAsync(user, context.Password))
{ {
await BuildErrorResultAsync(false, context, user); await BuildErrorResultAsync(false, context, user);
return; return;

View File

@ -50,5 +50,6 @@ namespace Bit.Core.Services
Task DisablePremiumAsync(User user, DateTime? expirationDate); Task DisablePremiumAsync(User user, DateTime? expirationDate);
Task UpdatePremiumExpirationAsync(Guid userId, DateTime? expirationDate); Task UpdatePremiumExpirationAsync(Guid userId, DateTime? expirationDate);
Task<UserLicense> GenerateLicenseAsync(User user, BillingInfo billingInfo = null); Task<UserLicense> GenerateLicenseAsync(User user, BillingInfo billingInfo = null);
Task<bool> CheckPasswordAsync(User user, string password);
} }
} }

View File

@ -411,7 +411,7 @@ namespace Bit.Core.Services
throw new ArgumentNullException(nameof(user)); throw new ArgumentNullException(nameof(user));
} }
if(await base.CheckPasswordAsync(user, masterPassword)) if(await CheckPasswordAsync(user, masterPassword))
{ {
var result = await UpdatePasswordHash(user, newMasterPassword); var result = await UpdatePasswordHash(user, newMasterPassword);
if(!result.Succeeded) if(!result.Succeeded)
@ -440,7 +440,7 @@ namespace Bit.Core.Services
throw new ArgumentNullException(nameof(user)); throw new ArgumentNullException(nameof(user));
} }
if(await base.CheckPasswordAsync(user, masterPassword)) if(await CheckPasswordAsync(user, masterPassword))
{ {
user.RevisionDate = user.AccountRevisionDate = DateTime.UtcNow; user.RevisionDate = user.AccountRevisionDate = DateTime.UtcNow;
user.SecurityStamp = Guid.NewGuid().ToString(); user.SecurityStamp = Guid.NewGuid().ToString();
@ -469,7 +469,7 @@ namespace Bit.Core.Services
throw new ArgumentNullException(nameof(user)); throw new ArgumentNullException(nameof(user));
} }
if(await base.CheckPasswordAsync(user, masterPassword)) if(await CheckPasswordAsync(user, masterPassword))
{ {
var result = await base.UpdateSecurityStampAsync(user); var result = await base.UpdateSecurityStampAsync(user);
if(!result.Succeeded) if(!result.Succeeded)
@ -527,7 +527,7 @@ namespace Bit.Core.Services
return false; return false;
} }
if(!await base.CheckPasswordAsync(user, masterPassword)) if(!await CheckPasswordAsync(user, masterPassword))
{ {
return false; return false;
} }
@ -745,7 +745,31 @@ namespace Bit.Core.Services
new UserLicense(user, billingInfo, _licenseService); new UserLicense(user, billingInfo, _licenseService);
} }
private async Task<IdentityResult> UpdatePasswordHash(User user, string newPassword, bool validatePassword = true) public override async Task<bool> CheckPasswordAsync(User user, string password)
{
if(user == null)
{
return false;
}
var result = await base.VerifyPasswordAsync(Store as IUserPasswordStore<User>, user, password);
if(result == PasswordVerificationResult.SuccessRehashNeeded)
{
await UpdatePasswordHash(user, password, false, false);
user.RevisionDate = DateTime.UtcNow;
await _userRepository.ReplaceAsync(user);
}
var success = result != PasswordVerificationResult.Failed;
if(!success)
{
Logger.LogWarning(0, "Invalid password for user {userId}.", user.Id);
}
return success;
}
private async Task<IdentityResult> UpdatePasswordHash(User user, string newPassword,
bool validatePassword = true, bool refreshStamp = true)
{ {
if(validatePassword) if(validatePassword)
{ {
@ -757,7 +781,10 @@ namespace Bit.Core.Services
} }
user.MasterPassword = _passwordHasher.HashPassword(user, newPassword); user.MasterPassword = _passwordHasher.HashPassword(user, newPassword);
user.SecurityStamp = Guid.NewGuid().ToString(); if(refreshStamp)
{
user.SecurityStamp = Guid.NewGuid().ToString();
}
return IdentityResult.Success; return IdentityResult.Success;
} }