5
votes

I am currently aiming to implement a read-only role provider for an ASP.NET application based on domain security groups using the utilities in the System.DirectoryServices.AccountManagement assembly. I have the following piece of code which works fine on my development domain, but fails in the deployment environment:

Using myContext As New PrincipalContext(ContextType.Domain, Nothing, "DC=My,DC=Controller", accountName, accountPassword)
    Try
        Dim p As UserPrincipal = UserPrincipal.FindByIdentity(myContext, IdentityType.SamAccountName, userName)
        Dim groups = p.GetAuthorizationGroups()
        For Each g In groups
            Debug.WriteLine("Found security group: " & g.DisplayName & vbNewLine)
        Next
    Catch ex As Exception
        Debug.WriteLine("Encountered an exception: " & vbNewLine & ex.ToString())
    End Try
End Using

The exception stack trace returns as follows:

    System.DirectoryServices.AccountManagement.PrincipalOperationException: There is no such object on the server.
     ---> System.DirectoryServices.DirectoryServicesCOMException (0x80072030): There is no such object on the server.
       at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
       at System.DirectoryServices.DirectoryEntry.Bind()
       at System.DirectoryServices.DirectoryEntry.get_SchemaEntry()
       at System.DirectoryServices.AccountManagement.ADStoreCtx.IsContainer(DirectoryEntry de)
       at System.DirectoryServices.AccountManagement.ADStoreCtx..ctor(DirectoryEntry ctxBase, Boolean ownCtxBase, String username, String password, ContextOptions options)
       at System.DirectoryServices.AccountManagement.PrincipalContext.CreateContextFromDirectoryEntry(DirectoryEntry entry)
       at System.DirectoryServices.AccountManagement.PrincipalContext.DoLDAPDirectoryInit()
       --- End of inner exception stack trace ---
       at System.DirectoryServices.AccountManagement.PrincipalContext.DoLDAPDirectoryInit()
       at System.DirectoryServices.AccountManagement.PrincipalContext.DoDomainInit()
       at System.DirectoryServices.AccountManagement.PrincipalContext.Initialize()
       at System.DirectoryServices.AccountManagement.PrincipalContext.get_QueryCtx()
       at System.DirectoryServices.AccountManagement.Principal.FindByIdentityWithTypeHelper(PrincipalContext context, Type principalType, Nullable`1 identityType, String identityValue, DateTime refDate)
       at System.DirectoryServices.AccountManagement.Principal.FindByIdentityWithType(PrincipalContext context, Type principalType, IdentityType identityType, String identityValue)
       at System.DirectoryServices.AccountManagement.UserPrincipal.FindByIdentity(PrincipalContext context, IdentityType identityType, String identityValue)

I know the obvious "gotcha" here is to be certain the object actually, well... exists on the server. However, I can confirm without a doubt that no matter which account's SAM Account Name I use, I receive the same result from the call. Additionally, Microsoft's ActiveDirectoryMembershipProvider has no trouble authenticating against the same SAM Account Name and I am able to find the object using that information with the DirectorySearcher class. The only differences I can identify between the development network and deployment is that the deployment environment's DC is a Windows Server 2003 box, whereas locally I am developing with a Windows Server 2008 DC. What might I be overlooking?

3

3 Answers

4
votes

For some reason, the problem lay in the path to the domain controller. Describing the path as DC=box123,DC=dom did not work, but using the path box123.dom did. Can't say why, and it's not a behavior I can duplicate on the local domain, but that resolved the issue.

EDIT:
Upon further investigation, the construction DC=box123,DC=dom when pared down to DC=dom functioned correctly as well. I don't understand the dynamics of the addressing, but I was able to determine the trouble by displaying the path to a sample user using a DirectorySearcher object, which revealed the path to my user to be: LDAP://box123.dom/CN=username/CN=Users/DC=dom

2
votes

I know this is a relatively old question, but I thought our solution might help someone else down the line. We encountered the same issue in the customer's live environment. Initially we couldn't replicate the issue in our test environment, but then we discovered it only happened when accessing the site under https. Through a lot of trial and error plus a support call to Microsoft, I started playing around with the call to create the principal context. Initially, the object instantiation was coded as

using (var pc = new PrincipalContext(ContextType.Domain, <serverUri>, <ldapDomain>, <username>, <userpass>))

The full constructor can take one additional parameter

using (var pc = new PrincipalContext(ContextType.Domain, <serverUri>, <ldapDomain>, ContextOptions.Negotiate, <username>, <userpass>))

Once the ContextOption was specified (and in our case, it had to be Negotiate), the call to UserPrincipal.FindByIdentity worked as expected.

1
votes

You don't show th values of dcPath here is a way to construct PrincipalContext like this.

Using myContext As New PrincipalContext ContextType.Domain, "dom.fr:389", "dc=dom,dc=fr", "jpb", "root.123");

After that the exception can be explained by the fact that userName is not a valid samAccountName on your controler.