0

I am using user the PrincipalContext class to connect to an Active Directory server and then use the ValidateCredentials method like this:

new PrincipalContext(ContextType.Domain, <some url>, <some container>);
principalContext.ValidateCredentials(userName, password, ContextOptions.Negotiate);

The some container parameter is of type Container and according to the documentation "All queries are performed under this root". Also according to this answer specifying the Container "... limits all queries using that DomainContext to the specified container."

The problem though is that against my companie's AD server if I specify a container that does not exist or just put in gibberish the AD server still finds a user if I specify a user that exists with the correct password. Does anybody know why the user is still found? Is there some documentation you can point me to that explains this?

SmokerJones
  • 323
  • 1
  • 2
  • 11

1 Answers1

0

The simple answer is that ValidateCredentials doesn't use the specified container, simply because it doesn't need to. It doesn't actually search for the user. It just attempts to authenticate to the server with the credentials specified.

You can see the source code for ValidateCredentials here, which ends up calling CredentialValidator.Validate (an internal class).

In the constructor of PrincipalContext, it creates the CredentialValidator object, but you'll notice that it does not pass the container to it, only the name (the domain name).

_credValidate = new CredentialValidator(contextType, name, _serverProperties);

The _serverProperties variable is also built from only the server name, not the container, which you can see from the ReadServerConfig method.

Gabriel Luci
  • 38,328
  • 4
  • 55
  • 84
  • If you look at the second example in this post on how to validate credentials with PowerShell using the same method ValidateCredentials, it says to enter the Domain to target the search. This means that specifying the container is taken into account.https://itpro-tips.com/2019/test-ad-authentication-via-powershell/. This uses the System.DirectoryServices.AccountManagement dll which is the same as I'm using in C# – SmokerJones Aug 23 '22 at 13:25
  • In that example, the `$Domain` variable is passed as the second variable in the constructor of `PrincipalContext`, which corresponds to the `name` parameter. That is absolutely used when calling `ValidateCredentials`, since it tells it which domain to connect to. However, the `$Server` variable is the third parameter, which corresponds to the `container` parameter, so it's misleading to call it `$Server` and it is not used at all when calling `ValidateCredentials`. I've updated my answer to show that `ValidateCredentials` doesn't use the value of `container`. – Gabriel Luci Aug 23 '22 at 13:52
  • One more question then. What about the UserPrinciple.FindByIdentity method? If you trace this method down you end up at Principal.FindByIdentityWithTypeHelper. Here the container is apparently also not used but in my testing I noticed that this method does respect the Container value if one is present. Can you please take a look and comment on this? https://github.com/angelcolmenares/pash/blob/master/External/System.DirectoryServices.AccountManagement/System/DirectoryServices.AccountManagement/Principal.cs – SmokerJones Aug 24 '22 at 06:16
  • It is used there. `FindByIdentityWithTypeHelper` calls `queryCtx.FindPrincipalByIdentRef`. `queryCtx` is `context.QueryCtx`. When `QueryCtx` is created, the container is used, which you can see starting at [line 372 of the `PrincipalContext` class](https://github.com/angelcolmenares/pash/blob/master/External/System.DirectoryServices.AccountManagement/System/DirectoryServices.AccountManagement/PrincipalContext.cs#L372). – Gabriel Luci Aug 24 '22 at 13:40