question

ShwetaJena-8089 avatar image
0 Votes"
ShwetaJena-8089 asked cheong00 commented

PrincipalContext Fails to find a domain user from a trusted domain

Hi Guys,

I am running into an issue where PrincipalContext fails to find the identity of an user from a trusted domain.

I have two domains which has 1 way trust between them , lets say ABC.XYZ.net and XYZ.net.



Setup:

We have an apache service running as Network Service. This apache service uses PrincipalConext to find an user in the domain. The user can be from ABC.XYZ.net or XYZ.net. When the machine on which the service runs is connected to ABC.XYZ.net, UserPrincipal.FindByIdentity is able to find the user from the same domain, but fails to find an user from XYZ.net domain. Please Note- there is trust established between two domains, where an user from XYZ.net is bale to login to machine in ABC.XYZ.net



We have tried the below constructors of PrincipalContext but nothing worked.

PrincipalContext context = new PrincipalContext(ContextType.Domain);

PrincipalContext context = new PrincipalContext(ContextType.Domain, "XYZ.net");



We don't have a way to use any user credential to use ValidateCredential api. The intention is to check if the given username is present in any of the two domains.

dotnet-csharp
· 5
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@ShwetaJena-8089
Could you please tell us in which domain the code runs?
Will using other projects such as console projects instead of apache service affect the results?

0 Votes 0 ·

The domain is corporate network domains.

I tested a parent and child domain setup where by default two way trust is being established. It worked successfully.
But, when I have two domains which have one way trust established, this fails.

0 Votes 0 ·

The domain is corporate network domains.

I tested a parent and child domain setup where by default two way trust is being established. It worked successfully.
But, when I have two domains which have one way trust established, this fails.

0 Votes 0 ·

@ShwetaJena-8089
Does the apache service you mentioned run in these two domains? Or is it running on other machines outside these two domains?
If it’s the latter, maybe you can see if this helps:
How to list users in all domains running code from a non-domain computer?

0 Votes 0 ·

Apache service runs one of these two domains.

For example -

my machine is on domain1 and has my apache server running on that machine.
Now, on my machine I am trying to authenticate an user from domain2. domain1 and domain2 are two separate domains and they have trust in between.
( A user from domain2 can login to domain1 machine)

Now, in this scenario, PrincipalContext fails with an exception saying "a referral is returned"
I can not pass any credential to PrincipalContext constructor in my current setup.

0 Votes 0 ·
TimonYang-MSFT avatar image
0 Votes"
TimonYang-MSFT answered

Try if these codes work for you:

             using (var context = new PrincipalContext(ContextType.Domain,"domain", "CN=Users,DC=xyz,DC=net"))
             {
                 using (var searcher = new PrincipalSearcher(new UserPrincipal(context)))
                 {
                     foreach (var result in searcher.FindAll())
                     {
                         DirectoryEntry de = result.GetUnderlyingObject() as DirectoryEntry;
                         Console.WriteLine("First Name: " + de.Properties["Name"].Value);
                         Console.WriteLine("path: "+de.Path);
                         Console.WriteLine();
                     }
                 }
             }

If the response is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

cheong00 avatar image
0 Votes"
cheong00 answered cheong00 commented

I just wrote something similar last week. See if it works for you:

         const string ldapBase = "LDAP://pdc.xyz.net:389/";
         public static DC[] GetDomains()
         {
             List<DC> domainList = new List<DC>();
    
             DirectoryEntry configRoot = new DirectoryEntry(ldapBase + "CN=Configuration,DC=xyz,DC=net", LDAPUser, LDAPPassword);
    
             using (DirectorySearcher adsearcher = new DirectorySearcher(configRoot))
             {
                 adsearcher.Filter = "(&(objectClass=crossRef)(nETBIOSName=*))";
                 adsearcher.SearchScope = SearchScope.Subtree;
                 adsearcher.PropertiesToLoad.Add("name");
                 adsearcher.PropertiesToLoad.Add("dnsRoot");
    
                 DC dc = null;
                 SearchResultCollection resultList = adsearcher.FindAll();
                 foreach (SearchResult searchResult in resultList)
                 {
                     dc = new DC()
                     {
                         Name = searchResult.Properties["name"].Count > 0 ? (string)searchResult.Properties["name"][0] : String.Empty,
                         DNSRoot = searchResult.Properties["dnsRoot"].Count > 0 ? ((string)searchResult.Properties["dnsRoot"][0]).ToUpper() : String.Empty,
                         Inactive = false,
                         IsDown = false,
                     };
                     if (includeDomains.Contains(dc.Name))
                     {
                         domainList.Add(dc);
                     }
                 }
             }
             return domainList.ToArray();
         }

pdc.xyz.net can be found by running "set" command in ""command prompt" and find the "LOGONSERVER" environment variable, then add ".xyz.net" after that.

includeDomains is string array contains the Win2k style domain prefix to include. If you want to search all domains then you can omit that part.

Now you get the root for all the trusted DCs in your domain, and you can loop your PrincipalContext(dc.DNSRoot) against them to find the user. (I keep use DirectoryContext+ DirectorySearcher though)

As you can see, I also have code to handle Inactive domains (domains that once trusted, but permanently shutdown because of organization restructuring) or down (VPN lost or etc.). You can skip them if it's irrelevant to you, or to create test yourself.

· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Forgot to add that this is based on the fact that all DNS in the domain do stay with the domain controller, so the hostname for DNSRoot will be the same as the domain controller for that foreign domain.

For generic use you may want to add query for the actual server location.


0 Votes 0 ·