I am using DirectoryEntry class for LDAP authentication. It works fine when I use a single LDAP connection string. But as soon as I start executing the code on multiple threads for multiple LDAP connection string it starts throwing authentication exception randomly even though the username and password is correct. I am using following code.
public bool IsAuthenticated(string path, string domain, string group, string username, string pwd)
{
string domainAndUsername = domain + @"\" + username;
LogManager.Application.DebugFormat("Inside IsAuthenticated for User {0} from Domain {1} and Group {2} of Path {3} ", username, domain, group, path);
try
{
using (DirectoryEntry entry = new DirectoryEntry(path, domainAndUsername, pwd))
{
entry.AuthenticationType = AuthenticationTypes.Secure;
entry.RefreshCache();
//Bind to the native AdsObject to force authentication.
object obj = entry.NativeObject;
using (DirectorySearcher search = new DirectorySearcher(entry))
{
search.Filter = "(SAMAccountName=" + username + ")";
search.PropertiesToLoad.Add("cn");
SearchResult result = search.FindOne();
if (null == result)
{
LogManager.Application.ErrorLogFormat("User {0} is not available in Domain {1}", username, domain);
return false;
}
}
LogManager.Application.DebugFormat("User {0} is available in Domain {1}", username, domain);
return true;
}
}
catch (Exception ex)
{
LogManager.Application.ErrorLogFormat("Exception occured while authenticating user {0} : Error {1} ", username, ex.Message);
return false;
}
}
This function is exposed through ASMX web-service. This web service is executed simultaneously by multiple users. Each user provides the path (LDAP://{IP}/DC={Domain},DC=COM)
, domain and the credentials. So simultaneously code is executed for multiple LDAP connections.
UPDATE:
This is the ASMX web-service function which calls above function:
public class ValidateUserService : System.Web.Services.WebService
{
[WebMethod]
public Models.AuthenticationToken IsUserAuthenticated(string username, string password, string partnerName)
{
string path;
string group;
string domain;
// Internal Code to pull the domain name, group and path from the db with help of partnerName.
//each partner will have different path (LDAP conenction string) and domain.
bool isAuthenticated = IsAuthenticated(path, domain, group, username, password);
}
}
What I have observed is when multiple users from different ADs try to execute this code it randomly throws the authentication error.
As you can see the code does not have any static variable. So for each call it creates new instance of the DirectoryEntry
. So at higher level this set-up code should work with multiple LDAP connections.
Having said that, has anyone seen this behavior? Internally, does .net framework shares data across multiple DirectoryEntry
instances? Can single process have multiple simultaneous LDAP connections?
Any help, suggestion or pointers are greatly appreciated.
I have found out the work-around for the issue and posting it if anyone else faces the same issue. I have tried following methods to work with AD/LDAP:
What I have observed is that, if the application works with multiple AD servers at a time and opens simultaneous connections with multiple AD servers, then DirectoryEntry method does not work. For the valid credentials it throws the “unauthorized access” exception. My guess is that the some data/variables are shared and it tries to authenticate user against incorrect AD server. I have looked into the assembly code and I verified that it uses static variables. This could be the real cause but not 100% sure. My workaround is to use other two methods if the application needs to open simultaneous connections to multiple AD servers. I have tested it with around 10 simultaneous connections for around last six months and its working fine.
Hope this helps if someone is facing the same issue.