Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AspNet.Identit 2.1.0 ConfirmEmailAsync always returns Invalid token

I am trying to ConfirmEmail but each time I get a Invalid token! I am calling the API from a angulaJS app http://www.codeproject.com/Articles/784106/AngularJS-Token-Authentication-using-ASP-NET-Web-A

 // GET: /Account/ConfirmEmail
    [System.Web.Http.HttpGet]
    [System.Web.Http.AllowAnonymous]
    [System.Web.Http.Route("ConfirmEmail")]
    public async Task<IHttpActionResult> ConfirmEmail(string userId, string code)
    {
        var newcode = HttpContext.Current.Server.UrlDecode(code);

        if (userId == null || code == null)
        {
            return BadRequest(ModelState);
        }
        var result = await UserManager.ConfirmEmailAsync(userId, newcode);
        if (result.Succeeded) {
            return Ok(result.Succeeded);
        }
        return GetErrorResult(result);
    }

I ask for a Token in 2 places

1 in Account/Register var result = await UserManager.CreateAsync(user, model.Password);

        if (result.Succeeded)
        {
         //   await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);

            // For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=320771
            // Send an email with this link

            string callbackUrl = await SendEmailConfirmationTokenAsync(user.Id, "Confirm your account");


            return Ok(result.Succeeded);
        }
            return GetErrorResult(result);
        }

and the other in ResendEmail.

        [System.Web.Http.HttpGet]
    [System.Web.Http.Route("ResendEmail")]
    public async Task<IHttpActionResult> ResendEmail(string email)
    {
        if (ModelState.IsValid)
        {
            var user = await UserManager.FindByNameAsync(ActiveMember.Email);

            if (user.Email == email)
            {

                var callbackUrl = await SendEmailConfirmationTokenAsync(user.Id, "Confirm your Email");

            }
            return Ok();
        }
        // If we got this far, something failed, redisplay form
        return BadRequest(ModelState);
    }

SendEmailConfirmationTokenAsync Helper

        private async Task<string> SendEmailConfirmationTokenAsync(string userId, string subject)
    {
        string host = Request.RequestUri.Host.ToLower();

        string code = await UserManager.GenerateEmailConfirmationTokenAsync(userId);
        string callbackUrl = host + "/#/account/ConfirmEmail?userId=" + userId + "&code=" + HttpContext.Current.Server.UrlEncode(code);
        await UserManager.SendEmailAsync(userId, subject, "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a><p>" + userId + "<p>" + code + "<p>" + callbackUrl);


        return callbackUrl;
    }

And the IdentityCinfig just has

var dataProtectionProvider = options.DataProtectionProvider;
        if (dataProtectionProvider != null)
        {
            manager.UserTokenProvider =
                new DataProtectorTokenProvider<Member>(dataProtectionProvider.Create("Identity"));
           // manager.UserTokenProvider = new EmailTokenProvider<Member, string>();
        }

Is this something that I going wrong?

Thanks for your help.

like image 914
nafnaf1000 Avatar asked Feb 26 '15 18:02

nafnaf1000


1 Answers

I needed to encode the url and HttpUtilitu.UrlEncode wasn't effective, it replaced the character + with space which caused the token to be invalid.

I have two helper methods

public static string Base64ForUrlEncode(string str)
{
    var encbuff = Encoding.UTF8.GetBytes(str);
    return HttpServerUtility.UrlTokenEncode(encbuff);
}

public static string Base64ForUrlDecode(string str)
{
   var decbuff = HttpServerUtility.UrlTokenDecode(str);
   return decbuff != null ? Encoding.UTF8.GetString(decbuff) : null;
}

usage

Register action

var code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
            var callbackUrl = string.Format("{0}/#confirm-email?userId={1}&code={2}", "your-web-url", user.Id.ToString(), StringHelper.Base64ForUrlEncode(code));

and the ConfirmEmail action

var result = await UserManager.ConfirmEmailAsync(userId.ConvertToGuid(), StringHelper.Base64ForUrlDecode(code));
like image 138
Labi Avatar answered Oct 15 '22 09:10

Labi