I'm having trouble with a user validation when the "User must change password on next log on" is set.
Here's how I validate the user:
Boolean ValidateUser(String userName, String password)
{
try
{
var userOk = new DirectoryEntry("LDAP://<my LDAP server>",
userName,
password,
AuthenticationTypes.Secure
| AuthenticationTypes.ServerBind);
return true;
}
catch (COMException ex)
{
if (ex.ErrorCode == -2147023570) // 0x8007052E -- Wrong user or password
return false;
else
throw;
}
}
When the "must change password" is set the COMException is catched as expected, however, the ErrorCode
is the same as if the password was wrong.
Does anyone know how to fix this?
I need a return code that tells that the password is correct AND that the user must change the password.
I don't want to implement Kerberos in C# just to check for a damn flag when the user must change the password.
After a long search on the Internet, some empirical work with error messages and some spelunking through Win32API, I've came up with a solution that, so far works.
Unfortunately, using an error message is not a fool-proof way to accomplish verify the reasons an account login was rejected. For this reason, it is important to understand how your LDAP environment manages user accounts. In Microsoft Active Directory, the userAccountControl field is used to handle most account statuses. Here is a list of common userAccountControl bits:
Keep in mind that these are often combined. So, for instance, if a user with a normal account (LDAP_UF_NORMAL_ACCOUNT) is also disabled (LDAP_UF_ACCOUNT_DISABLE), the LDAP field userAccountControl would be set to 514 (Because 512 + 2 = 514)
Now, to answer the original question: When a user account is set for "Password must be changed", AD simply adds LDAP_UF_PASSWORD_EXPIRED to the userAccountControl field. So: Normal Account: LDAP_UF_NORMAL_ACCOUNT + LDAP_UF_PASSWORD_EXPIRED = 8389120
For this specific instance (Password Expired), that is by far the most common value, but it isn't the only one. You need to consider all possible options when evaluating if the account is set for password expired.
Of course, this isn't the easiest way to verify settings, but it is the most reliable way.
Thank you Paulo. This works for me. Using this link I've expanded response after exception occur, something like this: