02 March 2017 Active Directory, .NET Robert Muehsig

I had to find a way to access all group memberships from a given Active Directory user. The problem here is, that groups may contain other groups and I needed a list of “all” applied group memberships - directly or indirectly.

The “fastest” solution (without querying each group) is to use the Token-Groups attribute, which already does this magic for us. This list should contain all applied groups.

The code would also allow to read any other AD property, e.g. the UPN or names etc.

Code

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("ListAllGroupsViaTokenGroups:");

        List<string> result = new List<string>();

        try
        {
            result = ListAllGroupsViaTokenGroups("USERNAME", "DOMAIN");

            foreach (var group in result)
            {
                Console.WriteLine(group);
            }
        }
        catch (Exception exc)
        {
            Console.WriteLine(exc.Message);
        }

        Console.Read();
    }

  
    private static List<string> ListAllGroupsViaTokenGroups(string username, string domainName)
    {
        List<string> result = new List<string>();

        using (PrincipalContext domainContext = new PrincipalContext(ContextType.Domain, domainName))
        using (var searcher = new DirectorySearcher(new DirectoryEntry("LDAP://" + domainContext.Name)))
        {
            searcher.Filter = String.Format("(&(objectClass=user)(sAMAccountName={0}))", username);
            SearchResult sr = searcher.FindOne();

            DirectoryEntry user = sr.GetDirectoryEntry();

            // access to other user properties, via user.Properties["..."]

            user.RefreshCache(new string[] { "tokenGroups" });

            for (int i = 0; i < user.Properties["tokenGroups"].Count; i++)
            {
                SecurityIdentifier sid = new SecurityIdentifier((byte[])user.Properties["tokenGroups"][i], 0);
                NTAccount nt = (NTAccount)sid.Translate(typeof(NTAccount));

                result.Add(nt.Translate(typeof(NTAccount)).ToString() + " (" + sid + ")");
            }
        }

        return result;
    }

}

Hope this will help someone in the future.

Code @ GitHub


Written by Robert Muehsig

Software Developer - from Saxony, Germany - working on primedocs.io. Microsoft MVP & Web Geek.
Other Projects: KnowYourStack.com | ExpensiveMeeting | EinKofferVollerReisen.de