nlstack01
nlstack01

Reputation: 839

Get Primary Group From UserPrincipal C#

I want to locate the Primary Group from the code below

I can get all the Groups for a user, but which one is the primary group?

        string primaryGroupName = String.Empty;
        using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
        {
            using (UserPrincipal user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, "userName"))
            {
                foreach (Principal p in user.GetGroups())
                {
                    WriteLog("PrimaryGroup Name(s)???:");
                    WriteLog(p.Name);
                    primaryGroupName = p.Name;
                }
            }
        }

Whats returned from the code above is...

Domain Users
Administrators
Schema Admins
Enterprise Admins
Domain Admins
..and a few more

What is the Primary Group?

Upvotes: 1

Views: 1679

Answers (1)

Gabriel Luci
Gabriel Luci

Reputation: 40938

You have the right idea: The primaryGroupID holds the RID (Relative Identifier) of the group that is the primary group. The RID is the last set of numbers in the SID. The rest of the SID identifies the domain. So you can figure out the SID of the group using the SID of the user and the primaryGroupID.

I wrote a couple articles about this. One called What makes a member a member?, with a section describing the primary group. But also an article called Finding all of a user’s groups where I shared some code to find the primary group. I have found that using DirectoryEntry directly is always faster than using UserPrincipal/GroupPrincipal, so that's what my examples use:

Here is the method:

private static string GetUserPrimaryGroup(DirectoryEntry de) {
    de.RefreshCache(new[] {"primaryGroupID", "objectSid"});

    //Get the user's SID as a string
    var sid = new SecurityIdentifier((byte[])de.Properties["objectSid"].Value, 0).ToString();

    //Replace the RID portion of the user's SID with the primaryGroupId
    //so we're left with the group's SID
    sid = sid.Remove(sid.LastIndexOf("-", StringComparison.Ordinal) + 1);
    sid = sid + de.Properties["primaryGroupId"].Value;

    //Find the group by its SID
    var group = new DirectoryEntry($"LDAP://<SID={sid}>");
    group.RefreshCache(new [] {"cn"});

    return group.Properties["cn"].Value as string;
}

To use that from your code, you would do this:

var primaryGroupName = GetUserPrimaryGroup((DirectoryEntry) user.GetUnderlyingObject());

That method just returns the name of the group, but you can modify it as you need.

All that said, 513 is always the RID of the built-in Domain Users group.

Upvotes: 1

Related Questions