TFA tweaks for templates (#1299)

This commit is contained in:
Hao Kung 2017-07-06 13:14:47 -07:00 committed by GitHub
parent a72acc93dc
commit b355f59a01
5 changed files with 62 additions and 10 deletions

View File

@ -7,7 +7,6 @@ using System.Linq;
using System.Linq.Expressions;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
@ -1890,6 +1889,7 @@ namespace Microsoft.AspNetCore.Identity.Test
{
IdentityResultAssert.IsSuccess(await manager.RedeemTwoFactorRecoveryCodeAsync(user, code));
IdentityResultAssert.IsFailure(await manager.RedeemTwoFactorRecoveryCodeAsync(user, code));
Assert.Equal(--numCodes, await manager.CountRecoveryCodesAsync(user));
}
// One last time to be sure
foreach (var code in newCodes)

View File

@ -31,5 +31,13 @@ namespace Microsoft.AspNetCore.Identity
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>True if the recovery code was found for the user.</returns>
Task<bool> RedeemCodeAsync(TUser user, string code, CancellationToken cancellationToken);
/// <summary>
/// Returns how many recovery code are still valid for a user.
/// </summary>
/// <param name="user">The user who owns the recovery code.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The number of valid recovery codes for the user..</returns>
Task<int> CountCodesAsync(TUser user, CancellationToken cancellationToken);
}
}

View File

@ -2167,7 +2167,7 @@ namespace Microsoft.AspNetCore.Identity
/// </summary>
/// <param name="user">The user to generate recovery codes for.</param>
/// <param name="number">The number of codes to generate.</param>
/// <returns>The new recovery codes for the user.</returns>
/// <returns>The new recovery codes for the user. Note: there may be less than number returned, as duplicates will be removed.</returns>
public virtual async Task<IEnumerable<string>> GenerateNewTwoFactorRecoveryCodesAsync(TUser user, int number)
{
ThrowIfDisposed();
@ -2183,7 +2183,7 @@ namespace Microsoft.AspNetCore.Identity
newCodes.Add(CreateTwoFactorRecoveryCode());
}
await store.ReplaceCodesAsync(user, newCodes, CancellationToken);
await store.ReplaceCodesAsync(user, newCodes.Distinct(), CancellationToken);
var update = await UpdateAsync(user);
if (update.Succeeded)
{
@ -2197,9 +2197,7 @@ namespace Microsoft.AspNetCore.Identity
/// </summary>
/// <returns></returns>
protected virtual string CreateTwoFactorRecoveryCode()
{
return Guid.NewGuid().ToString();
}
=> Guid.NewGuid().ToString().Substring(0, 8);
/// <summary>
/// Returns whether a recovery code is valid for a user. Note: recovery codes are only valid
@ -2225,6 +2223,23 @@ namespace Microsoft.AspNetCore.Identity
return IdentityResult.Failed(ErrorDescriber.RecoveryCodeRedemptionFailed());
}
/// <summary>
/// Returns how many recovery code are still valid for a user.
/// </summary>
/// <param name="user">The user.</param>
/// <returns>How many recovery code are still valid for a user.</returns>
public virtual Task<int> CountRecoveryCodesAsync(TUser user)
{
ThrowIfDisposed();
var store = GetRecoveryCodeStore();
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
return store.CountCodesAsync(user, CancellationToken);
}
/// <summary>
/// Releases the unmanaged resources used by the role manager and optionally releases the managed resources.
/// </summary>

View File

@ -992,9 +992,7 @@ namespace Microsoft.AspNetCore.Identity
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
public virtual Task SetAuthenticatorKeyAsync(TUser user, string key, CancellationToken cancellationToken)
{
return SetTokenAsync(user, InternalLoginProvider, AuthenticatorKeyTokenName, key, cancellationToken);
}
=> SetTokenAsync(user, InternalLoginProvider, AuthenticatorKeyTokenName, key, cancellationToken);
/// <summary>
/// Get the authenticator key for the specified <paramref name="user" />.
@ -1003,8 +1001,29 @@ namespace Microsoft.AspNetCore.Identity
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation, containing the security stamp for the specified <paramref name="user"/>.</returns>
public virtual Task<string> GetAuthenticatorKeyAsync(TUser user, CancellationToken cancellationToken)
=> GetTokenAsync(user, InternalLoginProvider, AuthenticatorKeyTokenName, cancellationToken);
/// <summary>
/// Returns how many recovery code are still valid for a user.
/// </summary>
/// <param name="user">The user who owns the recovery code.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The number of valid recovery codes for the user..</returns>
public virtual async Task<int> CountCodesAsync(TUser user, CancellationToken cancellationToken)
{
return GetTokenAsync(user, InternalLoginProvider, AuthenticatorKeyTokenName, cancellationToken);
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
var mergedCodes = await GetTokenAsync(user, InternalLoginProvider, RecoveryCodeTokenName, cancellationToken) ?? "";
if (mergedCodes.Length > 0)
{
return mergedCodes.Split(';').Length;
}
return 0;
}
/// <summary>

View File

@ -431,5 +431,15 @@ namespace Microsoft.AspNetCore.Identity.InMemory
}
return false;
}
public async Task<int> CountCodesAsync(TUser user, CancellationToken cancellationToken)
{
var mergedCodes = await GetTokenAsync(user, AuthenticatorStoreLoginProvider, RecoveryCodeTokenName, cancellationToken) ?? "";
if (mergedCodes.Length > 0)
{
return mergedCodes.Split(';').Length;
}
return 0;
}
}
}