Search code examples
asp.netasp.net-identity-2

Email token expired and "Email already taken" issue - Asp.net Identity 2.0 API


I'm facing a strange issue in Asp.Net Identity API 2.0.

When an user signs up, I send a confirmation email to the user, and if the user confirms his / her account within 3 hours of signing up, the "ConfirmEmailAsync" method seems to be working.

But after 3 hours, if I try to confirm the email address, I'm getting a "Invalid Token" error.

Then if the user tries to register again he gets a "Email/Name is already taken" error.

How can I solve that case that the user is getting "locked", he can't log in and he also can't register from scratch.

Can anyone help please?


Solution

  • There are various places where you can do this.Say you are doing something like below to register the user

    var user = new ApplicationUser { UserName = model.RegisterEmail.ToLower(), Email = model.RegisterEmail.ToLower(), PhoneNumber = model.RegisterPhoneNumber, EmailConfirmed = true, PhoneNumberConfirmed = true };
    var addUserResult = await UserManager.CreateAsync(user, model.RegisterPassword);
    
    
    if (!addUserResult.Succeeded)
    {
        ApplicationUser user = await UserManager.FindByEmailAsync(model.RegisterEmail.ToLower());
        if(!user.EmailConfirmed)
        {
           var code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
           //Send the new link
           //return the error message accordingly.
        }       
    }
    

    You can do samething during Login

    ApplicationUser user = await UserManager.FindAsync(model.UserName.ToLower(), model.Password);   
    if(user != null && !user.EmailConfirmed)
    {
           var code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
        //Send the new link
        //return the error message accordingly.
    }
    

    Or if you are using SigninManager (this is from default MVC template)

    var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
    switch (result)
    {
        case SignInStatus.Success:
            return RedirectToLocal(returnUrl);
        case SignInStatus.LockedOut:
            return View("Lockout");
        case SignInStatus.RequiresVerification:
            //redirecting to a different page
            return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
        case SignInStatus.Failure:
        default:
            ModelState.AddModelError("", "Invalid login attempt.");
            return View(model);
    }
    

    Hope this helps.