I'm seeing some odd behaviour here using PrincipalContext.ValidateCredentials
. The set-up is two Active Directory domains in parent/child setup (so we have primary domain company.com
and sub-domain development.company.com
).
When I validate credentials against the primary domain, ValidateCredentials
behaves as expected, returning true for good user/pass pairs, and false for anything else.
However if I validate a user in the sub-domain, ValidateCredentials
returns true for both good username/passwords AND invalid users. If I provide a valid user with an invalid password, it correctly returns false.
Now I'm working around it at the moment by doing UserPrincipal.FindByIdentity()
first and if the user exists, then calling ValidateCredentials
-- but I'd like to understand what's going on.
Another workaround I've looked at is by passing the username through as domain\username
as the MSDN entry for ValidateCredentials
states:
In each version of this function, the userName string can be in one of a variety of different formats. For a complete list of the acceptable types of formats, see the ADS_NAME_TYPE_ENUM documentation.
...of which this form of username is listed. But this causes ValidateCredentials
to always return true, no matter what combination of username and password I pass in.
The pertinent code is:
bool authenticated = false;
// Various options tried for ContextOptions, [etc] inc. explicit username/password to bind to AD with -- no luck.
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, domain, null, ContextOptions.Negotiate, null, null))
{
log(pc.ConnectedServer + " => " + pc.UserName + " => " + pc.Name + " => " + pc.Container);
using (var user = UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, username))
{
if (user != null)
{
log(user.DistinguishedName + "; " + user.DisplayName);
authenticated = pc.ValidateCredentials(username, password);
} else {
log("User not found");
// Debug only -- is FindByIdentity() needed. This should always return
// false, but doesn't.
authenticated = pc.ValidateCredentials(username, password);
}
}
}
return authenticated;
Any and all (sensible) suggestions welcome -- I'm scratching my head over this as it just goes against all expectations.
I ought to add: this is running as myself on my machine, both of which are members of the primary domain. However I've also tried running it in a command prompt on my machine as a user of the sub-domain (runas /user:subdomain\user cmd
) with exactly the same results.