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; } ///