Reputation: 2947
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
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:
distinguishedName
is in the group's member
attribute, orprimaryGroupId
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:
primaryGroupId
back to something else, the user appears back in the member
attribute of the group.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