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));
|
throw new ArgumentNullException(nameof(user));
|
||||||
}
|
}
|
||||||
|
|
||||||
var error = await PreSignInCheck(user);
|
var attempt = await CheckPasswordSignInAsync(user, password, lockoutOnFailure);
|
||||||
if (error != null)
|
return attempt.Succeeded
|
||||||
{
|
? await SignInOrTwoFactorAsync(user, isPersistent)
|
||||||
return error;
|
: attempt;
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -291,6 +269,52 @@ namespace Microsoft.AspNetCore.Identity
|
||||||
return await PasswordSignInAsync(user, password, isPersistent, lockoutOnFailure);
|
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>
|
/// <summary>
|
||||||
/// Returns a flag indicating if the current client browser has been remembered by two factor authentication
|
/// 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.
|
/// for the user attempting to login, as an asynchronous operation.
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,37 @@ namespace Microsoft.AspNetCore.Identity.Test
|
||||||
manager.Verify();
|
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)
|
private static Mock<UserManager<TestUser>> SetupUserManager(TestUser user)
|
||||||
{
|
{
|
||||||
var manager = MockHelpers.MockUserManager<TestUser>();
|
var manager = MockHelpers.MockUserManager<TestUser>();
|
||||||
|
|
@ -534,9 +565,11 @@ namespace Microsoft.AspNetCore.Identity.Test
|
||||||
var helper = SetupSignInManager(manager.Object, context.Object, logStore);
|
var helper = SetupSignInManager(manager.Object, context.Object, logStore);
|
||||||
// Act
|
// Act
|
||||||
var result = await helper.PasswordSignInAsync(user.UserName, "bogus", false, false);
|
var result = await helper.PasswordSignInAsync(user.UserName, "bogus", false, false);
|
||||||
|
var checkResult = await helper.CheckPasswordSignInAsync(user, "bogus", false);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.False(result.Succeeded);
|
Assert.False(result.Succeeded);
|
||||||
|
Assert.False(checkResult.Succeeded);
|
||||||
Assert.True(logStore.ToString().Contains($"User {user.Id} failed to provide the correct password."));
|
Assert.True(logStore.ToString().Contains($"User {user.Id} failed to provide the correct password."));
|
||||||
manager.Verify();
|
manager.Verify();
|
||||||
context.Verify();
|
context.Verify();
|
||||||
|
|
@ -587,6 +620,33 @@ namespace Microsoft.AspNetCore.Identity.Test
|
||||||
manager.Verify();
|
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]
|
[Theory]
|
||||||
[InlineData(true)]
|
[InlineData(true)]
|
||||||
[InlineData(false)]
|
[InlineData(false)]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue