diff --git a/src/Microsoft.AspNetCore.Identity.Specification.Tests/UserManagerSpecificationTests.cs b/src/Microsoft.AspNetCore.Identity.Specification.Tests/UserManagerSpecificationTests.cs
index df5dae884..7bf7f81aa 100644
--- a/src/Microsoft.AspNetCore.Identity.Specification.Tests/UserManagerSpecificationTests.cs
+++ b/src/Microsoft.AspNetCore.Identity.Specification.Tests/UserManagerSpecificationTests.cs
@@ -1532,6 +1532,24 @@ public async Task CanChangePhoneNumber()
Assert.NotEqual(stamp, await manager.GetSecurityStampAsync(user));
}
+ ///
+ /// Test.
+ ///
+ /// Task
+ [Fact]
+ public async Task ChangePhoneNumberTokenIsInt()
+ {
+ if (ShouldSkipDbTests())
+ {
+ return;
+ }
+ var manager = CreateManager();
+ var user = CreateTestUser(phoneNumber: "123-456-7890");
+ IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
+ var token1 = await manager.GenerateChangePhoneNumberTokenAsync(user, "111-111-1111");
+ Assert.True(int.TryParse(token1, out var ignored));
+ }
+
///
/// Test.
///
@@ -1550,7 +1568,7 @@ public async Task ChangePhoneNumberFailsWithWrongToken()
var stamp = await manager.GetSecurityStampAsync(user);
IdentityResultAssert.IsFailure(await manager.ChangePhoneNumberAsync(user, "111-111-1111", "bogus"),
"Invalid token.");
- IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyUserTokenAsync() failed with purpose: ChangePhoneNumber:111-111-1111 for user { await manager.GetUserIdAsync(user)}.");
+ IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyChangePhoneNumberTokenAsync() failed for user { await manager.GetUserIdAsync(user)}.");
Assert.False(await manager.IsPhoneNumberConfirmedAsync(user));
Assert.Equal("123-456-7890", await manager.GetPhoneNumberAsync(user));
Assert.Equal(stamp, await manager.GetSecurityStampAsync(user));
@@ -1605,7 +1623,7 @@ public async Task CanVerifyPhoneNumber()
Assert.True(await manager.VerifyChangePhoneNumberTokenAsync(user, token2, num2));
Assert.False(await manager.VerifyChangePhoneNumberTokenAsync(user, token2, num1));
Assert.False(await manager.VerifyChangePhoneNumberTokenAsync(user, token1, num2));
- IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyUserTokenAsync() failed with purpose: ChangePhoneNumber:111-123-4567 for user {await manager.GetUserIdAsync(user)}.");
+ IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyChangePhoneNumberTokenAsync() failed for user {await manager.GetUserIdAsync(user)}.");
}
///
diff --git a/src/Microsoft.Extensions.Identity.Core/UserManager.cs b/src/Microsoft.Extensions.Identity.Core/UserManager.cs
index 5aa64f3e1..7c0cf8718 100644
--- a/src/Microsoft.Extensions.Identity.Core/UserManager.cs
+++ b/src/Microsoft.Extensions.Identity.Core/UserManager.cs
@@ -1579,10 +1579,12 @@ public virtual Task IsPhoneNumberConfirmedAsync(TUser user)
///
/// The that represents the asynchronous operation, containing the telephone change number token.
///
- public virtual Task GenerateChangePhoneNumberTokenAsync(TUser user, string phoneNumber)
+ public virtual async Task GenerateChangePhoneNumberTokenAsync(TUser user, string phoneNumber)
{
ThrowIfDisposed();
- return GenerateUserTokenAsync(user, Options.Tokens.ChangePhoneNumberTokenProvider, ChangePhoneNumberTokenPurpose + ":" + phoneNumber);
+ return Rfc6238AuthenticationService.GenerateCode(
+ await CreateSecurityTokenAsync(user), phoneNumber)
+ .ToString(CultureInfo.InvariantCulture);
}
///
@@ -1596,16 +1598,21 @@ public virtual Task GenerateChangePhoneNumberTokenAsync(TUser user, stri
/// The that represents the asynchronous operation, returning true if the
/// is valid, otherwise false.
///
- public virtual Task VerifyChangePhoneNumberTokenAsync(TUser user, string token, string phoneNumber)
+ public virtual async Task VerifyChangePhoneNumberTokenAsync(TUser user, string token, string phoneNumber)
{
ThrowIfDisposed();
- if (user == null)
+
+ var securityToken = await CreateSecurityTokenAsync(user);
+ int code;
+ if (securityToken != null && Int32.TryParse(token, out code))
{
- throw new ArgumentNullException(nameof(user));
+ if (Rfc6238AuthenticationService.ValidateCode(securityToken, code, phoneNumber))
+ {
+ return true;
+ }
}
-
- // Make sure the token is valid and the stamp matches
- return VerifyUserTokenAsync(user, Options.Tokens.ChangePhoneNumberTokenProvider, ChangePhoneNumberTokenPurpose+":"+ phoneNumber, token);
+ Logger.LogWarning(8, "VerifyChangePhoneNumberTokenAsync() failed for user {userId}.", await GetUserIdAsync(user));
+ return false;
}
///