Active Directory Services: PrincipalContext -- What is the DN of a "container" object?
Asked Answered
T

2

20

I'm currently trying to authenticate via Active Directory Services using the PrincipalContext class. I would like to have my application authenticate to the Domain using Sealed and SSL contexts. In order to do this, I have to use the following constructor of PrincipalContext (link to MSDN page):

public PrincipalContext(
    ContextType contextType,
    string name,
    string container,
    ContextOptions options
)

Specifically, I'm using the constructor as so:

PrincipalContext domainContext = new PrincipalContext(
    ContextType.Domain, 
    domain, 
    container, 
    ContextOptions.Sealing | ContextOptions.SecureSocketLayer);

MSDN says about "container":

The container on the store to use as the root of the context. All queries are performed under this root, and all inserts are performed into this container. For Domain and ApplicationDirectory context types, this parameter is the distinguished name (DN) of a container object.

What is the DN of a container object? How do I find out what my container object is? Can I query the Active Directory (or LDAP) server for this?

Toluene answered 29/3, 2010 at 13:10 Comment(0)
T
32

Well, I managed to figure out the issue:

PrincipalContext domainContext = new PrincipalContext(ContextType.Domain,domain);

domainContext.ValidateCredentials(userName, password, 
    ContextOptions.Negotiate | ContextOptions.SecureSocketLayer);

By specifying the ContextOptions in the ValidateCredentials method (instead of in the constructor), this allowed me to avoid having to specify a DN for a container object.

UPDATE:

Although I should clarify that after further experimentation, I found that any queries derived from this PrincipalContext object takes place UN-encrypted.

Apparently, when the ContextOptions are set in ValidateCredentials, those options are only used for that specific call of ValidateCredentials. But here's where it gets strange...

So, I wanted to have my queries to the AD server take place encrypted as well. Example query:

UserPrincipal p = UserPrincipal.FindByIdentity(
    domainContext, IdentityType.SamAccountName, userName);
var groups = p.GetGroups();
foreach (GroupPrincipal g in groups) { /* do something */ }

The above code gets a list of all the Groups that the user belongs to, but it happens in the clear (unencrypted). So after much fiddling, I discovered that the DN never needs to be set.

PrincipalContext domainContext = new PrincipalContext(ContextType.Domain,domain,
    null,ContextOptions.Negotiate | ContextOptions.SecureSocketLayer);

I found that I could set the container object (DN) to null. And this works fine. Setting it to an empty string ("") results in an exception of some unknown type, so don't think you can give it an empty string.

And here's the weird part. You'd think that setting the SecureSocketLayer option in the PrincipalContext would mean that you don't have to explicitly set it when you use VerifyCredentials. But I found that if I didn't set it in the VerifyCredentials part, the authentication would fail, but the queries (like in the example to the Groups) still takes place encrypted.

Maybe I just don't fully understand AD authentication and queries yet, but that seems like odd behavior to me.

Toluene answered 29/3, 2010 at 18:41 Comment(4)
Your explanation for "the weird part" was the key to fixing a 20 second delay calling ValidateCredentials. Thanks!Northwest
I know this is super old but I am researching whether or not to use SSL over Signing and came across this post. I believe you could use null in the constructor. That's how I do it when I want to specify ContextOptions. Example: var pc = new PrincipalContext(ContextType.Domain, Environment.UserDomainName, null, ContextOptions.Sealing);Lunge
@nameless: I think that's what the code shows in the last code block. (FWIW, I barely remember what this was about, but remember being really happy when I figured it out.) :)Toluene
@Toluene Ahhhhhh. Good to hear and thanks for pointing that failure of mine to completely read through the entire answer, lol. I had stopped reading when I got to the part of your answer that reads By specifying the ContextOptions in the ValidateCredentialsLunge
V
0

The container can be set to the DC part of the domain.

corp.contoso.com => var container = "DC=corp, DC=contoso, DC=com"

Vindication answered 2/3, 2020 at 9:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.