There are already a few questions which ask how to validate Active Directory domain questions. However, I do not believe they deal adequately with multi-domain scenarios across the forest. For starters, they both suggest that the most definitive way to perform AD authentication in C# with .NET 3.5+ should look something like this:
bool isValid = false;
using(var ctx = new PrincipalContext(ContextType.Domain, "foo.com"))
{
// verify user exists first
var lookedUp = UserPrincipal.FindByIdentity(ctx, "myuser");
if (lookedUp != null)
{
// validate credentials
isValid = pc.ValidateCredentials("myuser", "mypassword");
}
}
This is all well and good when the user you want to authenticate belongs to foo.com. However, there are some subtle unexpected differences in the case of a user belonging to a child domain, whose password is also expired. (I have successfully got the PrincipalContext
to find the user in the child domain two different ways: (a) setting the domain argument to "foo.com:3268"
; (b) adding a container argument w/ the base DN of the child domain: new PrincipalContext(ContextType.Domain, "foo.com", "dc=child,dc=foo,dc=com")
. The problem I describe below occurs in both scenarios.)
If the user belongs to foo.com, and has an expired password, ValidateCredentials
returns true
(at least on Windows 7 where I'm testing; I've seen others say the behavior is different in Windows 2003). However, if the user belongs to child.foo.com and the password is expired, then ValidateCredentials
returns false
.
It is pretty important for me to be able to distinguish between "valid password but expired" and "invalid password". If the entered password is correct but expired, then I want to be able to redirect them to a "change password" screen. However, if the password they entered was totally wrong, then it could be considered leakage of information to forward them to a change password screen.
The only way forward I see is to use the LDAP interface to AD and try to parse the status messages it sends back to figure out the underlying error code. This sounds neither fun nor wise.
Can anyone provide a reason for this behavior when dealing with subdomains within the same forest? Can anyone provide a solution to what I am trying to accomplish here?