Share via


Using System.DirectoryServices to add, remove, and verify group membership

I've had several customers who have built SharePoint solutions to manage domain group membership in lieu of rolling out full on Forefront Identity Manager.   I'm not one to debate the decision as to if SharePoint is the right tool or not but I do have occasion to support them on their endeavors. 

There are several ways to skin this cat in .NET.   You could use the System.DirectoryServices.AccountManagement (https://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement(v=vs.110).aspx)  namespace.  It was introduced in .NET 3.5 so you can use it with SharePoint 2010 full trust code.

I'm a big fan of doing things the old fashioned way so to speak using System.DirectoryServices (https://msdn.microsoft.com/en-us/library/system.directoryservices(v=vs.110).aspx).   That stuff has been around since .NET 1.1.   By using ADSI you can query via LDAP and manually manipulate the DirectoryEntry objects.   I find this solution just makes more sense to me.  It also is transportable and if for some reason you weren't using Active Directory and instead you were using some other LDAP provider your code would still work.

To that end I created a simple helper class that can be used to add, remove, and verify group membership for a user.   Here is a class you can use followed by an example of how to utilize it from a console app.

 using System;
 using System.DirectoryServices;
 
 namespace ADHelper
 {
 public class ADHelper
 {
 
 private string username;
 private string password;
 public string domain;
 
 public ADHelper(string username, string password, string domain)
 {
 this.username = username;
 this.password = password;
 this.domain = domain;
 }
 
 //Looks up the DN for a user based on the sAMAccountName
 public string GetUserDN(string identity)
 {
 //Split out the identity to get just the username portion
 if (identity.Contains("\\"))
 {
 string[] identityList = identity.Split('\\'); 
 string userName = identityList[1];
 using (var rootEntry = new DirectoryEntry("LDAP://" + domain, this.username, this.password, AuthenticationTypes.Secure))
 {
 using (var directorySearcher = new DirectorySearcher(rootEntry, String.Format("(sAMAccountName={0})", userName)))
 {
 var searchResult = directorySearcher.FindOne();
 if (searchResult != null)
 {
 using (var userEntry = searchResult.GetDirectoryEntry())
 {
 return (string)userEntry.Properties["distinguishedName"].Value;
 }
 }
 }
 }
 }
 return null;
 }
 
 
 //Looks up the DN for the group based on the name
 public string GetGroupDN(string groupname)
 {
 using (var rootEntry = new DirectoryEntry("LDAP://" + domain, this.username, this.password, AuthenticationTypes.Secure))
 {
 using (var directorySearcher = new DirectorySearcher(rootEntry, String.Format("(&(objectCategory=group)(cn={0}))", groupname)))
 {
 var searchResult = directorySearcher.FindOne();
 if (searchResult != null)
 {
 using (var userEntry = searchResult.GetDirectoryEntry())
 {
 return (string)userEntry.Properties["distinguishedName"].Value;
 }
 }
 }
 }
 return null;
 }
 
 
 
 //Checks to see if a user is in a group and returns a bool
 public bool isUserInGroup(string userDn, string groupDn)
 {
 bool match = false;
 
 
 DirectoryEntry user = new DirectoryEntry("LDAP://" + userDn, this.username, this.password, AuthenticationTypes.Secure);
 foreach (string group in user.Properties["memberof"])
 if (group == groupDn)
 match = true;
 
 return match;
 }
 
 
 //Adds a given user to a group 
 public bool AddToGroup(string userDn, string groupDn)
 {
 bool success = false;
 try
 {
 DirectoryEntry dirEntry = new DirectoryEntry("LDAP://" + groupDn, this.username, this.password, AuthenticationTypes.Secure);
 dirEntry.Properties["member"].Add(userDn);
 dirEntry.CommitChanges();
 dirEntry.Close();
 success = true;
 }
 catch (System.DirectoryServices.DirectoryServicesCOMException ex)
 {
 success = false;
 }
 
 return success;
 }
 
 //Removes a user from a group
 public bool RemoveUserFromGroup(string userDn, string groupDn)
 {
 bool success = false;
 try
 {
 DirectoryEntry dirEntry = new DirectoryEntry("LDAP://" + groupDn);
 dirEntry.Properties["member"].Remove(userDn);
 dirEntry.CommitChanges();
 dirEntry.Close();
 success = true;
 }
 catch (System.DirectoryServices.DirectoryServicesCOMException ex)
 {
 
 success = false;
 }
 return success;
 }
 }
 }
  namespace ADHelper
 {
 class Program
 {
 static void Main(string[] args)
 {
 
 string username = "jason";
 string password = "supersecretpassword";
 string domain = "home.vallery.net";
 
 //Create new helper object with the username and password of service account
 ADHelper helper = new ADHelper(username, password, domain);
 
 //Lookup the DN of our user
 string userDN = helper.GetUserDN("home\\jason");
 
 //Lookup the DN of our group
 string groupDN = helper.GetGroupDN("AWESOME PEOPLE GROUP");
 
 
 //Determine if our user is in the group
 Console.WriteLine(string.Format("Is {0} a member of {1}: {2}", userDN, groupDN, helper.isUserInGroup(userDN, groupDN).ToString()));
 
 //Add our user to the group
 helper.AddToGroup(userDN, groupDN);
 
 //Determine if our user is in the group
 Console.WriteLine(string.Format("Is {0} a member of {1}: {2}", userDN, groupDN, helper.isUserInGroup(userDN, groupDN).ToString()));
 
 //Remove user from the group
 helper.RemoveUserFromGroup(userDN, groupDN);
 
 //Determine if our user is in the group
 Console.WriteLine(string.Format("Is {0} a member of {1}: {2}", userDN, groupDN, helper.isUserInGroup(userDN, groupDN).ToString()));
 
 Console.ReadLine();
 
 }
 }
 }

Comments

  • Anonymous
    June 22, 2014
    RemoveUserFromGroup  is trying to do this anonymously? :)

  • Anonymous
    December 10, 2015
    There seems to be a bug in the GetUserDN function in that, if the value passed to the 'identity' variable does NOT contain a slash, a null value is returned by the function. Took me ages to figure out that this was the reason my call of the isUserInGroup function kept failing.