Thursday, March 22, 2012

C# Code to look up current user in Active Directory

C# Code to look up Current User in Active Directory

Here's some re-usable C# code to lookup the currently logged-in user in Active Directory to get various AD properties such as FirstName, Last Name, and Email. The method IsExistInAD() below is handy in intranet applications where your ASCX or ASPX can assume the current user is authenticated in the domain and you need properties of the user from Active Directory. Method IsExistInAD() takes, as input the user name in the format DOMAIN\\alias and performs a Directory search using .NET Directory Services using System.DirectoryServices.ActiveDirectory. If successful, it populates the private SearchResult _result variable with the various properties from Active Directory and returns true. If the Directory search does not find the current user, the IsExistInAD() method returns false.  Note this code handles multiple domains, so if some of your users have username e.g. NORTHAMERICA\\bobsmith and other users have e.g. SOUTHAMERICA\\juanparamo, this code handles it by parsing the domain name and using it in the rootDirectory of the Directory Searcher, so it will find the user in the correct ActiveDirectory Domain.

Note that your ASP.NET application gets this user name to pass as input to IsExistInAD() automatically for the currently logged in user from the Page.User.Identity.Name property when your web application is configured for Windows Authentication.

The first time you setup the target server that will run the Site Info Web Application, you must configure IIS to use Windows Authentication. The Site Info Web Application depends on this and it is not the default configuration of IIS.  This configuration setting is Windows/IIS and does not require adjustment on future deployments of new builds or upgrades.

How to Configure Windows Authentication 


On the target IIS server
From Server Manager, Open Internet Information Services (IIS) Manager

In the left side panel, select the server (e.g. ZLMRCWEB31)

Double-click the  Authentication icon to open the Authentication Applet

  1. Enable Windows Authentication

  1. Disable Anonymous Authentication





Code Default.aspx.cs

using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
namespace TestADLookupUsersEmail
{
    public partial class _Default : System.Web.UI.Page
    {
        public class ContactADFields
        {
            public string FirstName;
            public readonly string FirstNameProp = "givenname";
            public string LastName;
            public readonly string LastNameProp = "sn";
            public string Email;
            public readonly string EmailProp = "mail";
            public string FullName;
            public readonly string FullNameProp = "displayname";
        }
        private SearchResult _result;
        private ContactADFields contact = new ContactADFields();       

        protected void Page_Load(object sender, EventArgs e)
        {
        }
        public string getUserIdentityName()
        {
            return Page.User.Identity.Name;
        }
        public string getUserEmail()
        {
            if (IsExistInAD(Page.User.Identity.Name))
            {
                if (_result.Properties.Contains(contact.FirstNameProp))
                {
                    contact.FirstName = (string)_result.Properties[contact.FirstNameProp][0];
                }
                if (_result.Properties.Contains(contact.LastNameProp))
                {
                    contact.LastName = (string)_result.Properties[contact.LastNameProp][0];
                }
                if (_result.Properties.Contains(contact.EmailProp))
                {
                    contact.Email = (string)_result.Properties[contact.EmailProp][0];
                }
                if (_result.Properties.Contains(contact.FullNameProp))
                {
                    contact.FullName = (string)_result.Properties[contact.FullNameProp][0];
                }
                int propCount = _result.Properties.PropertyNames.Count;
                foreach (string propName in _result.Properties.PropertyNames)
                {
                    try
                    {
                        string propVal = (string)_result.Properties[propName][0] as String;
                    }
                    catch (Exception)
                    {
                        continue;
                    }
                }
            }
            return contact.Email;
        }
        /// <summary>
        /// Parse a User Identity Name e.g. "REDMOND\\billg" setting the out accountName and out domainName
        /// </summary>
        /// <param name="path"></param>
        /// <param name="accountName"></param>
        /// <param name="domainName"></param>
        /// <returns>true if successful parsing the input user name</returns>
        private bool ParseUserName(string path, out string accountName, out string domainName)
        {
            bool retVal = false;
            accountName = String.Empty;
            domainName = String.Empty;
            string[] userPath = path.Split(new char[] { '\\' });
            if (userPath.Length > 0)
            {
                retVal = true;
                accountName = userPath[userPath.Length - 1];
                if (userPath.Length > 1)
                {
                    domainName = userPath[userPath.Length - 2];
                }
            }
            return retVal;
        }
        /// <summary>
        /// Lookup user in AD, and if successful, set SearchResult _result and return true.
        /// </summary>
        /// <param name="loginName">The Page.User.Identity.Name e.g. "REDMOND\\billg"</param>
        /// <returns>True if found in AD. Also sets SearchResult _result.</returns>
        private bool IsExistInAD(string loginName)
        {
            DirectorySearcher search = null;
            string userName;
            string domainName;
            if (ParseUserName(loginName, out userName, out domainName))
            {
                DirectoryContext dirCtx = new DirectoryContext(DirectoryContextType.Domain, domainName);
                if (dirCtx != null)
                {
                    Domain usersDomain = System.DirectoryServices.ActiveDirectory.Domain.GetDomain(dirCtx);
                    if (usersDomain != null)
                    {
                        DirectoryEntry rootDirEntry = usersDomain.GetDirectoryEntry();
                        if (rootDirEntry != null)
                        {
                            search = new DirectorySearcher(rootDirEntry);
                            search.Filter = String.Format("(SAMAccountName={0})", userName);
                        }
                    }
                }
            }
            else
            {
                search = new DirectorySearcher();
                search.Filter = String.Format("(SAMAccountName={0})", loginName);
            }
            // Adding properties to the DirectorySearcher is supposed to make the
            // query more efficient by only returning the fields we want. However,
            // doing so seems to always make teh Last Name prop ("sn") return blank.
            //search.PropertiesToLoad.Add(contact.FirstNameProp);
            //search.PropertiesToLoad.Add(contact.LastNameProp);
            //search.PropertiesToLoad.Add(contact.EmailProp);
            //search.PropertiesToLoad.Add(contact.FullNameProp);
            _result = search.FindOne();
           
            if (_result == null)
            {
                return false;
            }
            else
            {
                return true;
            }
        }
    }
}