I’ve spent a few hours trying to figure out why my code does not work, and I have not found any explanations to the issue, so might just write it down here.

In ASP.NET Identity there is a concept for user locking out. You can specify how many attempts user can gets before the lock-out kicks in and for how long the lockout is enabled. This is a widely known, from all the articles online. But what these articles don’t say is that users can be opted-in and opted-out from this process.

If you look on IdentityUser class, there are 2 fields that relate to lockout: LockoutEnabled and LockoutEndDateUtc. My first reaction was that LockoutEnabled says that user is locked-out and LockoutEndDateUtc is time when the lockout expires.

Turned out that I was wrong. LockoutEnabled is a flag saying that user can (or can not) be locked in principle. I.e. opt-in flag for locking. So if we have an admin user who we don’t want to lockout ever, we’ll set this flag to be false. And for the rest of user-base this should be set to true.

To check if user is locked-out use UserManager.IsLockedOutAsync(user.Id). Function UserManager.GetLockoutEnabledAsync() checks if user is opted in for lock-out, it does not check if user is actually locked-out.

And fields on IdentityUser – don’t use them to detect is user is locked out, they are lies! Use UserManager functions to detect user state.

Hope this will save some people a head-banging, cause that caused me some stress!

Update 27 Aug 2014

To enable locking-out UserManager should have these flags set:

//lockout users for 10 minutes
UserManager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(10);

// takes 6 incorrect attempts to lockout 
this.MaxFailedAccessAttemptsBeforeLockout = 6;

// when new user is created, they will be "lockable". 
this.UserLockoutEnabledByDefault = true;

To lockout user you can do this:

user.LockoutEnabled = true;
user.LockoutEndDateUtc = DateTime.UtcNow.AddMinutes(42);
await userManager.UpdateAsync(user);

This will set the user to be locked out for 42 minutes from now. However, this is not recommended way to lock-out user, this is what the framework does in the background. There are ways users can lock themselves out.

If you are updated to AspNet Identity 2.1 (which has been released recently). You should use SignInManager:

var signInManager = new SignInManager(userManager, authenticationManager);
var signInStatus = await signInManager.PasswordSignInAsync(username, password, isPersistent, shouldLockout);

If shouldLockout is true, user is getting locked out after a number of failed attempts to login.

PasswordSignInAsync method does the following steps:

  • checks if user with given username exists;
  • then checks if this user is not locked out;
  • if password is correct, redirects logic to 2FA (if it is enabled);
  • if shouldLockout is true, then on incorrect password increases number of failed log-ins on user record.

If you have not updated and still using Identity v2.0 do the following. On every failed attempt to login, call the following

await userManager.AccessFailedAsync(user.Id); 

IdentityUser class have property AccessFailedCount. The method above increases count on this property. If count is greater than UserManager.MaxFailedAccessAttemptsBeforeLockout, then user is getting locked out: user.LockoutEndDateUtc is set to a date in the future and resets AccessFailedCount to zero.

When user is signed-in successfully, you need to reset AccessFailedCount to zero. Do it by calling:

await userManager.ResetAccessFailedCountAsync(user.Id);
  • PCERoman

    Thank you for the insight! I have just spent (wasted???) several hours looking for exactly the same description.

  • rb

    So then how do you lockout a user?

  • Marselus Chia

    Good info here, thanks.
    I have tried on my local test site which is updated recently with the latest identity 2.1.0.
    If a user is not lockout enabled, even if we have set the last parameter in the signinmanager to true. Lockout is still not applied to this user.

    • well, if a `LockoutEnabled` for user is set to false, then the user is never locked-out.

  • Good article and very helpful. The lockouts are working for me, but for some reason, once I get the lockouts done, I can manually go to a page that requires authentication and it acts as if I’m logged in.
    Any ideas on that one?

    • Mm.. need to see your code. By default Identity does not check if user is locked-out or not, so you need to do that yourself. And if you don’t do the checking, the code from standard template will just authenticate the user, as if there is no lock-out.

  • Ajaxian Krasic

    Thank you bro! You saved my day from waste a lot of time implementing something useless. Then I’ll implement my own user-disabled flag to handle user locking

  • Er Ashutosh Kushawaha

    await UserManager.GetAccessFailedCountAsync(user.Id) is not working,

    please suggest me why not working.

    • please expand “not working”. Does it throw an exception? does it return a value you don’t expect?

    • Suresh Kaushik

      May be your method that is invoking this statement is not async.

  • Nicholas Mitchell

    Thanks brother. Good info, especially about SignInManager. Cheers!

  • Dov Miller

    Thank you! Very helpful! 1. Where is the code enabling lock out to be put? 2. What is 2FA?

    • Place your logic for lock-out in the same place where you log users in.
      2FA = 2-Factor-Authorisation

      • Dov Miller

        Thank you for your response. I meant this “To enable locking-out UserManager should have these flags set:”. Where should those flags be set?

        • `UserManager` or `ApplicationUserManager` class. Or whatever that is called in your project. These fields are part of that class.

  • Burak TARHANLI

    Thank you so much, this was helped to me.