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?
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