Search code examples
c#active-directoryldap-query

Slow AD group membership lookup


I have some code to check if a domain user is a member of the machines administrators group:

public static bool ActiveDirectoryGroupMembershipOk(string userid, string groupName)
{
    using (PrincipalContext ctx = new PrincipalContext(ContextType.Machine, "my_pc_name"))
    {
        using (GroupPrincipal grp = GroupPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, "administrators"))
        {
            if (grp != null)
            {
                foreach (Principal p in grp.GetMembers(false))
                {
                    if (p is UserPrincipal && p.SamAccountName.Equals(userid, StringComparison.InvariantCultureIgnoreCase))
                    {
                        return true;
                    }
                }
            }
        }
    }
    return false;
}

It works, but the below code line takes some seconds to complete:

using (GroupPrincipal grp = GroupPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, "administrators"))

Is there a faster way to lookup the membership?

I don't know if it is important or not, but the userid is a Domain User and the windows group is on the local PC.


Solution

  • I found that it seems to be faster not to look up the user in a group but instead to check the user's role membership.

    Here is the code that performs faster than the code in my question:

    public static bool ActiveDirectoryGroupMembershipOk(string userid, string groupName)
    {
        bool membershipOk = false;
        using (var pc = new PrincipalContext(ContextType.Machine, "my_pc_name"))
        {
            using (var p = Principal.FindByIdentity(pc, IdentityType.SamAccountName, userid))
            {
                // if user account exists, check the group membership
                if(p != null)
                {
                    System.Security.Principal.WindowsIdentity wi = new System.Security.Principal.WindowsIdentity(userid);
                    System.Security.Principal.WindowsPrincipal wp = new System.Security.Principal.WindowsPrincipal(wi);
                    membershipOk = wp.IsInRole(groupName);
                }
            }
        }
        return membershipOk;
    }