I have a Windows Service that provides data through WCF to a Windows Forms application. The service takes care also of user authentication, validating user password using LDAP over the company Active Directory servers.
The problem is that it works for weeks (even months), than something happens and the LDAP user authentication fails with the following exception until I restart the service:
System.DirectoryServices.AccountManagement.PrincipalServerDownException: The server could not be contacted.
---> System.DirectoryServices.Protocols.LdapException: The LDAP server is unavailable.
at System.DirectoryServices.Protocols.LdapConnection.Connect()
at System.DirectoryServices.Protocols.LdapConnection.SendRequestHelper(DirectoryRequest request, Int32& messageID)
at System.DirectoryServices.Protocols.LdapConnection.SendRequest(DirectoryRequest request, TimeSpan requestTimeout)
at System.DirectoryServices.Protocols.LdapConnection.SendRequest(DirectoryRequest request)
at System.DirectoryServices.AccountManagement.PrincipalContext.ReadServerConfig(String serverName, ServerProperties& properties)
--- End of inner exception stack trace ---
at System.DirectoryServices.AccountManagement.PrincipalContext.ReadServerConfig(String serverName, ServerProperties& properties)
at System.DirectoryServices.AccountManagement.PrincipalContext.DoServerVerifyAndPropRetrieval()
at System.DirectoryServices.AccountManagement.PrincipalContext..ctor(ContextType contextType, String name, String container, ContextOptions options, String userName, String password)
at System.DirectoryServices.AccountManagement.PrincipalContext..ctor(ContextType contextType, String name, String userName, String password)
at SMSTModel.Authentication.ActiveDirectory.IsUserAllowed(String username, String password)
The service restart fixes the problem.
public static bool IsUserAllowed(string username, string password)
{
String localDomain = Domain.GetComputerDomain().Name;
string userDomain = null;
string user = username;
if (user.Contains(@"\"))
{
userDomain = user.Substring(0, user.IndexOf("\\"));
user = user.Substring(user.IndexOf("\\") + 1);
}
userDomain = userDomain != null ? userDomain : localDomain;
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, userDomain, user, password))
{
bool credOk = pc.ValidateCredentials(user, password);
if (!credOk)
return false;
using (UserPrincipal userP = UserPrincipal.FindByIdentity(pc, user))
{
if (userP != null)
{
using (PrincipalContext pc1 = new PrincipalContext(ContextType.Domain, localDomain))
{
using (GroupPrincipal groupPrincipal = new GroupPrincipal(pc1))
{
groupPrincipal.Name = "APP_*";
using (PrincipalSearcher principalSearcher = new PrincipalSearcher(groupPrincipal))
foreach (Principal found in principalSearcher.FindAll())
{
if (found.Name == "APP_Group" && found is GroupPrincipal && userP.IsMemberOf((GroupPrincipal)found))
{
return true;
}
}
}
}
}
}
}
return false;
}
Any idea on why it happens and how to fix it?