We just launched our web app 6 days ago and have had over 5000 people register for accounts, great!
The issue is 3-5% of those users who click the confirmation email link (and same seems to go for reset password) get shown the error screen presumably because they have an invalid token.
I read on StackOverflow that you need to encode the url to avoid special characters throwing it off and then decode it right before you validate it. I did that to no effect though, some users were still getting errors on their validation token.
I also read that having different MachineKey's could be a reason tokens aren't processed as being valid. Everything is hosted on Azure so I presumed (and saw on SO) it was or should taken care of
So with 30-50 people emailing us for the past 6 days now about issues, I got desperate while I tried to come up wit a solution and set my confirmEmail action to be the following:
[AllowAnonymous]publicActionResultConfirmEmail(string userId =null,string code =null){if(userId ==null|| code ==null){returnView("Error");}else{var emailCode =UserManager.GenerateEmailConfirmationToken(userId);var result =UserManager.ConfirmEmail(userId, emailCode);returnView(result.Succeeded?"ConfirmEmail":"Error");}}
I thought to myself there is no way in heck this could fail, it literally just generates a token and then immediately uses it - yet somehow it still fails (by fails I mean the user sees the error page)
My best guess as to a possible solution so far is this answer from SO (http://stackoverflow.com/questions/25405307/asp-net-identity-2-invalid-token-error, halfway down)
Every time when a UserManager is created (or new-ed), a new dataProtectionProvider is generated as well. So when a user receives the email and clicks the link the AccountController is already not the old one, neither are the _userManager and it's token provider. So the new token provider will fail because it has no that token in it's memory. Thus we need to use a single instance for the token provider.
Is that really the issue? If so, what the heck ASP.net Identity team? Why?
Some of the things I have changed:
The default Register Action recommends sending confirmation emails the following way:
var callbackUrl =Url.Action("ConfirmEmail","Account",new{ userId = user.Id, code = code }, protocol:Request.Url.Scheme);
Where I have the following in my Register Action
string callbackUrl = await SendEmailConfirmationTokenAsync(user.Id,"Confirm your XXXXXXX account");
And then I specify the following in the SendEmailConfirmationTokenAsync
private async Task<string>SendEmailConfirmationTokenAsync(string userID,string subject){string code = await UserManager.GenerateEmailConfirmationTokenAsync(userID);var callbackUrl =Url.Action("ConfirmEmail","Account",new{ userId = userID, code = code }, protocol:Request.Url.Scheme);// construct nice looking email body await UserManager.SendEmailAsync(userID, subject, htmlBody);return callbackUrl;}
To me, both sections are equivalent, is this not the case?
And then the only other thing I can think of is how I added my db class, but that shouldn't affect the UserManager should it?
The top part of my account controller looks like the following:
privateSiteClasses db =newSiteClasses();publicAccountController(){}publicAccountController(ApplicationUserManager userManager,ApplicationSignInManager signInManager ){UserManager= userManager;SignInManager= signInManager;}privateApplicationUserManager _userManager;publicApplicationUserManagerUserManager{ get{return _userManager ??HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();}privateset{ _userManager = value;}}...
We are using the recommended email provider sendgrid and I have never been able to replicate this issue (after creating ~60 test accounts manaually) and most people seem to get along fine.
Part of this could be errors resulting from the users themselves, but this seems to be happening for a bunch of non tech-savvy people who just click on the link and expect it to work like a normal confirmation email should. Most users are coming to us from their iPhone where I would presume they are just using Apple's default mail client but not positive. I don't know of any spam filter or email settings that would remove the query string values from links.
I'm getting somewhat desperate for answers as I am trying to launch a great new startup but am getting hung up by ASP.net Identity technicalities or bugs or whatever is going on.