简体   繁体   English

AspNetCore.Identity.UserManager[9] VerifyUserTokenAsync() "code": "InvalidToken",

[英]AspNetCore.Identity.UserManager[9] VerifyUserTokenAsync() "code": "InvalidToken",

I am making api in .net 5 and implementing sending email confirmation after succesful registration.我正在 .net 5 中制作 api 并在成功注册后实现发送 email 确认。 This one is killing me and can't see the reason why it returns Invalid Token .这个正在杀死我,看不到它返回Invalid Token的原因。

So here's my code:所以这是我的代码:

Startup.cs启动.cs

services.AddAuthentication
...
...
...
services.AddIdentityCore<User>(config =>
{
  config.SignIn.RequireConfirmedEmail = true;

}).AddEntityFrameworkStores<WorkoutDbContext>()
.AddDefaultTokenProviders();

EmailHelper.cs电子邮件助手.cs

    public class EmailHelper
    {
        public bool SendEmail(string userEmail, string confirmationLink)
        {
            MailMessage mailMessage = new MailMessage();
            mailMessage.From = new MailAddress("noreply@*********.io");
            mailMessage.To.Add(new MailAddress(userEmail));

            mailMessage.Subject = "Confirm your email";
            mailMessage.IsBodyHtml = false;
            mailMessage.Body = confirmationLink;
            SmtpClient client = new SmtpClient();
            client.UseDefaultCredentials = false;
            client.Credentials = new System.Net.NetworkCredential("noreply@*********.io", "super secret password");
            client.Host = "host";
            client.Port = 000;
            client.EnableSsl = false;
            client.DeliveryFormat = (SmtpDeliveryFormat)SmtpDeliveryMethod.Network;
            try
            {
                client.Send(mailMessage);
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                // log exception
            }
            return false;
        }
    }

AccountService.cs AccountService.cs

        public async void RegisterUser(RegisterUserDto dto)
        {
            var uniqueId = Guid.NewGuid().ToString()[..8];
            var newUser = new User()
            {
                Name = dto.Name,
                LastName = dto.LastName,
                Email = dto.Email,
                EmailConfirmed = false,
                UniqeId = uniqueId,
                RegistrationDate = DateTime.Now,
                Active = false,
                RoleId = dto.RoleId
            };

            var hashedPassword = _passwordHasher.HashPassword(newUser, dto.Password);
            newUser.Password = hashedPassword;
            newUser.NormalizedEmail = dto.Email;
            _context.Add(newUser);
            _context.SaveChanges();
            var user = await _userManager.FindByEmailAsync(newUser.Email);
            if(user != null)
            {
                EmailHelper emailHelper = new EmailHelper();
                var token = HttpUtility.UrlEncode(await _userManager.GenerateEmailConfirmationTokenAsync(newUser));
                var confirmationLink = "http://localhost:5000/confirmEmail?token=" + token + "&email=" + newUser.NormalizedEmail;
                bool emailResponse = emailHelper.SendEmail(newUser.NormalizedEmail, confirmationLink);
            } 

        }

User registration works fine.用户注册工作正常。 If email is not registered than registration fails.如果 email 未注册,则注册失败。 Otherwise server return 200 as expected.否则服务器按预期返回 200。 Confirmation link is sent to email provided during registration process.确认链接发送至注册过程中提供的 email。 So till now works as expected.所以直到现在按预期工作。

EmailController.cs电子邮件控制器.cs

        [HttpGet]
        public async Task<IdentityResult> ConfirmEmail([FromQuery]string token, [FromQuery] string email)
        {
            var user = await _userManager.FindByEmailAsync(email);
            var result = await _userManager.ConfirmEmailAsync(user, token);
            if (result.Succeeded) { return IdentityResult.Success; }
            else { return (IdentityResult) result;  }

        }

Problem start when clicking on activation link - it throws warn: Microsoft.AspNetCore.Identity.UserManager[9] VerifyUserTokenAsync() "code": "InvalidToken", So activation link is sent, it checks if user !== null and than goes to conditional statement and triggers EmailHelper which sends link to inbox correctly.单击激活链接时出现问题 - 它会引发warn: Microsoft.AspNetCore.Identity.UserManager[9] VerifyUserTokenAsync() "code": "InvalidToken",所以激活链接已发送,它会检查user !== null并且比去到条件语句并触发正确发送链接到收件箱的EmailHelper

