Add CheckPasswordSignIn method
This commit is contained in:
parent
ddaab5f549
commit
fe60304df5
|
|
@ -241,32 +241,10 @@ namespace Microsoft.AspNetCore.Identity
|
|||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
|
||||
var error = await PreSignInCheck(user);
|
||||
if (error != null)
|
||||
{
|
||||
return error;
|
||||
}
|
||||
if (await IsLockedOut(user))
|
||||
{
|
||||
return await LockedOut(user);
|
||||
}
|
||||
if (await UserManager.CheckPasswordAsync(user, password))
|
||||
{
|
||||
await ResetLockout(user);
|
||||
return await SignInOrTwoFactorAsync(user, isPersistent);
|
||||
}
|
||||
Logger.LogWarning(2, "User {userId} failed to provide the correct password.", await UserManager.GetUserIdAsync(user));
|
||||
|
||||
if (UserManager.SupportsUserLockout && lockoutOnFailure)
|
||||
{
|
||||
// If lockout is requested, increment access failed count which might lock out the user
|
||||
await UserManager.AccessFailedAsync(user);
|
||||
if (await UserManager.IsLockedOutAsync(user))
|
||||
{
|
||||
return await LockedOut(user);
|
||||
}
|
||||
}
|
||||
return SignInResult.Failed;
|
||||
var attempt = await CheckPasswordSignInAsync(user, password, lockoutOnFailure);
|
||||
return attempt.Succeeded
|
||||
? await SignInOrTwoFactorAsync(user, isPersistent)
|
||||
: attempt;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -291,6 +269,52 @@ namespace Microsoft.AspNetCore.Identity
|
|||
return await PasswordSignInAsync(user, password, isPersistent, lockoutOnFailure);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts a password sign in for a user.
|
||||
/// </summary>
|
||||
/// <param name="user">The user to sign in.</param>
|
||||
/// <param name="password">The password to attempt to sign in with.</param>
|
||||
/// <param name="lockoutOnFailure">Flag indicating if the user account should be locked if the sign in fails.</param>
|
||||
/// <returns>The task object representing the asynchronous operation containing the <see name="SignInResult"/>
|
||||
/// for the sign-in attempt.</returns>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<SignInResult> CheckPasswordSignInAsync(TUser user, string password, bool lockoutOnFailure)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
|
||||
var error = await PreSignInCheck(user);
|
||||
if (error != null)
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
if (await IsLockedOut(user))
|
||||
{
|
||||
return await LockedOut(user);
|
||||
}
|
||||
if (await UserManager.CheckPasswordAsync(user, password))
|
||||
{
|
||||
await ResetLockout(user);
|
||||
return SignInResult.Success;
|
||||
}
|
||||
Logger.LogWarning(2, "User {userId} failed to provide the correct password.", await UserManager.GetUserIdAsync(user));
|
||||
|
||||
if (UserManager.SupportsUserLockout && lockoutOnFailure)
|
||||
{
|
||||
// If lockout is requested, increment access failed count which might lock out the user
|
||||
await UserManager.AccessFailedAsync(user);
|
||||
if (await UserManager.IsLockedOutAsync(user))
|
||||
{
|
||||
return await LockedOut(user);
|
||||
}
|
||||
}
|
||||
return SignInResult.Failed;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns a flag indicating if the current client browser has been remembered by two factor authentication
|
||||
/// for the user attempting to login, as an asynchronous operation.
|
||||
|
|
|
|||
|
|
@ -136,6 +136,37 @@ namespace Microsoft.AspNetCore.Identity.Test
|
|||
manager.Verify();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CheckPasswordSignInReturnsLockedOutWhenLockedOut()
|
||||
{
|
||||
// Setup
|
||||
var user = new TestUser { UserName = "Foo" };
|
||||
var manager = SetupUserManager(user);
|
||||
manager.Setup(m => m.SupportsUserLockout).Returns(true).Verifiable();
|
||||
manager.Setup(m => m.IsLockedOutAsync(user)).ReturnsAsync(true).Verifiable();
|
||||
|
||||
var context = new Mock<HttpContext>();
|
||||
var contextAccessor = new Mock<IHttpContextAccessor>();
|
||||
contextAccessor.Setup(a => a.HttpContext).Returns(context.Object);
|
||||
var roleManager = MockHelpers.MockRoleManager<TestRole>();
|
||||
var identityOptions = new IdentityOptions();
|
||||
var options = new Mock<IOptions<IdentityOptions>>();
|
||||
options.Setup(a => a.Value).Returns(identityOptions);
|
||||
var claimsFactory = new UserClaimsPrincipalFactory<TestUser, TestRole>(manager.Object, roleManager.Object, options.Object);
|
||||
var logStore = new StringBuilder();
|
||||
var logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore);
|
||||
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory, options.Object, logger.Object);
|
||||
|
||||
// Act
|
||||
var result = await helper.CheckPasswordSignInAsync(user, "bogus", false);
|
||||
|
||||
// Assert
|
||||
Assert.False(result.Succeeded);
|
||||
Assert.True(result.IsLockedOut);
|
||||
Assert.True(logStore.ToString().Contains($"User {user.Id} is currently locked out."));
|
||||
manager.Verify();
|
||||
}
|
||||
|
||||
private static Mock<UserManager<TestUser>> SetupUserManager(TestUser user)
|
||||
{
|
||||
var manager = MockHelpers.MockUserManager<TestUser>();
|
||||
|
|
@ -534,9 +565,11 @@ namespace Microsoft.AspNetCore.Identity.Test
|
|||
var helper = SetupSignInManager(manager.Object, context.Object, logStore);
|
||||
// Act
|
||||
var result = await helper.PasswordSignInAsync(user.UserName, "bogus", false, false);
|
||||
var checkResult = await helper.CheckPasswordSignInAsync(user, "bogus", false);
|
||||
|
||||
// Assert
|
||||
Assert.False(result.Succeeded);
|
||||
Assert.False(checkResult.Succeeded);
|
||||
Assert.True(logStore.ToString().Contains($"User {user.Id} failed to provide the correct password."));
|
||||
manager.Verify();
|
||||
context.Verify();
|
||||
|
|
@ -587,6 +620,33 @@ namespace Microsoft.AspNetCore.Identity.Test
|
|||
manager.Verify();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CheckPasswordSignInFailsWithWrongPasswordCanAccessFailedAndLockout()
|
||||
{
|
||||
// Setup
|
||||
var user = new TestUser { UserName = "Foo" };
|
||||
var manager = SetupUserManager(user);
|
||||
var lockedout = false;
|
||||
manager.Setup(m => m.AccessFailedAsync(user)).Returns(() =>
|
||||
{
|
||||
lockedout = true;
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}).Verifiable();
|
||||
manager.Setup(m => m.SupportsUserLockout).Returns(true).Verifiable();
|
||||
manager.Setup(m => m.IsLockedOutAsync(user)).Returns(() => Task.FromResult(lockedout));
|
||||
manager.Setup(m => m.CheckPasswordAsync(user, "bogus")).ReturnsAsync(false).Verifiable();
|
||||
var context = new Mock<HttpContext>();
|
||||
var helper = SetupSignInManager(manager.Object, context.Object);
|
||||
|
||||
// Act
|
||||
var result = await helper.CheckPasswordSignInAsync(user, "bogus", true);
|
||||
|
||||
// Assert
|
||||
Assert.False(result.Succeeded);
|
||||
Assert.True(result.IsLockedOut);
|
||||
manager.Verify();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
|
|
|
|||
Loading…
Reference in New Issue