Search code examples
c#asp.net-identityidentityserver4

LDAP Queries, Core 2.x, IdSvr, Self Host


Writing a C#, Core 2.1, self-hosted web api to stand up an Identy Sewrver 4 instance...

Trying to use LDAP for (temp) user and role store. Yet, when I run the STS I am working on, I keep getting a "bad password" error when I query LDAP. I am working on my Laptop (in a workgroup), am running a DC in Hyper-V (domain).

I am trying to use System.DirectoryServices.AccountManagement and have a simple search setup as:

// Pass in userName as [email protected]
// Example:  userName = [email protected]
// Domain Controller is found at dc01.sol3.net
public static bool CanSignIn(string userName, string domainName)
{
    using (var pc = new PrincipalContext(ContextType.Domain, domainName))
    {
        UserPrincipal user = null;

        try
        {
            var name = userName.Split('@');
            user = UserPrincipal.FindByIdentity(pc, IdentityType.Name, name[0]);
        }
        catch (Exception ex)
        {
            Log.Warning(ex, $"Could not find {userName} in Active Directory, Domain: {domainName}!");
        }

        return user != null;
    }
}

I am wondering if:

  • I need to attach my laptop to the domain?
  • Using Kestrel is interfering?
  • Should I run in IIS Express mode?
  • Should I research how to run under HTTP.SYS?
  • What path will help here?

TIA


Solution

  • I think you need to manually authenticate using a password in order to query the directory. Using the method you detail in your question there is no way for the calling app to identify itself. If you want the app to run independently of the domain (i.e. not have to run as a domain user on a domain-joined server) then the best way would be to use a raw LdapConnection and bind a username/password NetworkCredential to it.

    This example uses a pre-configured service account to query for a user by their primary email address:

    var connection = new LdapConnection(ldapServerName);
    connection.AuthType = AuthType.Basic;
    //Additional connection setup omitted for brevity
    connection.Bind(new NetworkCredential(serviceUserName, servicePassword));
    
    var request = new SearchRequest(
                   baseDistinguishedName,
                   "(&(objectClass=person)(mail=" + EscapeFilterValue(emailAddress) + "))",
                   System.DirectoryServices.Protocols.SearchScope.Subtree, 
                   null
    );
    
    SearchResponse response = (SearchResponse)_connection.SendRequest(request);