...BUT ...但

When I try to console user - it's empty, nothing shows in console.当我尝试安慰用户时 - 它是空的,控制台中没有显示任何内容。 Database is updated and user is saved in DB and it's visible and accessible.数据库已更新,用户保存在数据库中,并且可见且可访问。 In EmailController.cs it does not return userEmailController.cs它不返回用户

   var user = await _userManager.FindByEmailAsync(email);
   // if I try to console it it shows nothing - empty(not NULL)

If I try to send serialized user data to inbox instead of sending activation link it sends correct data from DB.如果我尝试将序列化的用户数据发送到收件箱而不是发送激活链接,它会从 DB 发送正确的数据。

So to sum up:所以总结一下:

  • user is created and saved in DB,用户被创建并保存在数据库中,
  • sending user data to inbox instead of confirmationLink sends accurate and correct data of user from database and proves that everything went ok将用户数据发送到收件箱而不是确认链接从数据库发送准确和正确的用户数据,并证明一切正常
  • confirmation link is generated correctly and send to inbox确认链接正确生成并发送到收件箱
  • checking var user = await _userManager.FindByEmailAsync(newUser.Email); if(user != null)检查var user = await _userManager.FindByEmailAsync(newUser.Email); if(user != null) var user = await _userManager.FindByEmailAsync(newUser.Email); if(user != null) makes user NOT null send allows to send email var user = await _userManager.FindByEmailAsync(newUser.Email); if(user != null)使用户 NOT null 发送允许发送 email

And this is killing me and do not know why checking if user exists gives true but trying to access via await _userManager.FindByEmailAsync(newUser.Email);这让我很生气,不知道为什么检查用户是否存在给出了 true 但尝试通过await _userManager.FindByEmailAsync(newUser.Email);访问gives no user(nothing)?没有用户(什么都没有)? I tried also (in EmailController ) _context.Users.FirstOrDefault(u => u.NormalizedEmail == email) but the result is the same - cannot get user from DB and returns我也试过(在EmailController中) _context.Users.FirstOrDefault(u => u.NormalizedEmail == email)但结果是一样的 - 无法从数据库中获取用户并返回

Microsoft.AspNetCore.Identity.UserManager[9]
      VerifyUserTokenAsync() failed with purpose: EmailConfirmation for user.

UPDATE IdentityResult output更新身份结果 output

{
  "succeeded": false,
  "errors": [
    {
      "code": "InvalidToken",
      "description": "Invalid token."
    }
  ]
}

UPDATE #2更新#2

When I serialize user and try to display in console it actually shows correct user data as a string.当我序列化user并尝试在控制台中显示时,它实际上将正确的用户数据显示为字符串。 The problem seems to be that neither var user = await _userManager.FindByEmailAsync(email);问题似乎是var user = await _userManager.FindByEmailAsync(email); nor var user= _context.Users.FirstOrDefault(u => u.Email == email);也不是var user= _context.Users.FirstOrDefault(u => u.Email == email); does not return user that can be verified.不返回可以验证的用户。

UPDATE #3更新#3

No IUserTwoFactorTokenProvider<TUser> named 'xxxx' is registered. System.NotSupportedException: No IUserTwoFactorTokenProvider<TUser> named 'xxxx' is registered. But AddDefaultTokenProviders() was implemented in Startup.cs Even tried config.Tokens.EmailConfirmationTokenProvider = TokenOptions.DefaultEmailProvider;但是在 Startup.cs 中实现了AddDefaultTokenProviders()甚至尝试config.Tokens.EmailConfirmationTokenProvider = TokenOptions.DefaultEmailProvider; or config.Tokens.ProviderMap.Add("Default", new TokenProviderDescriptor(typeof(IUserTwoFactorTokenProvider<User>)));config.Tokens.ProviderMap.Add("Default", new TokenProviderDescriptor(typeof(IUserTwoFactorTokenProvider<User>))); but the result is the same.但结果是一样的。

