Public Code Review
Okay, so I need to check if a username/password are valid on a given Active Directory domain (which is not the one that I am runing on). Here is the options that I came up with:
public bool IsValidLogin(string username, string password)
{
IntPtr userId = IntPtr.Zero;
if (LogonUser(username, domain, password, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
ref userId))
{
CloseHandle(userId);
return true;
}
return false;
}
I am not sure that the above code works for remote domains, and I am not sure that it works in all cases. LOGIN32_LOGIN_INTERACTIVE seems to be something that you shouldn't do on servers, but it doesn't work unles I run it with it.
Here is what MSDN seems to recommend:
public bool IsAuthenticated(string domain, string username, string pwd)
{
string domainAndUsername = domain + @"\" + username;
DirectoryEntry entry = new DirectoryEntry( _path,
domainAndUsername,
pwd);
try
{
// Bind to the native AdsObject to force authentication.
Object obj = entry.NativeObject;
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(SAMAccountName=" + username + ")";
search.PropertiesToLoad.Add("cn");
SearchResult result = search.FindOne();
if(null == result)
{
return false;
}
// Update the new path to the user in the directory
_path = result.Path;
_filterAttribute = (String)result.Properties["cn"][0];
}
catch (Exception ex)
{
throw new Exception("Error authenticating user. " + ex.Message);
}
return true;
}
I have numerous style, guidelines, performance, and best practices issues with this code.
Any other ways you can recommend?
I should note that this is actually the first time that I am interfacing with AD, although my company is doing a lot of work in this area, I always was the database/business functionality guy so far.
Comments
You must stick with AD approach. Otherwise if you use LogonUser all your requests would goes back to the PDC Emulator for processing- very bad in a bigger distributed domain environment. The directory service way to access information are usually quite cryptic, but too bad it seems is the only way to access AD in .net too.
You'll likely want to stick with AD, LogonUser is not really meant to be used across unrelated domains (and the reason you can't get other login types possibly has to do with the privileges granted to the target account).
There are a few gotchas to watch out for, though:
1- The above sample leaks resources like the plague.
2- Try to cache data if needed, hitting ADS is slow
3- Be very careful about using it in a high volume scenario. I once got into a situation where we hit AD using similar code very heavily (we had 700+ concurrent users) and the AD code would at random times cause massive deadlocks that completely brought a COM+ application to its knees. We spent more than a month with PSS trying to diagnose the issue and they never were able to tell us exactly what was causing the deadlock, though apparently something nasty was going on at a very low level (apparently the client was never catching some responses from the server or something like that).
Needless to say, they weren't very happy about having to look at memory dumps with 700 frozen threads :)
Comment preview