Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PrincipalContext.ValidateCredentials extremely slow

First off, I've looked at most of the questions on SO, but none seem to be exactly the same issue. Here is a similar question, but not entirely the same. In my circumstance, I'm creating a PrincipalContext as such:

Dim pctx As PrincipalContext = New PrincipalContext(ContextType.Domain, fullyqualifieddomain, container, ADUserID, ADPassword)


   If pctx.ValidateCredentials(userName, password) Then

The ADUserID is a service account.

This method works, but takes upwards of 6-10 seconds.

I've also tried retrieving the underlying directory entry and binding directly. This is much faster and works on my machine (which is outside the domain), but not on the web server (which is inside the domain). It fails at the DirectoryEntry.NativeObject call. I don't know why. Unfortunately, I'm in a situation where the only way that is working is too slow to be feasible. Is there a way to speed this up?

Thanks in advance!

like image 665
Matt M Avatar asked Jun 06 '12 19:06

Matt M


2 Answers

Try the code below. It may be no faster but it will be nice to see if it works.

Username should be without the domain included. For domain my test just used the short name, "DOMAIN", not a DN or even fully qualified (your milage may vary).

Add a reference to System.DirectoryServices.Protocols.

using System.DirectoryServices.Protocols;

public static bool Authenticate(string username, string password, string domain)
{
    try
    {
        //string userdn;
        using (LdapConnection lconn = new LdapConnection(new LdapDirectoryIdentifier(domain)))
        {
            lconn.Bind(new System.Net.NetworkCredential(username, password, domain));
            return true;
        }
    }
    catch (LdapException e)
    {
        return false;  
    }
}  

if (Authenticate("username", "password", "domain")) { }
like image 172
Peter Avatar answered Oct 18 '22 14:10

Peter


If your domain is using NetBIOS name, try change it to DNS name if you got it.

For example, from "domain: abc" => "domain: abc.com"

My code:

PrincipalContext dc = new PrincipalContext(ContextType.Domain, domain, dn, user, password);
bool authenticated = dc.ValidateCredentials(user, password);
if (authenticated) var info = UserPrincipal.FindByIdentity(dc, IdentityType.SamAccountName, $"{domain}\\{user}");

Before

2018/04/03 14:54:32[Info]PrincipalContext time:00:00:04.7638888
2018/04/03 14:54:41[Info]authenticated time:00:00:09.1260688
2018/04/03 14:54:46[Info]info time:00:00:04.7254238

After

2018/04/03 15:16:30[Info]PrincipalContext time:00:00:00.1557923
2018/04/03 15:16:30[Info]authenticated time:00:00:00.0373904
2018/04/03 15:16:30[Info]info time:00:00:00.0915680

Get IP from NetBIOS name cost lots time, that's why if using NetBIOS name as domain, PrincipalContext will be very slow.

like image 45
Died Avatar answered Oct 18 '22 16:10

Died