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:
parent
6e7bc8369d
commit
e350ef650a
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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.");
|
||||||
|
@ -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.");
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user