end-user
end-user

Reputation: 2947

why does setting the PrimaryGroupId revert my group membership?

I'm trying to add a new user to a specific group, set the PrimaryGroupID, and remove them from "domain users". However, the moment I set the ID, it removes them from the group. Any ideas?

internal Boolean CreateAdUser(User user, String password)
{
    UserPrincipal userPrincipal = new UserPrincipal(userContainerContext, user.UserId, password, true);
    userPrincipal.SamAccountName = user.UserId;
    userPrincipal.DisplayName = user.FullName;
    userPrincipal.GivenName = user.FirstName;
    userPrincipal.Surname = user.LastName;
    userPrincipal.UserPrincipalName = user.UserId + "@domain";
    userPrincipal.SetPassword(password);
    userPrincipal.PasswordNeverExpires = true;
    //create user
    userPrincipal.Save();
    //for thoroughness and to ensure I'm not dealing with a cache
    userPrincipal.Dispose();

    // at this point, I've verified the user exists.

    GroupPrincipal domainUsers;
    GroupPrincipal targetUsersGrp;

    //fetch fresh copy from AD
    userPrincipal = UserPrincipal.FindByIdentity(rootContext, user.UserId);
    targetUsersGrp = GroupPrincipal.FindByIdentity(rootContext, "MyUserGroup");

    //add user to my group
    targetUsersGrp.Members.Add(userPrincipal);
    targetUsersGrp.Save();
    //again, to be thorough
    userPrincipal.Dispose();
    targetUsersGrp.Dispose();

    // at this point, I can see the user is in the group and has "memberOf" set.

    //fetch fresh copy from AD
    userPrincipal = UserPrincipal.FindByIdentity(rootContext, user.UserId);
    targetUsersGrp = GroupPrincipal.FindByIdentity(rootContext, "MyUserGroup");
    object primaryGroupToken = getPrimaryGroupId((DirectoryEntry)targetUsersGrp.GetUnderlyingObject());

    //set primary group id on user - this has to be done through DirectoryEntry class calls
    DirectoryEntry userDirectoryEntry = (DirectoryEntry)userPrincipal.GetUnderlyingObject();
    userDirectoryEntry.Invoke("Put", new object[] { "primaryGroupID", primaryGroupToken });
    userDirectoryEntry.CommitChanges();

    // It's at this point where things go wrong.  The user is no longer listed in "MyUserGroup", and the "memberOf"
    // now shows it's in "Domain Users"; *however* the PrimaryGroupId *is* changed!

    //remove user from domain users - this doesn't seem to work, but I'm not there yet.
    domainUsers = GroupPrincipal.FindByIdentity(rootContext, "Domain Users");
    domainUsers.Members.Remove(userPrincipal);

    return true;
}
object getPrimaryGroupId(DirectoryEntry de)
{
    de.RefreshCache(new[] { "primaryGroupToken" });
    return de.Invoke("Get", new object[] { "primaryGroupToken" });
}

Upvotes: 1

Views: 728

Answers (1)

Gabriel Luci
Gabriel Luci

Reputation: 40928

I describe this in more detail in an article I wrote, but when a group and a user are on the same domain, there are two ways that the user can be considered a member of that group:

  1. The user's distinguishedName is in the group's member attribute, or
  2. The user's primaryGroupId is set to the primaryGroupToken of the group.

But you won't see both. That's what's happening. I just tested this in our environment now.

When you do this:

targetUsersGrp.Members.Add(userPrincipal);

The effect is that the user's DN is added to the group's member attribute.

Now, if you then set the user's primaryGroupId to the primaryGroupToken of the group, it will do it, but it also hides the user from the member attribute. I say "hides", because:

  1. If you change the primaryGroupId back to something else, the user appears back in the member attribute of the group.
  2. You cannot set the primaryGroupId to a group that the user is not already a member of via the members attribute.

So if you want to set the primary group, you must add the user to the member attribute of the group first, then set the primaryGroupId, which is exactly what you're doing.

(This is something I haven't experimented with before, so I learned something here. I'm going to add this information to my article.)

Yes, the user no longer shows in the member attribute of the group, but it is inaccurate to say that the user is no longer a member of the group. The user is still a member of the group.

Upvotes: 2

Related Questions