Search code examples
c#asp.net-mvcasp.net-identitylockout

MVC 5 Identity 2.0 lockout doesn't work


I need to block a user permanently. I don't understand why this code is not working.

This line UserManager.IsLockedOut(user.Id); always returns false instead of true.

Maybe it's necessary to put this line UserManager.UserLockoutEnabledByDefault = true; in user registration stage?

using (var _db = new ApplicationDbContext())
{
    UserStore<DALApplicationUser> UserStore = new UserStore<DALApplicationUser>(_db);
    UserManager<DALApplicationUser> UserManager = new UserManager<DALApplicationUser>(UserStore);
    UserManager.UserLockoutEnabledByDefault = true;
    DALApplicationUser user = _userService.GetUserByProfileId(id);
    bool a = UserManager.IsLockedOut(user.Id);
    UserManager.SetLockoutEnabled(user.Id, true);

    a = UserManager.IsLockedOut(user.Id);
    _db.SaveChanges();
}

Solution

  • The line

    UserManager.SetLockoutEnabled(user.Id, true);
    

    is not locking or unlocking the account. This method is used to permanently enable or disable the locking out process for the given user account. As it stands, you are making a call that is basically setting this user account up to be bound by the rules of account locking. Making a call with the second parameter as false ie:

    UserManager.SetLockoutEnabled(user.Id, false);
    

    would allow you to setup a user account that is exempt from the rules of locking - this may be useful for an admin account.

    Here is the code for UserManager.IsLockedOutAsync:

    /// <summary>
    ///     Returns true if the user is locked out
    /// </summary>
    /// <param name="userId"></param>
    /// <returns></returns>
    public virtual async Task<bool> IsLockedOutAsync(TKey userId)
    {
        ThrowIfDisposed();
        var store = GetUserLockoutStore();
        var user = await FindByIdAsync(userId).WithCurrentCulture();
        if (user == null)
        {
            throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound,
                userId));
        }
        if (!await store.GetLockoutEnabledAsync(user).WithCurrentCulture())
        {
            return false;
        }
        var lockoutTime = await store.GetLockoutEndDateAsync(user).WithCurrentCulture();
        return lockoutTime >= DateTimeOffset.UtcNow;
    }
    

    As you can see, for a user to be classed as locked out, the lockout must be enabled as above and the user must have a LockoutEndDateUtc value that is greater than or equal to the current date.

    So, to "permanently" lock an account, you could do the following:

    using (var _db = new ApplicationDbContext())
    {
        UserStore<DALApplicationUser> UserStore = new UserStore<DALApplicationUser>(_db);
        UserManager<DALApplicationUser> UserManager = new UserManager<DALApplicationUser>(UserStore);
        UserManager.UserLockoutEnabledByDefault = true;
        DALApplicationUser user = _userService.GetUserByProfileId(id);
    
        bool a = UserManager.IsLockedOut(user.Id);
    
        //user.LockoutEndDateUtc = DateTime.MaxValue; //.NET 4.5+
        user.LockoutEndDateUtc = new DateTime(9999, 12, 30);
        _db.SaveChanges();
    
        a = UserManager.IsLockedOut(user.Id);
    }