How do I validate Active Directory creds over LDAP + SSL?
I was able to validate credentials using the System.DirectoryServices.Protocols
namespace, thanks to a co-worker. Here's the code:
// See http://support.microsoft.com/kb/218185 for full list of LDAP error codes
const int ldapErrorInvalidCredentials = 0x31;
const string server = "sd.example.com:636";
const string domain = "sd.example.com";
try
{
using (var ldapConnection = new LdapConnection(server))
{
var networkCredential = new NetworkCredential(_username, _password, domain);
ldapConnection.SessionOptions.SecureSocketLayer = true;
ldapConnection.AuthType = AuthType.Negotiate;
ldapConnection.Bind(networkCredential);
}
// If the bind succeeds, the credentials are valid
return true;
}
catch (LdapException ldapException)
{
// Invalid credentials throw an exception with a specific error code
if (ldapException.ErrorCode.Equals(ldapErrorInvalidCredentials))
{
return false;
}
throw;
}
I'm not thrilled with using a try/catch block to control decisioning logic, but it's what works. :/
Maybe this is another way. There's nothing unusual in validate credentials. The ContextOptions must set properly.
Default value:
ContextOptions.Negotiate | ContextOptions.Signing | ContextOptions.Sealing
Add Ssl:
ContextOptions.Negotiate | ContextOptions.Signing | ContextOptions.Sealing | ContextOptions.SecureSocketLayer
ContextOptions.Negotiate or ContextOptions.SimpleBind is required. Or whatever your server need to perform authentication. ContextOptions only supports OR bit to bit.
You could try also set the ContextOptions directly this way in ValidateCredentials method.
using (var pc = new PrincipalContext(ContextType.Domain, "sd.example.com:636", "DC=sd,DC=example,DC=com", ContextOptions.Negotiate | ContextOptions.SecureSocketLayer))
{
return pc.ValidateCredentials(_username, _password);
}
Or
using (var pc = new PrincipalContext(ContextType.Domain, "sd.example.com:636", "DC=sd,DC=example,DC=com", ContextOptions.Negotiate))
{
return pc.ValidateCredentials(_username, _password, ContextOptions.Negotiate | ContextOptions.SecureSocketLayer);
}