Add ExternalSignIn overload that can bypass TFA
Move bypass into SignInOrTwoFactor helper
This commit is contained in:
parent
fe60304df5
commit
fa976e7765
|
|
@ -433,7 +433,19 @@ namespace Microsoft.AspNetCore.Identity
|
|||
/// <param name="isPersistent">Flag indicating whether the sign-in cookie should persist after the browser is closed.</param>
|
||||
/// <returns>The task object representing the asynchronous operation containing the <see name="SignInResult"/>
|
||||
/// for the sign-in attempt.</returns>
|
||||
public virtual async Task<SignInResult> ExternalLoginSignInAsync(string loginProvider, string providerKey, bool isPersistent)
|
||||
public virtual Task<SignInResult> ExternalLoginSignInAsync(string loginProvider, string providerKey, bool isPersistent)
|
||||
=> ExternalLoginSignInAsync(loginProvider, providerKey, isPersistent, bypassTwoFactor: false);
|
||||
|
||||
/// <summary>
|
||||
/// Signs in a user via a previously registered third party login, as an asynchronous operation.
|
||||
/// </summary>
|
||||
/// <param name="loginProvider">The login provider to use.</param>
|
||||
/// <param name="providerKey">The unique provider identifier for the user.</param>
|
||||
/// <param name="isPersistent">Flag indicating whether the sign-in cookie should persist after the browser is closed.</param>
|
||||
/// <param name="bypassTwoFactor">Flag indicating whether to bypass two factor authentication.</param>
|
||||
/// <returns>The task object representing the asynchronous operation containing the <see name="SignInResult"/>
|
||||
/// for the sign-in attempt.</returns>
|
||||
public virtual async Task<SignInResult> ExternalLoginSignInAsync(string loginProvider, string providerKey, bool isPersistent, bool bypassTwoFactor)
|
||||
{
|
||||
var user = await UserManager.FindByLoginAsync(loginProvider, providerKey);
|
||||
if (user == null)
|
||||
|
|
@ -446,7 +458,7 @@ namespace Microsoft.AspNetCore.Identity
|
|||
{
|
||||
return error;
|
||||
}
|
||||
return await SignInOrTwoFactorAsync(user, isPersistent, loginProvider);
|
||||
return await SignInOrTwoFactorAsync(user, isPersistent, loginProvider, bypassTwoFactor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -582,9 +594,10 @@ namespace Microsoft.AspNetCore.Identity
|
|||
}
|
||||
|
||||
|
||||
private async Task<SignInResult> SignInOrTwoFactorAsync(TUser user, bool isPersistent, string loginProvider = null)
|
||||
private async Task<SignInResult> SignInOrTwoFactorAsync(TUser user, bool isPersistent, string loginProvider = null, bool bypassTwoFactor = false)
|
||||
{
|
||||
if (UserManager.SupportsUserTwoFactor &&
|
||||
if (!bypassTwoFactor &&
|
||||
UserManager.SupportsUserTwoFactor &&
|
||||
await UserManager.GetTwoFactorEnabledAsync(user) &&
|
||||
(await UserManager.GetValidTwoFactorProvidersAsync(user)).Count > 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -314,6 +314,52 @@ namespace Microsoft.AspNetCore.Identity.Test
|
|||
auth.Verify();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public async Task ExternalSignInRequiresVerificationIfNotBypassed(bool bypass)
|
||||
{
|
||||
// Setup
|
||||
var user = new TestUser { UserName = "Foo" };
|
||||
const string loginProvider = "login";
|
||||
const string providerKey = "fookey";
|
||||
var manager = SetupUserManager(user);
|
||||
manager.Setup(m => m.SupportsUserLockout).Returns(false).Verifiable();
|
||||
manager.Setup(m => m.FindByLoginAsync(loginProvider, providerKey)).ReturnsAsync(user).Verifiable();
|
||||
if (!bypass)
|
||||
{
|
||||
IList<string> providers = new List<string>();
|
||||
providers.Add("PhoneNumber");
|
||||
manager.Setup(m => m.GetValidTwoFactorProvidersAsync(user)).Returns(Task.FromResult(providers)).Verifiable();
|
||||
manager.Setup(m => m.SupportsUserTwoFactor).Returns(true).Verifiable();
|
||||
manager.Setup(m => m.GetTwoFactorEnabledAsync(user)).ReturnsAsync(true).Verifiable();
|
||||
}
|
||||
var context = new Mock<HttpContext>();
|
||||
var auth = new Mock<AuthenticationManager>();
|
||||
context.Setup(c => c.Authentication).Returns(auth.Object).Verifiable();
|
||||
var helper = SetupSignInManager(manager.Object, context.Object);
|
||||
|
||||
if (bypass)
|
||||
{
|
||||
SetupSignIn(auth, user.Id, false, loginProvider);
|
||||
}
|
||||
else
|
||||
{
|
||||
auth.Setup(a => a.SignInAsync(helper.Options.Cookies.TwoFactorUserIdCookieAuthenticationScheme,
|
||||
It.Is<ClaimsPrincipal>(id => id.FindFirstValue(ClaimTypes.Name) == user.Id))).Returns(Task.FromResult(0)).Verifiable();
|
||||
}
|
||||
|
||||
// Act
|
||||
var result = await helper.ExternalLoginSignInAsync(loginProvider, providerKey, isPersistent: false, bypassTwoFactor: bypass);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(bypass, result.Succeeded);
|
||||
Assert.Equal(!bypass, result.RequiresTwoFactor);
|
||||
manager.Verify();
|
||||
context.Verify();
|
||||
auth.Verify();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, true)]
|
||||
[InlineData(true, false)]
|
||||
|
|
|
|||
Loading…
Reference in New Issue