确认电子邮件中的ASP.NET Core身份无效令牌 [英] ASP.NET Core Identity invalid token on confirmation email

查看:95
本文介绍了确认电子邮件中的ASP.NET Core身份无效令牌的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是与此非常相似的问题 在确认电子邮件中 aspnet身份无效令牌 但是解决方案无效,因为我使用的是包含ASP.NET Core身份的新ASP.NET Core 1.0.

This is a very similar question to this aspnet identity invalid token on confirmation email but the solutions are not valid because I am using the new ASP.NET Core 1.0 that includes ASP.NET Core Identity.

我的情况如下:

  1. 在后端(ASP.NET Core)中,我有一个函数可以发送带有链接的密码重置电子邮件.为了生成该链接,我必须使用Identity生成一个代码.像这样的东西.

  1. In the back end (ASP.NET Core) I have a function that sends a password reset email with a link. In order to generate that link I have to generate a code using Identity. 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);
    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 would generate an email with a link to:

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

然后,我的AngularJs应用程序将显示一个带有输入和确认新密码的表单的视图,并使用新密码和从URL中的查询参数获得的代码来放置JSON对象.

Then my AngularJs application would present a view with a form to enter and confirm the new password, and would PUT a JSON object with the new password and the code that got from the query parameter in the URL.

最后,我的后端将收到PUT请求,获取代码并使用Identity进行验证,如下所示:

Finally my back end would get the PUT request, grab the code and validate it using Identity like this:

[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();
}

问题是身份以

无效的令牌

Invalid token

错误.我发现问题在于代码不匹配,并且上面的代码将在PUT请求的JSON对象中被接收回去,如下所示:

error. I have found that the problem is that the codes don't match and the above code would be received back in the JSON object in the PUT request as follows:

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

请注意,现在有+个符号的地方有空格个符号,很显然,这使Identity认为令牌是不同的. 出于某种原因,Angular会以与编码不同的方式来解码URL查询参数.

Notice that where there was + symbols now there are spaces symbols and obviously that causes Identity to think the tokens are different. For some reason Angular is decoding the URL query parameter in a different way that was encoded.

该如何解决?

推荐答案

此答案 https://stackoverflow.com/a/31297879/2948212 为我指明了正确的方向.但是正如我说的是用于其他版本的解决方案,现在它的解决方案略有不同.

This answer https://stackoverflow.com/a/31297879/2948212 pointed me in the right direction. But as I said it was for a different version and now it is slightly different solution.

答案仍然是相同的:以基本64 URL编码令牌,然后以基本64 URL解码令牌.这样,Angular和ASP.NET Core都将检索完全相同的代码.

The answer is still the same: encode the token in base 64 url, and then decode it in base 64 url. That way both Angular and ASP.NET Core will retrieve the very same code.

我需要为Microsoft.AspNetCore.WebUtilities;

现在代码将是这样的:

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

以及在PUT请求期间接收回代码时

and when receiving back the code during the 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);
}

这篇关于确认电子邮件中的ASP.NET Core身份无效令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