Active Directory UserPrincipals in .Net

Continuing our Active Directory theme from the last post, I wanted to step back for a second and discuss UserPrincipal objects a little more as I have a few posts relating more to accounts following this one.

The UserPrincipal class has two constructors.  One takes a PrincipalContext and the other one takes the PrincipalContext, SAM account name, password, and enabled value.  In general, I use the constructor with just the PrincipalContext when searching for an existing AD account and the ‘expanded’ constructor when I am creating a new AD user object.  As most Active Directory environments need passwords, and I generally make it a point to not know user passwords (after I create them) I think this makes sense.  So, now I’ll detail these two uses below.

First, let’s take a look at finding a user and mapping it to a UserPrincipal object.  What I’m really focused on here is the UserPrincipal itself and I’ll cover searching more in other articles.  Here’s some code:

using (var context = new PrincipalContext(ContextType.Domain, FQDC))
{
   UserPrincipal user = null;
   do
   {
      // We don't create accounts with '1' so we need to increment again.
      if (count == 1) { count++; }
      // Similar to the ADID we need to determine the identifier for the username
      string filter = count > 0 ? this.UserName + count.ToString() : this.UserName;
      user = UserPrincipal.FindByIdentity(context, filter);
      count++;
   } while (user != null);
}

This is a somewhat expanded example of a routine I use to determine AD usernames but I didn’t want to just throw in three lines and call it a day.  My primary AD domain has 18000+ user accounts so we’re bound to have duplicate names using our standard naming scheme.  In case of a duplicate, I need to append a number on it so that’s what you see here, me determining the number.  What’s truly important here is that by using the FindByIdentity method, we return a UserPrincipal object from AD that contains common AD attributes that we may be interested in and once we have this object we can manipulate these values quite easily.  As a bonus, we can extend this object with custom code and map properties such as the EmployeeID field (which is not exposed by UserPrincipal).  I’ll save that for a later post though.

Now, the second scenario involves us wanting to create a new user.  Finding and connecting to a current user is easy and so is creating a new one.

using (PrincipalContext adPC = new PrincipalContext(ContextType.Domain, FQDC))
{
    using (UserPrincipal user = new UserPrincipal(adPC, this.CommonName, this.Pass, true))
    {
        user.SamAccountName = UserName;
        user.UserName = UserName;
        user.UserPrincipalName = UserName + "@some.domain";
        user.GivenName = FirstName;
        if (this.mName != "") { user.Initials = MiddleName; }
        user.Surname = LastName;
        user.DisplayName = this.CommonName;
        user.EmailAddress = UserName + "@mydomain.com";
        user.SetPassword(this.Pass);
        user.Department = "Rocking IT Department";
        user.Company = "My Fake Company";
        user.PhysicalDeliveryOfficeName = officeLocation;
        user.ExpirePasswordNow();
        user.Enabled = true;
        user.PasswordNotRequired = false;
        user.Save();
    }
}

So creating an account is pretty simple too.  Using a PrincipalContext attached to the DC that you want to create the object on, you create a new UserPrincipal passing in the values for the context, the name as it’ll appear in AD (First Last or Last, First — however your procedures require it)  the temporary password and true to say it’s enabled (although we do set that below).  The rest are fairly standard properties that you may be setting in your schema.  Once you’ve set all of your properties save the object and you have a new Active Directory user.

Leave a Reply