.NET: How to look up a user in Active Directory

active-directorynet

How do you look up a user in Active Directory?

Some example usernames are:

  • avatopia\ian
  • avatar\ian
  • ian@avatopia.com
  • ian@avatopia.local
  • avatopia.com\ian

It's important to note that i don't know the name of the domain, and i shouldn't be hard-coding it.

There is some sample code on stack-overflow that fails.

using System.DirectoryServices;

/// <summary>
/// Gets the email address, if defined, of a user from Active Directory.
/// </summary>
/// <param name="userid">The userid of the user in question.  Make
/// sure the domain has been stripped first!</param>
/// <returns>A string containing the user's email address, or null
/// if one was not defined or found.</returns>
public static string GetEmail(string userid)
{
    DirectorySearcher searcher;
    SearchResult result;
    string email;

    // Check first if there is a slash in the userid
    // If there is, domain has not been stripped
    if (!userid.Contains("\\"))
    {
        searcher = new DirectorySearcher();
        searcher.Filter = String.Format("(SAMAccountName={0})", userid);
        searcher.PropertiesToLoad.Add("mail");
        result = searcher.FindOne();
        if (result != null)
        {
            email = result.Properties["mail"][0].ToString();
        }
    }

    return email;
}

It specifically ensures that you didn't pass a full username. e.g.

Bad: avatopia\ian
Bad: avatar\ian
Good: ian
Good: ian

Because you are not allowed to pass the domain, it can't differentiate between the two users

ian
ian

Another guy has the same question on sackoverflow, but the accepted answer says that you must

first locate the naming context for
the required domain

i don't know what a "naming context" is, and i don't know what the "required domain" is. i'd really rather not write a regular expression to try to parse usernames into domain names and account names, e.g.

domain.something\user-name

into

domain.something
user-name

because i know there will be some edge case that i'll get wrong. i want the proper, intended, method of looking up a user in active directory.

There's a nice page on CodeProject How to do almost everything in Active Directory, but you can't lookup a user's information by username

i would hope that i can give my domain controller (whoever it is, where ever it is, whatever it's called) a username, and it will figure out which domain that user belongs to, talk to that domain controller, and get the work done.

Best Answer

This works for me.

You should be able to differentiate between different users on different domain controllers (ie domain/username) because the ldappaths will be different. And according to you you don't care because you are not specifying an ldappath.

You are making a bid deal about stripping out the domain/ of User.Identity.Name. but I'm not sure what you are worried about, you just need to chop the string into two halves the and the first time you encounter '\' it's time to chop.

and if you don't like that you can use the "proper way": http://msdn.microsoft.com/en-us/library/ms973834.aspx

this is good too http://geekswithblogs.net/mhamilton/archive/2005/09/30/55621.aspx

      /// This is some imaginary code to show you how to use it

      Session["USER"] = User.Identity.Name.ToString();
      Session["LOGIN"] = RemoveDomainPrefix(User.Identity.Name.ToString()); // not a real function :D
      string ldappath = "LDAP://your_ldap_path";
      // "LDAP://CN=<group name>, CN =<Users>, DC=<domain component>, DC=<domain component>,..."


      Session["cn"] = GetAttribute(ldappath, (string)Session["LOGIN"], "cn");
      Session["displayName"] = GetAttribute(ldappath, (string)Session["LOGIN"], "displayName");
      Session["mail"] = GetAttribute(ldappath, (string)Session["LOGIN"], "mail");
      Session["givenName"] = GetAttribute(ldappath, (string)Session["LOGIN"], "givenName");
      Session["sn"] = GetAttribute(ldappath, (string)Session["LOGIN"], "sn");


/// working code

public static string GetAttribute(string ldappath, string sAMAccountName, string attribute)
    {
        string OUT = string.Empty;

        try
        {
            DirectoryEntry de = new DirectoryEntry(ldappath);
            DirectorySearcher ds = new DirectorySearcher(de);
            ds.Filter = "(&(objectClass=user)(objectCategory=person)(sAMAccountName=" + sAMAccountName + "))";

            SearchResultCollection results = ds.FindAll();

            foreach (SearchResult result in ds.FindAll())
            {
                OUT =  GetProperty(result, attribute);
            }
        }
        catch (Exception t)
        {
            // System.Diagnostics.Debug.WriteLine(t.Message);
        }

        return (OUT != null) ? OUT : string.Empty;
    }

public static string GetProperty(SearchResult searchResult, string PropertyName)
    {
        if (searchResult.Properties.Contains(PropertyName))
        {
            return searchResult.Properties[PropertyName][0].ToString();
        }
        else
        {
            return string.Empty;
        }
    }

For domain/username

    public static string GetDomain(string s)
    {
        int stop = s.IndexOf("\\");
        return (stop > -1) ?  s.Substring(0, stop + 1) : null;
    }

    public static string GetLogin(string s)
    {
        int stop = s.IndexOf("\\");
        return (stop > -1) ? s.Substring(stop + 1, s.Length - stop - 1) : null;
    }

For username@domain style

   public static string GetDomain(string s) //untested
    {
        int stop = s.IndexOf("@");
        return (stop > -1) ? s.Substring(stop + 1, s.Length - stop - 1) : null;
    }


    public static string GetLogin(string s) //untested
    {
        int stop = s.IndexOf("@");
        return (stop > -1) ?  s.Substring(0, stop) : null;
    }