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>
|
/// <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"/>
|
/// <returns>The task object representing the asynchronous operation containing the <see name="SignInResult"/>
|
||||||
/// for the sign-in attempt.</returns>
|
/// 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);
|
var user = await UserManager.FindByLoginAsync(loginProvider, providerKey);
|
||||||
if (user == null)
|
if (user == null)
|
||||||
|
|
@ -446,7 +458,7 @@ namespace Microsoft.AspNetCore.Identity
|
||||||
{
|
{
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
return await SignInOrTwoFactorAsync(user, isPersistent, loginProvider);
|
return await SignInOrTwoFactorAsync(user, isPersistent, loginProvider, bypassTwoFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.GetTwoFactorEnabledAsync(user) &&
|
||||||
(await UserManager.GetValidTwoFactorProvidersAsync(user)).Count > 0)
|
(await UserManager.GetValidTwoFactorProvidersAsync(user)).Count > 0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -314,6 +314,52 @@ namespace Microsoft.AspNetCore.Identity.Test
|
||||||
auth.Verify();
|
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]
|
[Theory]
|
||||||
[InlineData(true, true)]
|
[InlineData(true, true)]
|
||||||
[InlineData(true, false)]
|
[InlineData(true, false)]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue