aspnet identity invalid token on confirmation email
但解决方案无效,因为我使用的是包含ASP.NET核心标识的新ASP.NET Core 1.0.
我的方案如下:
>在后端(ASP.NET Core)我有一个函数,它发送一个带有链接的密码重置电子邮件.为了生成该链接,我必须使用Identity生成代码.像这样的东西.
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);
}
这会生成一封电子邮件,其中包含以下链接:
HTTP:// MyApp的:8080 / passwordreset代码= CfDJ8JBnWaVj6h1PtqlmlJaH57r9TRA5j7Ij1BVyeBUpqX 5Cq1msu9zgkuI32Iz9x / 5uE1B9fKFp4tZFFy6lBTseDFTHSJxwtGu jHX5cajptUBiVqIChiwoTODh7ei4 MOkX7rdNVBMhG4jOZWqqtZ5J30gXr / JmltbYxqOp4JLs8V05BeKDbbVO / Fsq5 jebokKkR5HEJU mQ5MLvNURsJKRBbI3qIllj1RByXt9mufGRE3wmQf2fgKBkAL6VsNgB8w ==
>然后我的AngularJs应用程序将显示一个视图,其中包含一个用于输入和确认新密码的表单,并将使用新密码和从URL中的查询参数获取的代码输出JSON对象.
>最后我的后端将获得PUT请求,获取代码并使用Identity验证它,如下所示:
[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对象中收到,如下所示:
CfDJ8JBnWaVj6h1PtqlmlJaH57r9TRA5j7Ij1BVyeBUpqX 5Cq1msu9zgkuI32Iz9x/5uE1B9fKFp4tZFFy6lBTseDFTHSJxwtGu jHX5cajptUBiVqIChiwoTODh7ei4 MOkX7rdNVBMhG4jOZWqqtZ5J30gXr/JmltbYxqOp4JLs8V05BeKDbbVO/Fsq5 jebokKkR5HEJU mQ5MLvNURsJKRBbI3qIllj1RByXt9mufGRE3wmQf2fgKBkAL6VsNgB8w==
请注意,现在有符号的地方有空格符号,显然会导致身份认为令牌不同.
出于某种原因,Angular以不同的方式解码URL查询参数.
怎么解决这个?
答案仍然是相同的:在base 64 url中编码令牌,然后在base 64 url中对其进行解码.这样,Angular和ASP.NET Core都将检索相同的代码.
我需要为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",code = codeEncoded },link);
}
当在PUT请求期间接收代码时
[HttpPut]
[AllowAnonymous]
[Route("api/password/{email}")]
public async Task<IActionResult> SendPasswordEmailResetRequestAsync(string email,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);
}