Guard against null security stamps
This commit is contained in:
parent
82893848dd
commit
4dd38e8ca8
|
|
@ -1247,6 +1247,10 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(user));
|
throw new ArgumentNullException(nameof(user));
|
||||||
}
|
}
|
||||||
|
if (stamp == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(stamp));
|
||||||
|
}
|
||||||
user.SecurityStamp = stamp;
|
user.SecurityStamp = stamp;
|
||||||
return TaskCache.CompletedTask;
|
return TaskCache.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Identity
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the default <see cref="IdentityError"/>.
|
/// Returns the default <see cref="IdentityError"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The default <see cref="IdentityError"/>,</returns>
|
/// <returns>The default <see cref="IdentityError"/>.</returns>
|
||||||
public virtual IdentityError DefaultError()
|
public virtual IdentityError DefaultError()
|
||||||
{
|
{
|
||||||
return new IdentityError
|
return new IdentityError
|
||||||
|
|
|
||||||
|
|
@ -250,6 +250,22 @@ namespace Microsoft.AspNetCore.Identity
|
||||||
return string.Format(CultureInfo.CurrentCulture, GetString("NoTokenProvider"), p0);
|
return string.Format(CultureInfo.CurrentCulture, GetString("NoTokenProvider"), p0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// User security stamp cannot be null.
|
||||||
|
/// </summary>
|
||||||
|
internal static string NullSecurityStamp
|
||||||
|
{
|
||||||
|
get { return GetString("NullSecurityStamp"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// User security stamp cannot be null.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatNullSecurityStamp()
|
||||||
|
{
|
||||||
|
return GetString("NullSecurityStamp");
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Incorrect password.
|
/// Incorrect password.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -177,6 +177,10 @@
|
||||||
<value>No IUserTokenProvider named '{0}' is registered.</value>
|
<value>No IUserTokenProvider named '{0}' is registered.</value>
|
||||||
<comment>Error when there is no IUserTokenProvider</comment>
|
<comment>Error when there is no IUserTokenProvider</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="NullSecurityStamp" xml:space="preserve">
|
||||||
|
<value>User security stamp cannot be null.</value>
|
||||||
|
<comment>Error when a user's security stamp is null.</comment>
|
||||||
|
</data>
|
||||||
<data name="PasswordMismatch" xml:space="preserve">
|
<data name="PasswordMismatch" xml:space="preserve">
|
||||||
<value>Incorrect password.</value>
|
<value>Incorrect password.</value>
|
||||||
<comment>Error when a password doesn't match</comment>
|
<comment>Error when a password doesn't match</comment>
|
||||||
|
|
|
||||||
|
|
@ -2236,6 +2236,14 @@ namespace Microsoft.AspNetCore.Identity
|
||||||
|
|
||||||
private async Task<IdentityResult> ValidateUserInternal(TUser user)
|
private async Task<IdentityResult> ValidateUserInternal(TUser user)
|
||||||
{
|
{
|
||||||
|
if (SupportsUserSecurityStamp)
|
||||||
|
{
|
||||||
|
var stamp = await GetSecurityStampAsync(user);
|
||||||
|
if (stamp == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(Resources.NullSecurityStamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
var errors = new List<IdentityError>();
|
var errors = new List<IdentityError>();
|
||||||
foreach (var v in UserValidators)
|
foreach (var v in UserValidators)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -483,6 +483,42 @@ namespace Microsoft.AspNetCore.Identity.Test
|
||||||
hasher.VerifyAll();
|
hasher.VerifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CreateFailsWithNullSecurityStamp()
|
||||||
|
{
|
||||||
|
// Setup
|
||||||
|
var store = new Mock<IUserSecurityStampStore<TestUser>>();
|
||||||
|
var manager = MockHelpers.TestUserManager(store.Object);
|
||||||
|
var user = new TestUser { UserName = "nulldude" };
|
||||||
|
store.Setup(s => s.GetSecurityStampAsync(user, It.IsAny<CancellationToken>())).ReturnsAsync(null).Verifiable();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
// Assert
|
||||||
|
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => manager.CreateAsync(user));
|
||||||
|
Assert.Contains(Resources.NullSecurityStamp, ex.Message);
|
||||||
|
|
||||||
|
store.VerifyAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task UpdateFailsWithNullSecurityStamp()
|
||||||
|
{
|
||||||
|
// Setup
|
||||||
|
var store = new Mock<IUserSecurityStampStore<TestUser>>();
|
||||||
|
var manager = MockHelpers.TestUserManager(store.Object);
|
||||||
|
var user = new TestUser { UserName = "nulldude" };
|
||||||
|
store.Setup(s => s.GetSecurityStampAsync(user, It.IsAny<CancellationToken>())).ReturnsAsync(null).Verifiable();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
// Assert
|
||||||
|
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => manager.UpdateAsync(user));
|
||||||
|
Assert.Contains(Resources.NullSecurityStamp, ex.Message);
|
||||||
|
|
||||||
|
store.VerifyAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task RemoveClaimsCallsStore()
|
public async Task RemoveClaimsCallsStore()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue