Active Directory Integration with a .NET Application


In a recent project, I tackled the task of integrating OWIN (Open Web Interface for .NET) claims-based identity with an on-premise Active Directory. In this blog post, I will look into basic details of how to work with AD (Active Directory) Domain Services in a .NET application. System.DirectoryServices.AccountManagement namespace provides a set of APIs that can be used to access users, security groups and other directory objects stored in Active Directory, which I will demonstrate below.

To get started you need to add a reference to System.DirectoryServices.AccountManagement assembly, which is included in the .NET Framework.

Visual Studio Add Reference to System.DirectoryServices.AccountManagement Assembly

For a .NET Core project, Microsoft.Windows.Compatibility NuGet package must be installed in order to access the namespace. Additionally, .NET Core version should be updated to 2.0.6 or later. Example shown below uses NuGet Package Manager Console.

PM> Install-Package Microsoft.Windows.Compatibility

Next, let’s create a simple provider class that can be leveraged in any .NET project. To take it one step further, abstraction in the form of an interface can be created, which will make our code more decoupled and easier to unit test. Having said that, at the minimum, the interface needs to contain methods to retrieve user principal object, validate credentials and retrieve user’s security groups.

public interface IActiveDirectoryProvider
{
    UserPrincipal FindUserByName(string userName);

    bool ValidateUserCredentials(string userName, string password);

    IEnumerable<Principal> GetUserSecurityGroups(string userName);
}

Now it is time to create an interface implementation. An instance of PrincipalContext class is a required dependency. This class encapsulates the domain against which all operations are performed. A good approach is to inject an instance of this class using the constructor.

public class ActiveDirectoryProvider : IActiveDirectoryProvider
{
    private PrincipalContext _principalContext;

    public ActiveDirectoryProvider(PrincipalContext principalContext)
    {
        _principalContext = principalContext;
    }

    public UserPrincipal FindUserByName(string userName)
    {
        return UserPrincipal.FindByIdentity(_principalContext, userName);
    }

    public bool ValidateUserCredentials(string userName, string password)
    {
        return _principalContext.ValidateCredentials(userName, password);
    }

    public IEnumerable<Principal> GetUserSecurityGroups(string userName)
    {
        var userPrincipal = UserPrincipal.FindByIdentity(_principalContext, userName);

        if (userPrincipal == null)
        {
                throw new InvalidOperationException("User does not exist.");
        }

        return userPrincipal.GetAuthorizationGroups().ToList();
    }
}

Now let’s turn our attention to PrincipalContext. In order to initialize a new instance of this class, we must specify a context type, and in most cases, ContextType.Domain should be used. However, for testing purposes, ContextType.Machine will allow authentication against accounts on a local development machine.

PrincipalContext principalContext = new PrincipalContext(ContextType.Domain);

The following is a simple example of how our provider can be leveraged in an MVC Controller or some other .NET component. Of course, you might choose to take advantage of the dependency injection technique to handle the initialization of ActiveDirectoryProvider.

IActiveDirectoryProvider adProvider = new ActiveDirectoryProvider(principalContext);

var isAuthenticated = false;

var user = adProvider.FindUserByName(viewModel.UserName);

if (user != null)
{
    isAuthenticated = adProvider.ValidateUserCredentials(viewModel.UserName, viewModel.Password);
    
    if (isAuthenticated)
    {
        var userGroups = adProvider.GetUserSecurityGroups(viewModel.UserName);

        // Create new ClaimsIdentity using the security groups information ...
    }
}

System.DirectoryServices.AccountManagement namespace provides a great set of APIs to integrate any .NET application with Active Directory. For further discovery of classes and functionality, please refer to Microsoft .NET documentation.

 

View more blogs and tutorials about Sitecore

Learn about our Sitecore work

 

Categories: NET Development, Identity

SEARCH ARTICLES

CATEGORIES

Sitecore 144
Commerce 100
Web Development 100
Sitecore Commerce 83
Sitecore Experience Commerce 9 64
Sitecore Experience Commerce 59
Content Management 55
eCommerce 48
B2B eCommerce 42
Sitecore Experience Platform 39
Sitecore Platinum Partner 39
Architecture 34
Insite 29
User Experience 26
Strategy 22
B2C eCommerce 21
B2B Commerce Blogs 21
commerceconnect 21
CloudCraze 20
SaaS (Software as a Service) 20
Cloud 17
Commerce Server 17
Salesforce B2B Commerce Cloud 16
Mobile 13
Search 13
Plugins 12
Analytics 12
Application Development 12
Digital Transformation 11
Sitecore Symposium 11
SPEAK 10
Helix 10
DMS 8
Social 8
Business Process 7
Authentication 7
5 Reasons 7
BI and Big Data 6
Data Visualization 6
Sitecore Presentation 6
Coveo 6
NET Development 5
Microsoft Azure 5
Automation 5
Front-End Development 4
SaaS (Software as a Service) 4
Digital Strategy 4
Brightcove 4
Press Release 4
Avalara Tax 3
Sitecore Experience Accelerator (SXA) 3
Sitecore Layouts 3
Video 3
SPE 3
Multi-site 3
Multi-lingual 3
Accessibility 3
Habitat 3
Vault 3
Identity 2
Managed Services 2
CDN 2
SMB 2
Cryptocurrency 2
Sitecore Forms 2
Sitecore Experience Commerce 9 Promotions 2
Uncategorized 2
EXM 2
Conversational Commerce 2
Sitecore SaaS 2
Security 2
Unit Testing 2
Headless Architecture 2
Sitecore Experience Awards 2
Google 1
Content Delivery Network 1
Configure Price Quote 1
CPQ 1
Blockchain 1
Coupons 1
Sitecore Rss 1
Artificial Intelligence 1
Machine Learning 1
Okta 1
RFP Process 1
NoSQL 1
Flex Accelerator for Sitecore 1
Reviews 1
SEO 1
Page Labels 1