Active Directory user validation

This is part of an answer I posted on StackOverflow

(https://stackoverflow.com/questions/28667830/validate-users-of-remote-active-directory-in-c-sharp/28690682#28690682)

 

First some basics (independent of this question)

Authentication

The system checks if Bob is really Bob. In an Active Directory environment, this is usually done with a domain login from the workstation, Bob enters his username and password, and he gets a Kerberos ticket. Later, if he wants to access e.g. a file share on a remote fileserver, he does not need to login anymore, and can access the files without entering username/password.

Authorization

The system checks which resources Bob is allowed to access. Usually Bob is in domain groups, and a group is in the ACL (access control list) of the resource.

If there are multiple trusting domains, Bob needs to login in one domain, and can access resources in all other domains. This is one of the main reasons using Active Directory: single sign on

Checking if user / password is valid

If you have a username and password and want to check if the password is valid, you have to do a login to the domain. There is no way of just “checking if the password is correct”. Login means: if there is a security policy “lock account if more than 3 invalid logins”, the account will be locked out checking with wrong password, even if you “only want to check the user+password”.

Using .NET Directory Service functions

I assume here that the process is either run by a human account as a normal program, or the program is a Windows service or a scheduled task which runs under a domain “technical user” account. In this case, you do not need to provide credentials for using the AD functions. If accessing other trusting AD domains, this is also true. If you want to login to a “foreign domain”, and there is no trust, you need to provide a username+password (as in your code).

“Manually” authenticating a user

Normally, this should not be needed. Example: ASP.NET intranet usage. The user access a web application on the current domain or trusting domain, the authentication is done “in the background” by browser and IIS (if integrated Windows authentication is on). So you never need to handle user passwords in the application.

I don’t see many use cases where a password is handled by code.

One may that your program is a helper tool for storing emergency user accounts/passwords. And you want to check periodically if these accounts are valid.

This is a simple way to check:

using System.DirectoryServices.AccountManagement;
...

PrincipalContext principalContext = 
     new PrincipalContext(ContextType.Domain, "192.168.1.1");

bool userValid = principalContext.ValidateCredentials(name, password);

One can also use the older, raw ADSI functions:

using System.DirectoryServices;
....

bool userOk = false;
string realName = string.Empty;

using (DirectoryEntry directoryEntry = 
   new DirectoryEntry"LDAP://192.168.1.1/DC=ad,DC=local", name, password))
{
    using (DirectorySearcher searcher = new DirectorySearcher(directoryEntry))
    {
        searcher.Filter = "(samaccountname=" + name + ")";
        searcher.PropertiesToLoad.Add("displayname");

        SearchResult adsSearchResult = searcher.FindOne();

        if (adsSearchResult != null)
        {
            if (adsSearchResult.Properties["displayname"].Count == 1)
            {   
                realName = (string)adsSearchResult.Properties["displayname"][0];
            }
            userOk = true;
        }
    }
}