Solved: Getting 401 Unauthorized while calling an ASMX service using windows authentication

Today I’ve spent almost the whole day to figure out why an application (COM+) couldn’t authenticate against a ASMX web service. Using my favorite networking tools Wireshark and HTTP Fiddler I saw that the credentials didn’t get included in the initial request, and no other request was made when the 401 challenge came from the web service.

The code was doing something like this:

using (client = new MyWebService())
{
    var credentials = new NetworkCredential();
    credentials.Username = ConfigurationManager.AppSettings["WSUserName"]
    credentials.Password = ConfigurationManager.AppSettings["WSPassword"]
    credentials.Domain = ConfigurationManager.AppSettings["WSDomain"]
    client.Credentials = credentials;

    // .. and the call here ..
}

That didn’t work very well. So I fiddled around with CredentialsCache (trying both “Negotiate” and “NTLM”) and using FQDN or just the server name:

var cache = new System.Net.CredentialCache();
cache.Add(new Uri("http://srt00428"), "NTLM", new NetworkCredential("SomeName", "SomePassword"));

var client = new MyWebService();
client.Credentials = cache;
// ..and the call..

That didn’t work so well either.

Then I tried to assign it directly:

var client = new MyWebService();
client.Credentials = new NetworkCredential("SomeName", "SomePassword", "MyDomain")
// ..and the call..

Didn’t work either. And out of desperation I just tried to use the username/password:

var client = new MyWebService();
client.Credentials = new NetworkCredential("SomeName", "SomePassword")
// ..and the call..

Voila! It worked. Don’t ask me why, but it does. Do note that I couldn’t get this to work:

using (client = new MyWebService())
{
    var credentials = new NetworkCredential();
    credentials.Username = ConfigurationManager.AppSettings["WSUserName"]
    credentials.Password = ConfigurationManager.AppSettings["WSPassword"]
    client.Credentials = credentials;

    // .. and the call here ..
}

The username/password HAS to be set in the NetworkCredential constructor..

My final code:

using (client = new MyWebService())
{
    var username = ConfigurationManager.AppSettings["WSUserName"]
    var password = ConfigurationManager.AppSettings["WSPassword"]
    client.Credentials = new NetworkCredential(username, password);

    // .. and the call here ..
}