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