Who am I? A NetworkCredential saga.
Ok. Saga might be a strong word for this little post. I was having some problems with a web service call I was trying to make and I thought it might be worthy of a post.
Basically I have the following problem. I want an application running on a machine in Domain1 to call a web service running on a machine in Domain2. Domain2 trusts Domain1, but I was having troubles with 401 Unauthorized access replies when I tried to call my web service.
UserGroup instance = new UserGroup();
instance.Credentials = System.Net.CredentialCache.DefaultCredentials;
instance.AddUserToGroup(_GroupName,
newUser.userName,
newUser.userLoginName,
newUser.userEmail,
newUser.userNotes);
This code works beautifully if I’m executing it on the actual server INSIDE an IDE. However, when I move off the server with my test harness and DLL, I get the 401 HTTP error. The problem I found is that 99% of online examples (both in and out of MSDN) use the DefaultCredentials from the CredentialCache.
So I changed the code to look like this. I should mention that the user I'm specifying can browse to the URL and pass the authentication check.
UserGroup instance = new UserGroup();
System.Net.NetworkCredential _NetworkCredential = new System.Net.NetworkCredential("Administrator", "Password1", "MyDomain");
System.Net.CredentialCache _CredentialCache = new System.Net.CredentialCache();
System.Uri _Uri = new System.Uri(@"http://10.143.3.90/_vti_bin/UserGroup.asmx");
_CredentialCache.Add(_Uri, "Basic", _NetworkCredential); // we’ve even tried setting IIS authentication to basic although we really need Windows Integrated Authentication
instance.Credentials = _CredentialCache;
instance.AddUserToGroup(_GroupName,
newUser.userName,
newUser.userLoginName,
newUser.userEmail,
newUser.userNotes);
I had Keith Rome check my work and he said he thought that should work. No dice. So I begged for help from Mr. Web Services himself - Kirk A Evans. Kirk sent me this simple little snippet:
static void Main(string[] args)
{
localhost.HelloService s = new client.localhost.HelloService();
s.Credentials = new System.Net.NetworkCredential("kirke", "MyDomainPassword", "northamerica");
Console.WriteLine(s.HelloWorld());
}
It seems like my code was overthinking the process. I'd attempted to use the completely unnecessary (for this purpose) credential cache. Just assigning the NetworkCredential to my service's credentials solved the problem. This isn't a mistake I'm likely to make again.
Thanks for the help Kirk!