I'm validating user logins using python's ldap module. When the login fails, I get a ldap.INVALID_CREDENTIALS login, but this can be either because of a wrong password or because the account is locked. The account get's locked after the 3rd try.
I would like to detect that the account is locked and report that to the frustrated user, instead of the same "invalid login" message.
Searching for a solution I found:
- The userAccountControl LOCKED flag is not used by AD;
- The lockoutTime attribute should be used instead
The LDAP query I should be using to find locked users is:
(&(objectClass=user)(lockoutTime>=1))
Or for a specific user:
(&(objectClass=user)(sAMAccountName=jabberwocky)(lockoutTime>=1))
But this is not working, the query returns no results every time.
In addition, I found that lockoutTime is not guaranteed for all users in AD (at least in our configuration), but will be created upon reaching the number of failed lockout attempts. So in checking for locked accounts, checking for None or an equivalent will be required as well.
(&(objectClass=user)(&(lockoutTime=*)(!(lockoutTime=0))))
Will return objects which are users and have a present attribute named lockoutTime which isn't equal to 0.
use this query to get the best results,
Get-ADUser -LDAPFilter "(&(objectCategory=Person)(objectClass=User)(lockoutTime>=1))" -Properties LockedOut
I found also this list of property flags: How to use the UserAccountControl flags
You must make a binary-AND of property
userAccountControl
with0x002
. In order to get all locked (i.e. disabled) accounts you can useFor operator
1.2.840.113556.1.4.803
see LDAP Matching RulesA value of zero in
lockoutTime
means it's not locked out. So, you should try this.Actually, the above query is still not 100% correct. If you read the fine print from MSDN, Microsoft is suggesting you to add the
Lockout-Time
attribute to theLockout-Duration
attribute and then compare it with the current time. That's because there is such a thing called lockout duration. Once the lockout duration passes, the user is unlocked automatically. Zero inLockout-Duration
means the account is locked forever until the administrator unlock it.See this MSDN article
lockoutTime
is a<not set>
attribute so the easiest way is to use:for the non-empty entries.
Update:
However, this value is also set when the password expires, password needs to change etc.
So it needs to be filtered by:
to get the cases where the user is locked out because they violated the password policy e.g incorrectly entered the password 5 times.