How to Track Active AD Users Connected to IIS Web Server Programmatically


4 views

When managing internal IIS web servers, administrators often need to identify currently connected Active Directory (AD) users. This is particularly important for security audits, performance monitoring, or troubleshooting authentication issues. The native IIS Manager provides basic connection information, but lacks AD user context.

While you can view current connections in IIS Manager (under "Worker Processes" or "Current Requests"), this method doesn't directly show AD usernames. For proper AD integration, we need to combine several Windows APIs:

// C# example using System.DirectoryServices
using (DirectoryEntry entry = new DirectoryEntry("LDAP://DC=yourdomain,DC=com"))
{
    DirectorySearcher search = new DirectorySearcher(entry);
    search.Filter = "(samAccountName=" + username + ")";
    // Additional search properties here
}

Here's a practical PowerShell script that combines IIS and AD information:

Import-Module WebAdministration
$sessions = Get-ChildItem IIS:\AppPools | ForEach-Object {
    $poolName = $_.Name
    Get-WmiObject -Namespace "root\WebAdministration" -Class WorkerProcess |
    Where-Object { $_.AppPoolName -eq $poolName } |
    Select-Object -ExpandProperty GetRequests() |
    ForEach-Object {
        $username = $_.GetServerVariable("LOGON_USER")
        if ($username) {
            $adUser = Get-ADUser -Filter {SamAccountName -eq $username}
            [PSCustomObject]@{
                IP = $_.ClientIPAddr
                User = $username
                FullName = $adUser.Name
                Department = $adUser.Department
                RequestURL = $_.Url
                Time = $_.TimeElapsed
            }
        }
    }
}
$sessions | Format-Table -AutoSize

For enterprise environments, consider creating a custom solution with SignalR for real-time updates:

// ASP.NET Core example
public class ConnectionTracker : IConnectionTracker
{
    public async Task<List<ActiveUser>> GetActiveUsersAsync()
    {
        var serverManager = new ServerManager();
        var activeUsers = new List<ActiveUser>();
        
        foreach (var site in serverManager.Sites)
        {
            foreach (var app in site.Applications)
            {
                var pool = serverManager.ApplicationPools[app.ApplicationPoolName];
                if (pool != null)
                {
                    var workers = pool.WorkerProcesses;
                    foreach (var worker in workers)
                    {
                        var requests = worker.GetRequests(0);
                        foreach (var request in requests)
                        {
                            var username = request.GetServerVariable("LOGON_USER");
                            if (!string.IsNullOrEmpty(username))
                            {
                                activeUsers.Add(new ActiveUser {
                                    Username = username,
                                    IPAddress = request.ClientIPAddr,
                                    Url = request.Url,
                                    LastActive = DateTime.Now
                                });
                            }
                        }
                    }
                }
            }
        }
        return activeUsers;
    }
}

When implementing these solutions:

  • Ensure your service account has appropriate permissions in both IIS and AD
  • Consider implementing caching to reduce AD query load
  • Log only necessary information to comply with privacy regulations
  • Use secure protocols when transmitting sensitive user data

For non-.NET environments, you can:

  1. Parse IIS logs with LogParser and correlate with AD data
  2. Use JavaScript tracking on the client side (less reliable for intranet)
  3. Implement HTTP modules for custom tracking

When managing an internal IIS web server, administrators often need to identify which Active Directory users are currently accessing resources. This requirement becomes crucial for:

  • Security auditing and compliance
  • Performance monitoring during peak usage
  • Troubleshooting specific user issues

While IIS provides basic connection monitoring through its Management Console, it primarily shows:

Get-WmiObject -Namespace "root\WebAdministration" -Class WorkerProcess | Select-Object AppPoolName, ProcessId, State | Format-Table -AutoSize

This PowerShell command reveals worker processes but doesn't directly map to AD users. The main limitations include:

  • Shows only anonymous or basic authentication users
  • No direct AD user mapping for Windows Authentication
  • Limited historical tracking

Here's a C# solution that extends IIS logging to capture AD user information:

using System;
using System.DirectoryServices;
using System.Web;

public class ADUserTrackingModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.PostAuthenticateRequest += OnAuthenticate;
    }

    private void OnAuthenticate(object sender, EventArgs e)
    {
        var context = ((HttpApplication)sender).Context;
        if (context.User.Identity.IsAuthenticated)
        {
            var userName = context.User.Identity.Name;
            using (var entry = new DirectoryEntry("LDAP://" + userName.Split('\\')[0]))
            {
                using (var searcher = new DirectorySearcher(entry))
                {
                    searcher.Filter = $"(sAMAccountName={userName.Split('\\')[1]})";
                    var result = searcher.FindOne();
                    // Log user details to database or file
                    LogAccess(userName, result.Properties["displayName"][0].ToString(),
                             context.Request.UserHostAddress);
                }
            }
        }
    }

    private void LogAccess(string userName, string displayName, string ip)
    {
        // Implementation depends on your logging solution
    }

    public void Dispose() { }
}

For immediate visibility, combine these PowerShell commands:

# Get current IIS sessions
$sessions = Get-WebSessionState -ApplicationHost

# Map to AD users
$activeUsers = $sessions | ForEach-Object {
    $user = $_.SessionId.Split('.')[0]
    Get-ADUser -Identity $user -Properties DisplayName,Department |
    Select-Object SamAccountName,DisplayName,Department,@{Name='IP';Expression={$_.SessionId.Split('.')[1]}}
}

$activeUsers | Format-Table -AutoSize

For large-scale deployments consider:

  • Implementing a custom HTTP module that logs to a central database
  • Using Azure Application Insights with custom telemetry
  • Deploying a reverse proxy with enhanced logging capabilities

When implementing user tracking:

  • Ensure compliance with privacy policies
  • Secure stored logs with proper access controls
  • Anonymize sensitive data in non-production environments