Failed Logon Attempts resets to 0 after maximum number of attempts
This commit is contained in:
@@ -57,7 +57,7 @@ namespace Umbraco.Core.Security
|
||||
[Obsolete("Use the overload specifying all dependencies instead")]
|
||||
public static BackOfficeUserManager Create(
|
||||
IdentityFactoryOptions<BackOfficeUserManager> options,
|
||||
IUserService userService,
|
||||
IUserService userService,
|
||||
IExternalLoginService externalLoginService,
|
||||
MembershipProviderBase membershipProvider)
|
||||
{
|
||||
@@ -94,7 +94,7 @@ namespace Umbraco.Core.Security
|
||||
manager.InitUserManager(manager, membershipProvider, contentSectionConfig, options);
|
||||
return manager;
|
||||
}
|
||||
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Use the overload specifying all dependencies instead")]
|
||||
public static BackOfficeUserManager Create(
|
||||
@@ -129,7 +129,7 @@ namespace Umbraco.Core.Security
|
||||
[Obsolete("Use the overload specifying all dependencies instead")]
|
||||
protected void InitUserManager(
|
||||
BackOfficeUserManager manager,
|
||||
MembershipProviderBase membershipProvider,
|
||||
MembershipProviderBase membershipProvider,
|
||||
IdentityFactoryOptions<BackOfficeUserManager> options)
|
||||
{
|
||||
InitUserManager(manager, membershipProvider, UmbracoConfig.For.UmbracoSettings().Content, options);
|
||||
@@ -216,8 +216,8 @@ namespace Umbraco.Core.Security
|
||||
/// <param name="contentSectionConfig"></param>
|
||||
/// <returns></returns>
|
||||
protected void InitUserManager(
|
||||
BackOfficeUserManager<T> manager,
|
||||
MembershipProviderBase membershipProvider,
|
||||
BackOfficeUserManager<T> manager,
|
||||
MembershipProviderBase membershipProvider,
|
||||
IDataProtectionProvider dataProtectionProvider,
|
||||
IContentSection contentSectionConfig)
|
||||
{
|
||||
@@ -233,7 +233,7 @@ namespace Umbraco.Core.Security
|
||||
|
||||
//use a custom hasher based on our membership provider
|
||||
manager.PasswordHasher = GetDefaultPasswordHasher(membershipProvider);
|
||||
|
||||
|
||||
if (dataProtectionProvider != null)
|
||||
{
|
||||
manager.UserTokenProvider = new DataProtectorTokenProvider<T, int>(dataProtectionProvider.Create("ASP.NET Identity"));
|
||||
@@ -373,7 +373,7 @@ namespace Umbraco.Core.Security
|
||||
}
|
||||
|
||||
#region Overrides for password logic
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Logic used to validate a username and password
|
||||
/// </summary>
|
||||
@@ -469,7 +469,7 @@ namespace Umbraco.Core.Security
|
||||
await UpdateSecurityStampInternal(user);
|
||||
return IdentityResult.Success;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -507,15 +507,22 @@ namespace Umbraco.Core.Security
|
||||
|
||||
#endregion
|
||||
|
||||
public override Task<IdentityResult> SetLockoutEndDateAsync(int userId, DateTimeOffset lockoutEnd)
|
||||
public override async Task<IdentityResult> SetLockoutEndDateAsync(int userId, DateTimeOffset lockoutEnd)
|
||||
{
|
||||
var result = base.SetLockoutEndDateAsync(userId, lockoutEnd);
|
||||
var result = await base.SetLockoutEndDateAsync(userId, lockoutEnd);
|
||||
|
||||
// The way we unlock is by setting the lockoutEnd date to the current datetime
|
||||
if (result.Result.Succeeded && lockoutEnd >= DateTimeOffset.UtcNow)
|
||||
if (result.Succeeded && lockoutEnd >= DateTimeOffset.UtcNow)
|
||||
{
|
||||
RaiseAccountLockedEvent(userId);
|
||||
}
|
||||
else
|
||||
{
|
||||
RaiseAccountUnlockedEvent(userId);
|
||||
//Resets the login attempt fails back to 0 when unlock is clicked
|
||||
await ResetAccessFailedCountAsync(userId);
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -537,16 +544,39 @@ namespace Umbraco.Core.Security
|
||||
RaiseResetAccessFailedCountEvent(userId);
|
||||
return await UpdateAsync(user);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public override Task<IdentityResult> AccessFailedAsync(int userId)
|
||||
|
||||
/// <summary>
|
||||
/// Overides the microsoft ASP.NET user managment method
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns>
|
||||
/// returns a Async Task<IdentityResult>
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// Doesnt set fail attempts back to 0
|
||||
/// </remarks>
|
||||
public override async Task<IdentityResult> AccessFailedAsync(int userId)
|
||||
{
|
||||
var result = base.AccessFailedAsync(userId);
|
||||
var lockoutStore = (IUserLockoutStore<BackOfficeIdentityUser, int>)Store;
|
||||
var user = await FindByIdAsync(userId);
|
||||
if (user == null)
|
||||
throw new InvalidOperationException("No user found by user id " + userId);
|
||||
|
||||
var count = await lockoutStore.IncrementAccessFailedCountAsync(user);
|
||||
|
||||
if (count >= MaxFailedAccessAttemptsBeforeLockout)
|
||||
{
|
||||
await lockoutStore.SetLockoutEndDateAsync(user, DateTimeOffset.UtcNow.Add(DefaultAccountLockoutTimeSpan));
|
||||
//NOTE: in normal aspnet identity this would do set the number of failed attempts back to 0
|
||||
//here we are persisting the value for the back office
|
||||
}
|
||||
|
||||
var result = await UpdateAsync(user);
|
||||
|
||||
//Slightly confusing: this will return a Success if we successfully update the AccessFailed count
|
||||
if (result.Result.Succeeded)
|
||||
if (result.Succeeded)
|
||||
RaiseLoginFailedEvent(userId);
|
||||
|
||||
return result;
|
||||
|
||||
@@ -341,8 +341,10 @@
|
||||
vm.unlockUserButtonState = "busy";
|
||||
usersResource.unlockUsers([vm.user.id]).then(function (data) {
|
||||
vm.user.userState = 0;
|
||||
vm.user.failedPasswordAttempts = 0;
|
||||
setUserDisplayState();
|
||||
vm.unlockUserButtonState = "success";
|
||||
|
||||
formHelper.showNotifications(data);
|
||||
}, function (error) {
|
||||
vm.unlockUserButtonState = "error";
|
||||
|
||||
@@ -358,4 +358,4 @@
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user