Add ExternalSignIn overload that can bypass TFA

Move bypass into SignInOrTwoFactor helper
This commit is contained in:
Hao Kung 2016-08-08 14:10:16 -07:00
parent fe60304df5
commit fa976e7765
2 changed files with 63 additions and 4 deletions

View File

@ -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)
{

View File

@ -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)]