I was working on the solution for past few days but finally found a solution!过去几天我一直在研究解决方案,但终于找到了解决方案!

Since I am using IdentityUser but my User model did not contain table columns from Identity it cause problem, most likely because that security stamp column was not present.由于我使用的是IdentityUser但我的User model 不包含来自 Identity 的表列,因此会导致问题,很可能是因为该安全标记列不存在。

What I did was to include table columns from IdentityUser .我所做的是包含来自IdentityUser的表列。

I have also included我也包括了

            services.AddIdentityCore<User>(config =>
            {
                config.SignIn.RequireConfirmedEmail = true;
                config.Tokens.EmailConfirmationTokenProvider = TokenOptions.DefaultEmailProvider; <--- this line!!
            }).AddEntityFrameworkStores<WorkoutDbContext>()
            .AddDefaultTokenProviders();

Also in EmailController.cs in ConfirmEmail I had to decode token because I was encoding this with HttpUtility.Encode when egenrating.同样在ConfirmEmailEmailController.cs中,我必须decode令牌,因为我在生成时使用HttpUtility.Encode对其进行encoding var tokenDecode = HttpUtility.UrlDecode(token);

Than I checked with VerifyUserTokenAsync which returned true .比我检查返回trueVerifyUserTokenAsync After that I only received confirmation error when email was clicked that Username '' is invalid. Username can have only letters and number.之后,我只在单击 email 时收到确认错误,即Username '' is invalid. Username can have only letters and number. Username '' is invalid. Username can have only letters and number.

What I also did was generating userName containing only letters and numbers from email that was used for registration and assigning it to UserName column in DB set.我还做的是生成仅包含来自userName的字母和数字的用户名,用于注册并将其分配给数据库集中的UserName名列。

After that when email was sent and clicked it returned IdentityResult.Success之后,当发送 email 并单击它返回IdentityResult.Success

Damn.该死。 It was a long way home: :)回家的路很长::)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Microsoft.AspNetCore.Identity.UserManager:警告:VerifyUserTokenAsync() 失败,目的是:ResetPassword for user - Microsoft.AspNetCore.Identity.UserManager: Warning: VerifyUserTokenAsync() failed with purpose: ResetPassword for user 在界面中使用 AspNetCore.Identity RoleManager 和 UserManager - Use AspNetCore.Identity RoleManager and UserManager in an Interface AspNetCore.Identity UserManager CreateAsync无法保存关系 - AspNetCore.Identity UserManager CreateAsync cannot save relationships InvalidOperationException:无法解析类型为“Microsoft.AspNetCore.Identity.UserManager”的服务 - InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Identity.UserManager` 如何获取 userManager.VerifyUserTokenAsync 的目的字段? - How to get purpose field for userManager.VerifyUserTokenAsync? 无法解析“Microsoft.AspNetCore.Identity.UserManager”类型的服务 - Unable to resolve service for type 'Microsoft.AspNetCore.Identity.UserManager 没有注册“Microsoft.AspNetCore.Identity.UserManager`1[Microsoft.AspNetCore.Identity.IdentityUser]”类型的服务 - No service for type 'Microsoft.AspNetCore.Identity.UserManager`1[Microsoft.AspNetCore.Identity.IdentityUser]' has been registered 没有为“Microsoft.AspNetCore.Identity.UserManager`1[testLogin.Areas.Identity.Data.testLoginUser]”类型注册服务 - No service for type 'Microsoft.AspNetCore.Identity.UserManager`1[testLogin.Areas.Identity.Data.testLoginUser]' has been registered 没有类型“Microsoft.AspNetCore.Identity.UserManager”的服务:在尝试扩展 IdentityUser 时? - No service for type 'Microsoft.AspNetCore.Identity.UserManager' : while trying to extend IdentityUser? 尝试激活“AuthController”时无法解析“Microsoft.AspNetCore.Identity.UserManager”类型的服务 - Unable to resolve service for type 'Microsoft.AspNetCore.Identity.UserManager` while attempting to activate 'AuthController'
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM