TokenGroup Attribute - help RRS feed

  • Question

  • User-1343033763 posted

    I am using the tokenGroups attribute on a user object to determine the users group memberships.  I am using tokenGroups instead of memberof because I need to see nested memberships as well.  I was successfully returning the groups for users on my local development machine (ASP.NET), and when I deployed to our staging web server, the application did not work as expected.  The application would retreive the tokenGroups attribute without error, however, the count of the property array was 0, indicating that no values were being returned.  Then suddenly one day the application just started work on the staging server.  I'm not sure what changed but it wasn't my code.  Now, just as suddenly as it started working, the application does not work in either my local development environment or my staging environment.  The application does not error out, it simply returns nothing in the attribute being requested.  I have the following setting in my web.config:

     <identity impersonate="true" userName="domain\user" password="password" />

    And I am binding to active directory using the following:

    _ADRoots = New DirectoryEntry(ADPath, ADUser, ADPassword, AuthenticationTypes.Secure)

    where my ADUser is set to the userPrincipalName of the user I am using for impersonation.  Does anyone have any ideas on what could be going wrong here?

    Tuesday, April 18, 2006 9:57 AM

All replies

  • User1354132231 posted
    Not sure why one would work and the other would not if you are using explicit credentials.  Are some of these groups in another trusted domain? 

    As an observation, you are probably making your life more difficult with the way you have your impersonation setup.

    If you are using Windows 2003, the easiest way by far to get this to work is to create an Application Pool, then put a domain identity on it (usually a service account).  This is done through the MMC - associate your web app with the new application pool.  The service account should be added to the IIS_WPG as well.

    Next, remove all the <identity> tags in your web.config and allow the unmanaged identity to be controlled by the application pool.  Finally use the default constructor in your code everywhere :

    new DirectoryEntry(path, null, null, AuthenticationTypes.Secure)

    You don't need to worry about hard coded credentials now and it is a snap to change identities by changing the app pool.
    Tuesday, April 18, 2006 10:12 AM
  • User-1343033763 posted

    That is great advice on using the application pool and setting the domain credentials using that.  I will change the app to do that for sure.

    I agree that it is odd that the code would work in one environment and not another.  Are special permissions needed to access the tokenGroups attribute or is that a setting that is specific to our Active Directory instance?

    Tuesday, April 18, 2006 12:59 PM
  • User1354132231 posted
    AFAIK, there are no special authorization demands on the attribute.  Of course, if you forget to use the RefreshCache technique to get the attribute, it will always look like it is missing...

    DirectoryEntry user = new DirectoryEntry("LDAP://CN=SomeUser...", null, null, AuthenticationTypes.Secure);

    //Build our SID collection
    IdentityReferenceCollection irc = new IdentityReferenceCollection();
    using (user)
        user.RefreshCache(new string[]{"tokenGroups"});
        foreach (byte[] sidBytes in user.Properties["tokenGroups"])
           irc.Add(new SecurityIdentifier(sidBytes, 0));

    //flip it to NTAccount format
    foreach (IdentityReference ir in irc.Translate(typeof(NTAccount)))
        Console.WriteLine(ir); //now in domain\groupname format

    Tuesday, April 18, 2006 4:10 PM
  • User-1343033763 posted

    I think I may have figured out what the problem is, but it still doesn't seem quite right to me.  I was using the Global Catalog to find the user in Active Directory.  Once I found the user I would return the searchresult.GetDirectoryEntry.  From there I would do the refresh as you mentioned above and try to access the attribute.  But there was nothing in there.

    When I changed the code to query for the user using straight LDAP for my path, the problem corrected itself.  I don't understand why that would happen.  Wouldn't searchresult.GetDirectoryEntry based on a GC path result in the same object as searchresult.GetDirectoryEntry based on an LDAP path?

    Tuesday, April 18, 2006 4:25 PM
  • User1354132231 posted
    Yep, that makes sense.  The GC contains only a portion of the attributes for every object in the domain (and tokenGroups is not one).  Even if you get a DirectoryEntry from the search, you only have a DirectoryEntry from the GC (check it's Path property).  You would have to rebind to that DirectoryEntry in order to get all the attributes (or update it even).

    If you check your schema, you will see which attributes are GC replicated and constructed attributes like tokenGroups cannot be.
    Tuesday, April 18, 2006 4:47 PM
  • User-1343033763 posted

    Thank you for all your help.  I really love these forums!  I just stumbled across them yesterday and you can guarentee I will be using them again in the future.  Just to complete this post for others who may be reading through it looking for help, this is what I ended up doing.

    I used the global catelog (GC://) to find my user.  Once I had the user, I was able to determine the path to the object.  I then used straight LDAP to bind directly to the user object.  From there all the attributes were available that I needed.  I refreshed the tokenGroups attribute and everything worked as I expected.

    Wednesday, April 19, 2006 7:52 AM