Invalid ASP.NET Core Identity Token in Verification Email

This is a very similar question to this question. Invalid aspnet identification token in the confirmation email but the solutions are invalid because I am using the new ASP.NET Core 1.0, which includes the ASP.NET kernel identifier.

My scenario is as follows:

  • At the end (ASP.NET core), I have a function that sends a reset password by reference. To generate this link, I need to generate the code using Identity. Something like that.

    public async Task SendPasswordResetEmailAsync(string email) { //_userManager is an instance of UserManager<User> var userEntity = await _userManager.FindByNameAsync(email); var tokenGenerated = await _userManager.GeneratePasswordResetTokenAsync(userEntity); var link = Url.Action("MyAction", "MyController", new { email = email, code = tokenGenerated }, protocol: HttpContext.Request.Scheme); //this is my service that sends an email to the user containing the generated password reset link await _emailService.SendPasswordResetEmailAsync(userEntity , link); } 

    this will create an email with a link to:

    http://myapp:8080/passwordreset?code=CfDJ8JBnWaVj6h1PtqlmlJaH57r9TRA5j7Ij1BVyeBUpqX+5Cq1msu9zgkuI32Iz9x/5uE1B9fKFp4tZFFy6lBTseDFTHSJxwtGu+jHX5cajptUBiVqIChiwoTODh7ei4+MOkX7rdNVBMhG4jOZWqqtZ5J30gXr/JmltbYxqOp4JLs8V05BeKDbbVO/Fsq5+jebokKkR5HEJU+mQ5MLvNURsJKRBbI3qIllj1RByXt9mufGRE3wmQf2fgKBkAL6VsNgB8w==

  • Then my AngularJs application would present a view with a form for entering and confirming a new password and place a JSON object with the new password and code obtained from the request parameter in the URL.

  • Finally, my trailing end will receive a PUT request, take the code and verify it with Identity as follows:

     [HttpPut] [AllowAnonymous] [Route("api/password/{email}")] public async Task<IActionResult> SendPasswordEmailResetRequestAsync(string email, [FromBody] PasswordReset passwordReset) { //some irrelevant validatoins here await _myIdentityWrapperService.ResetPasswordAsync(email, passwordReset.Password, passwordReset.Code); return Ok(); } 

The problem is that Identity is responding

Invalid Token

mistake. I found that the problem is that the codes do not match, and the above code will be retrieved back to the JSON object in the PUT request as follows:

 CfDJ8JBnWaVj6h1PtqlmlJaH57r9TRA5j7Ij1BVyeBUpqX 5Cq1msu9zgkuI32Iz9x/5uE1B9fKFp4tZFFy6lBTseDFTHSJxwtGu jHX5cajptUBiVqIChiwoTODh7ei4 MOkX7rdNVBMhG4jOZWqqtZ5J30gXr/JmltbYxqOp4JLs8V05BeKDbbVO/Fsq5 jebokKkR5HEJU mQ5MLvNURsJKRBbI3qIllj1RByXt9mufGRE3wmQf2fgKBkAL6VsNgB8w== 

Note that where there are + characters, there are now spaces , and, obviously, this makes Identity think that the tokens are different. For some reason, Angular decodes the URL request parameter in a different way that has been encoded.

How to resolve this?

+14
angularjs asp.net-core forgot-password asp.net-identity
source share
2 answers

This answer fooobar.com/questions/171086 / ... pointed me in the right direction. But, as I said, this was for a different version, and now this is a slightly different solution.

The answer is the same: encode the token in the base url of 64, and then decode it in the URL of the base 64. Thus, both Angular and ASP.NET Core will get the same code.

I needed to install another dependency for Microsoft.AspNetCore.WebUtilities;

Now the code will be something like this:

 public async Task SendPasswordResetEmailAsync(string email) { //_userManager is an instance of UserManager<User> var userEntity = await _userManager.FindByNameAsync(email); var tokenGenerated = await _userManager.GeneratePasswordResetTokenAsync(userEntity); byte[] tokenGeneratedBytes = Encoding.UTF8.GetBytes(tokenGenerated); var codeEncoded = WebEncoders.Base64UrlEncode(tokenGeneratedBytes); var link = Url.Action("MyAction", "MyController", new { email = email, code = codeEncoded }, protocol: HttpContext.Request.Scheme); //this is my service that sends an email to the user containing the generated password reset link await _emailService.SendPasswordResetEmailAsync(userEntity , link); } 

and when returning the code during a PUT request

 [HttpPut] [AllowAnonymous] [Route("api/password/{email}")] public async Task<IActionResult> SendPasswordEmailResetRequestAsync(string email, [FromBody] PasswordReset passwordReset) { //some irrelevant validatoins here await _myIdentityWrapperService.ResetPasswordAsync(email, passwordReset.Password, passwordReset.Code); return Ok(); } //in MyIdentityWrapperService public async Task ResetPasswordAsync(string email, string password, string code) { var userEntity = await _userManager.FindByNameAsync(email); var codeDecodedBytes = WebEncoders.Base64UrlDecode(code); var codeDecoded = Encoding.UTF8.GetString(codeDecodedBytes); await _userManager.ResetPasswordAsync(userEntity, codeDecoded, password); } 
+19
source share

I had a similar problem and I encoded my token, but it continued to fail the test, and the problem turned out to be the following: options.LowercaseQueryStrings = true; Do not set true to options.LowercaseQueryStrings , this changes the integrity of the validation token, and you get an Invalid Token Error.

 // This allows routes to be in lowercase services.AddRouting(options => { options.LowercaseUrls = true; options.LowercaseQueryStrings = false; }); 
0
source share

All Articles