C# – Secure password solution for a web service authenticating against Active Directory

active-directoryauthenticationc++web-services

An application I'm modifying has a Web Service, and one of the web methods on that web methods is used to authenticate a user against active directory. So the current code called by the AuthenticateUser web method looks something like this:

string domainAndUsername = aDomain + @"\\" + username;
string ldsPath = buildLdsPath(searchBase);
DirectoryEntry entry = new DirectoryEntry(ldsPath, domainAndUsername, 
    password);

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();

    // more code to validate the result, etc...
}

When I started looking at this code, the first thing that worried me is the arguments to the web method look like this:

[WebMethod]
public ResultObj AddRole(string roleToAdd, string username, string password)
{
    // code that calls above Authentication fragment...
}

So the current web service is expecting a password string, presumably sent in the clear over the network as XML, when the request is made to the service.asmx page.

Has anyone dealt with this type of issue before? Are there alternative Active Directory authentication mechanisms I could use that would avoid having to pass in a plain-text password? The best option I could come up with on my own is to invoke the WebMethod using an encrypted password, and have the code on the other side decrypt it. However, I'd prefer a better solution–e.g.: is there some way to do search for a DirectoryEntry using a one-way hash instead of a password?

Edit:

Additional Details: To this point I haven't considered SSL as this is a tool that is internal to our company, so it seems like overkill, and possibly problematic (it'll be running on a company intranet, and not externally visible). The only reason I'm even worried about the security of sending plain-text passwords is the escalating amount of (possibly password-sniffing) malware present even on company intranets these days.

Best Solution

If you have a public/private key combination, then the client could encrypt with the public key, and you decrypt with the private key.

However, that's too much work for the client, and not a very "web method" way of doing it.

Since you are sending the user name and password as parameters then you should resort to transport security, HTTPS, basically, which requires you to have a public/private key combination issued to you from a trusted certificate authority.


It should be noted that your association of SSL encrypted channel with an external facing site is incorrect. The point of wanting to encrypt a channel is to prevent man-in-the-middle attacks, exactly like you are trying to do here.

You could use a self-issued certificate, but that would require installing the public key of the certificate on each machine that is going to call your web method. It's easier to just get one from a trusted authority.