ASP.NET C# Web API – IIS Active Directory Authentication

Overview

Companies that use Windows Servers (IIS) or Azure cloud service will have Active Directory groups, Most W-2 employees in a company will have an account with their unique user name. Everyone should belong to at least one or more Active Directory groups for access. If your application is deployed behind the company firewall (Intranet) then you might be able to take advantage of the user accounts, therefore authenticating a user with their Windows account credentials which will greatly improve the user experience. This post will show one of many ways you can take advantage of this feature.

Important! This example only works if the API and Client Application (React, Angular, Vue, Javascript) is deployed to the same server and folder.

IIS

You or a Windows Administrator will have to open the IIS Website and enable/disable authentication features.

Open IIS.

Click on the website to show the properties.

Disable Anonymous Authentication and Enable Windows Authentication

API

Web.Config

Add the <authentication mode=”windows”> </authentication> tags inside of <system.web>.

Note: This will not work on a local server. This has to be deployed to an IIS server otherwise comment these lines out.

<system.web>
   <authentication mode="Windows">
   </authentication>
</system.web>

Controller

Every call to the API will contain the AD information for the user. You can access this information with HttpContext. Just replace the domain name for the one assigned to your network.

var usernameFull = HttpContext.Current.Request.LogonUserIdentity.Name;

var user = HttpContext.Current.Request.LogonUserIdentity.Name.Replace(@"DOMAIN_NAME\", "");                
var username = HttpContext.Current.Request.LogonUserIdentity.Name.Substring(HttpContext.Current.Request.LogonUserIdentity.Name.LastIndexOf(@"\") + 1);

The function below was written to get the user name example “YOUR_DOMAIN\johansmith3” and check users table.


[Route("getaduser")]
[HttpGet]
public object getADUser()
{
    try
    {
      
        var user = HttpContext.Current.Request.LogonUserIdentity.Name.Replace(@"DOMAIN_NAME\", "");                
        var username = HttpContext.Current.Request.LogonUserIdentity.Name.Substring(HttpContext.Current.Request.LogonUserIdentity.Name.LastIndexOf(@"\") + 1);
        
        using (DemoEtities db = new DemoEtities())
        {

            var userRecord = db.users.Where(col => col.UserName.Contains(user)).Single();
                                
  ...

Active Directory Groups

Example of checking AD (Active Directory) Group

An alternative to using the [Authorize] attribute for an API action or the entire controller (Below)

[Authorize(Roles = @"YOUR_DOMAIN\AD GROUP NAME")]

The Alternative

We can use the Directory Services Account Management library we can check if a user is an a specific Active Directory group.

using System.DirectoryServices.AccountManagement;

From another action to authenticate you could call a function to check if a user exists in an Active Directory group,.

string groupMame = "AD GROUP NAME";

                    
if (this.isAdminUser(username))
{
    return new { msg = "User Exists", authorized = true};    
}
else
{
    return new { msg = "Not Found", authorized = false};
}

Example – Search in AD Groups Function

An example of a private function to check a name against an array of group names. The user is searched against each group and returns a true or false if found.

private bool isInADGroup(string userName, string[] groupNames)
{
    try
    {
        string YOURDomain = @"DOMAIN_NAME";
        List<string> result = new List<string>();
        foreach (string group in groupNames)
        {

          using (PrincipalContext pc = new PrincipalContext(ContextType.Domain,YOURDomain))
          {
             using (PrincipalSearchResult<Principal> src = UserPrincipal.FindByIdentity(pc, userName).GetGroups(pc))
                {
                    src.ToList().ForEach(sr => result.Add(sr.SamAccountName));
                }
            }

            if (result.Exists(item => item.Equals(group)))
            {
                return true;
            }
        }
        return false;


    }
    catch (Exception e)
    {
        return false;
    }
}
Photo by Anna Shvets from Pexels