3

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.

Mr. Blonde
  • 711
  • 2
  • 12
  • 27
  • AD in my experience is always slow so I tend to cache the results. In your case, i would use a class global variable grp and call FindByidentity just once – Pikoh Apr 04 '16 at 10:11
  • I do that per user. So it is my first request, that is slow. I just read a different post about looking at the user's memberships rather than the members of a group - and that could be faster. [Link](http://stackoverflow.com/questions/1675813/faster-way-to-find-out-if-a-user-exists-on-a-system) But I could not get that code to work. – Mr. Blonde Apr 04 '16 at 10:18

2 Answers2

1

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;
}
Mr. Blonde
  • 711
  • 2
  • 12
  • 27
0

I found a better way to do this still (assuming an AD domain), using part of Mr. Blonde's answer:

public static bool ActiveDirectoryGroupMembershipOk(String userid, String groupname)
{
    PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
    UserPrincipal user = UserPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, userid);
    GroupPrincipal group = GroupPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, groupname);

    return user.IsMemberOf(group);
}
Falcon Momot
  • 1,065
  • 8
  • 20