问题
I am trying to confirm email from my users and it always works locally on development environment but it always fails in hosted server. I cannot RDP to this server and this is third-party server where I have subscribed. It gives "Invalid Token" error everytime. Nothing else.
Is there any workaround for this ? Please advise.
Thanks Adam
This is how the code is generated and encoded.
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var newcode = HttpUtility.UrlEncode(code);
This is how the code is decoded and checked in 'ConfirmEmail' action.
var newcode = HttpUtility.UrlDecode(code);
var result = await _userManager.ConfirmEmailAsync(user, newcode);
This is the full code that generates the Token.
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
try
{
if (ModelState.IsValid)
{
string defaultUserRole = "UnAssigned";
// Send an email with this link
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
if (_roleManager != null)
{
var rolesAdded = await AddRoles();
if (rolesAdded == false)
{
throw new Exception("Unable to add user roles in database.");
}
var resultAddRole = await _userManager.AddToRoleAsync(user, defaultUserRole);
if (resultAddRole.Succeeded == false)
{
throw new Exception("Unable to add user to UnAssigned Role.");
}
}
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var newcode = HttpUtility.UrlEncode(code);
var callbackUrl = Url.Action(nameof(ConfirmEmail), "Account", new { userId = user.Id, code = newcode }, protocol: HttpContext.Request.Scheme);
await _emailSender.SendEmailAsync(model.Email, "Confirm your account", $"Please confirm your account by clicking this link: <a href='{callbackUrl}'>link</a>");
_logger.LogInformation("Email sent.");
UserInfoViewModel uiVM = new UserInfoViewModel(user.UserName, user.Email, defaultUserRole);
return RedirectToAction(nameof(AccountController.ConfirmRegistration), "Account", uiVM);
}
else
{
if (result.Errors.ToList().Count > 0)
{
string errorInfo = result.Errors.ToList()[0].Code + " : " + result.Errors.ToList()[0].Description;
return RedirectToAction(nameof(HomeController.Error), "Home", new { errorMessage = "Result Errors : " + errorInfo });
}
else
{
return RedirectToAction(nameof(HomeController.Error), "Home", new { errorMessage = "Unknown error. Please contat system admin." });
}
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
catch (Exception ex)
{
return RedirectToAction(nameof(HomeController.Error), "Home", new { errorMessage = "Final Exception : "+ ex.ToString() });
}
}
This is the full code that validates the token. This is the default scaffolding from Visual Studio 2017.
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> ConfirmEmail(string userId, string code)
{
try
{
if (userId == null || code == null)
{
return RedirectToAction(nameof(AccountController.AppsArkLogin), "Account");
}
if (_userManager == null)
{
throw new Exception("User manager is null.");
}
var user = await _userManager.FindByIdAsync(userId);
if (user == null)
{
throw new ApplicationException($"Unable to load user with ID '{userId}'.");
}
var newcode = HttpUtility.UrlDecode(code);
var result = await _userManager.ConfirmEmailAsync(user, newcode);
if (result == null)
{
return RedirectToAction(nameof(HomeController.Error), "Home", new { errorMessage = "ConfirmEmailAsync result is null." });
}
if (result.Succeeded)
{
//return RedirectToAction(nameof(HomeController.Error), "Home", new { errorMessage = "This is working." });
return View("ConfirmEmail");
}
else
{
if (result.Errors.ToList().Count > 0)
{
string errorInfo = result.Errors.ToList()[0].Code + " : " + result.Errors.ToList()[0].Description;
return RedirectToAction(nameof(HomeController.Error), "Home", new { errorMessage = errorInfo });
}
else
{
throw new Exception("Unknown error. Please contact system admin.");
}
}
}
catch (Exception ex)
{
return RedirectToAction(nameof(HomeController.Error), "Home", new { errorMessage = ex.ToString() });
}
}
来源:https://stackoverflow.com/questions/50283074/asp-net-core-2-0-asp-net-identity-invalid-token-error