This project is read-only.

Email confirmation token problem

May 5, 2014 at 10:00 PM
I have some more complex scenario than in examples. I create an user account without setting password and send the confirmation email. During the conformation user is setting password and confirming email. Unfortunately I'm getting the "Invalid token" error. Here is my code:
[HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Create(CreateViewModel model)
        {
            if (ModelState.IsValid)
            {
                var user = new AppUser { UserName = model.Email, Email = model.Email, FirstName = model.Name, LastName = model.Surname };

                try
                {
                    await userRepository.InsertAndSubmitAsync(user);

                    var userManager = HttpContext.GetOwinContext().GetUserManager<AppUserManager>();
                    var code = await userManager.GenerateEmailConfirmationTokenAsync(user.Id);
                    var callbackUrl = Url.Action("SetPassword", "Account", new { area = "", userId = user.Id, code = code }, protocol: Request.Url.Scheme);
                    await userManager.SendEmailAsync(user.Id, AppConstants.EmailSubjectPrefix + " Account Creation", "Your account was created.<br/>Click <a href=\"" + callbackUrl + "\">here</a> to activate your account and set password.");

                    this.Success("Account created.");
                    return RedirectToAction("Index");
                }
                catch (Exception)
                {
                    this.Error("Error!");
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }
And the SetPassword Action
//
        // GET: /Account/ForgotPassword
        [AllowAnonymous]
        public ActionResult SetPassword(int? userId, string code)
        {
            SetPasswordViewModel model = new SetPasswordViewModel()
            {
                UserId = userId,
                Code = code
            };

            return View(model);
        }

        //
        // POST: /Account/ForgotPassword
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> SetPassword(SetPasswordViewModel model)
        {
            if (model.UserId == null || model.Code == null)
            {
                return View("Error");
            }

            if (ModelState.IsValid)
            {
                var result = await UserManager.ConfirmEmailAsync(model.UserId.Value, model.Code);

                if (result.Succeeded)
                {
                    result = await UserManager.ChangePasswordAsync(model.UserId.Value, String.Empty, model.Password);
                    var user = await UserManager.FindByIdAsync(model.UserId.Value);

                    if (result.Succeeded)
                    {
                        AuthenticationManager.SignOut();
                        return View("ConfirmEmail");
                    }

                    AddErrors(result);
                    return View();
                }

                AddErrors(result);
                return View();
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }
Both actions are in differen controllers and areas. In Controller where I crate user I use my own user repository class and the asp.net identity UserManager. When I debug everywhere the code is correct but the "Invalid token." error is returned.

Anybody can help me to solve this problem?
May 6, 2014 at 1:29 PM
Nobody?
Oct 15, 2014 at 9:06 PM
The problem is this line
var code = await userManager.GenerateEmailConfirmationTokenAsync(user.Id);
The answer is to change it to this
var code = Url.Encode(await UserManager.GenerateEmailConfirmationTokenAsync(user.Id));