title: Login validation asp.net mvc identity 2.0 with 3 login attempts before lockout
body: <p>Not sure how best to post this, but it is to <strong>save anyone else</strong> from hours of searching trying to set up login validation using asp.net mvc identity 2.0</p>
  
  <p>The code below works, but if anyone else can improve on it please do so and save others from hours of searching.</p>
  
  <pre><code>[HttpPost]
          [AllowAnonymous]
          [ValidateAntiForgeryToken]
          public async Task&lt;ActionResult&gt; Login(LoginViewModel model, string returnUrl)
          {
              if (ModelState.IsValid)
              {
  
                  //*******************************************************
                  // Check if email exists, if not no point in continuing
                  //*******************************************************
                  var user = await UserManager.FindByEmailAsync(model.Email);
  
                  if (user != null)
                  {
                      // var checkIfUsernamePasswordValid = await UserManager.FindAsync(model.Email,model.Password);
  
                      //*******************************************************
                      // As password is hashed, need to use line below to return success
                      //*******************************************************
  
                      var checkIfUsernamePasswordValid = UserManager.PasswordHasher.VerifyHashedPassword(user.PasswordHash, model.Password);
  
                      //*******************************************************
                      //To stop user from login in before email is confirmed, use line below
                      //*******************************************************
  
                      var emailIsConfirmed = await UserManager.IsEmailConfirmedAsync(user.Id);
                      if (!emailIsConfirmed)
                      {
                          ModelState.AddModelError("", string.Format("Please check your email inbox and verify email address before trying to login"));
                          return View();
                      }
  
                      //*******************************************************
                      // Check if user is locked out due to invalid login attempts,
                      // If they are inform them
                      //*******************************************************
  
                      if (await UserManager.IsLockedOutAsync(user.Id))
                      {
                          ModelState.AddModelError("", string.Format("Your account has been locked out for {0} minutes due to {1} invalid login attempts.", ConfigurationManager.AppSettings["DefaultAccountLockoutTimeSpan"], ConfigurationManager.AppSettings["MaxFailedAccessAttemptsBeforeLockout"]));
                      }
  
                       //*******************************************************
                       // Count number of failed login attempts and display to user
                       // Before locking them out
                       //*******************************************************
  
                      else if (await UserManager.GetLockoutEnabledAsync(user.Id) &amp;&amp; Convert.ToBoolean(checkIfUsernamePasswordValid) != true)
                      {
                          await UserManager.AccessFailedAsync(user.Id);
  
                          string message;
  
                          if (await UserManager.IsLockedOutAsync(user.Id))
                          {
                              message = string.Format("Your account has been locked out for {0} minutes due to {1} invalid login attempts.", ConfigurationManager.AppSettings["DefaultAccountLockoutTimeSpan"], ConfigurationManager.AppSettings["MaxFailedAccessAttemptsBeforeLockout"]);
                          }
                          else
                          {
                              int accessFailedCount = await UserManager.GetAccessFailedCountAsync(user.Id);
  
                              int attemptsLeft = Convert.ToInt32(ConfigurationManager.AppSettings["MaxFailedAccessAttemptsBeforeLockout"]) - accessFailedCount;
  
                              message = string.Format("Invalid email/password. You have {0} more attempt(s) before your account is locked out for {1} minutes.", attemptsLeft, ConfigurationManager.AppSettings["DefaultAccountLockoutTimeSpan"]);
  
                          }
  
                          ModelState.AddModelError("", message);
                      }
                      else
                      {
                          await SignInAsync(user, model.RememberMe);
  
                          // If user get login correct before lock out reset failed count
                          await UserManager.ResetAccessFailedCountAsync(user.Id);
  
                          return RedirectToLocal(returnUrl);
                      }
                  }
                  else
                  {
                      ModelState.AddModelError("", string.Format("Sorry we cannot find your email address."));
                      return View();
                  }
              }
              return View(model);
          }
  </code></pre>
  
  <p>On final last step, in the <code>public async Task&lt;ActionResult&gt; Register(RegisterViewModel model)</code> </p>
  
  <p>its automatically logs the user in, if you want to prevent that, comment out the following line.</p>
  
  <pre><code>await SignInAsync(user, isPersistent: false);
  </code></pre>