Search code examples
c#asp.net.netasp.net-mvcasp.net-identity

Getting invalid token error from Identity when running UserManager.ResetPasswordAsync()


I have a .net 6 application with Identity for authentication handling. In a reset password endpoint, I'm struggling with a "Invalid token" error from Identity.

Token generation service:

        public async Task AskPasswordReset(string email)
        {
            var user = await _userManager.FindByEmailAsync(email);
            if (user != null)
            {
                var token = await _userManager.GeneratePasswordResetTokenAsync(user);
                var confirmationLink = _configuration["Base Url"] + "/ResetPassword?token=" + token + "&email=" + email;
                var emailAddress = email;
                var confimEmail = new EmailCommunicationDto
                {
                    To = emailAddress,
                    Body = $"You have a requested to reset you password.  Please click the link provided to reset your password.  Please click " + confirmationLink + " to reset.",
                    Subject = "Password Reset"
                };
                await _emailSender.SendVerificationEmail(confimEmail);

            }
        }

Token reset service:

        public async Task ResetPassword(ResetPasswordDto resetPasswordDto)
        {
            var user = await _userManager.FindByEmailAsync(resetPasswordDto.email);
            if (user == null)
            {
                throw new NotFoundException();
            }
            var result = await _userManager.ResetPasswordAsync(user, resetPasswordDto.token, resetPasswordDto.newPassword);
            if (!result.Succeeded)
            {
                Console.WriteLine(result.ToString());
                throw new InvalidCredentialsException();
            }
        }

Generated email:

You have a requested to reset you password. Please click the link provided to reset your password. Please click https://localhost:3000/ResetPassword?token=CfAA8KTxCSxQvlpEtzGh0VfCOQoKfuszpNPEK/yXBxCLkB2iC07vDNHecXedk6GFdl/ZlO8oqxxDNrVjj5ZdiPCXdpleOcfU2+utrCm7MLqlEWQYfx6RvAlmLRgKwcrIqVE1kXLqEGvdumAgDYYfCw0m5RosDgf0JlW3fthpbQWgIe5CoOl9UWJV20gdl2hVgh95wLhRV7WfWNTXSYv28K9ZQk31YzOhNaFjmgqXOSHAgTI2&[email protected] to reset.

Reset password DTO:

{ "newPassword": "joijoji9**Koji", "token": "CfAA8KTxCSxQvlpEtzGh0VfCOQoKfuszpNPEK/yXBxCLkB2iC07vDNHecXedk6GFdl/ZlO8oqxxDNrVjj5ZdiPCXdpleOcfU2 utrCm7MLqlEWQYfx6RvAlmLRgKwcrIqVE1kXLqEGvdumAgDYYfCw0m5RosDgf0JlW3fthpbQWgIe5CoOl9UWJV20gdl2hVgh95wLhRV7WfWNTXSYv28K9ZQk31YzOhNaFjmgqXOSHAgTI2", "email": "[email protected]" }

1st guess: When the token is gotten from the url (I'm using React), there is a decoding that alters it. 2nd guess: Identity only allows password reset after email verification


Solution

  • Your first guess looks promising to me, since the token you're appending in your URL contains special characters like '/'.

    Try encoding the token before appending it, with something like

    token = Base64UrlEncoder.Encode(token);
    var confirmationLink = _configuration["Base Url"] + "/ResetPassword?token=" + token + "&email=" + email;