In a recent situation with a client I was called into look at some problems that they were having making some web service calls and through a discussion I realized that the URL for the web service was hard coded to use localhost. On the surface this doesn’t look like a problem. You know that localhost will resolve and it will point back to the same server. So what’s wrong?
Well, SharePoint, because of its centralized management of multiple servers in a farm, by default uses host headers to determine which web application that a request should be routed to. A typical SharePoint server farm will have a few web applications (at least the main web application, central administration and a shared services provider.) So what happens when you hardcode a reference to localhost?
Well, on a local development server where there’s really only one web site on port 80 and someone has gone in and manually added an entry into IIS to accept all requests on port 80 — without requiring a host header or requiring local host — everything works magically. However, when you get to a controlled environment which has multiple applications and the IIS entry hasn’t been changed bad things start to happen.
First, the request isn’t answered so someone adds allowing all requests without a matching host header entry to go to the web site. That makes the request physically go to the same server. However, doing this can make authentication information break.
So the second problem that’s seen is that when you try to use the default network credential cache it doesn’t work for the web service. This will either be the NTLM double hop issue or an issue with Kerberos and the application pool being trusted for delegation. Let’s deal with the first situation with NTLM. Essentially for security concerns the credentials supplied by the user on one server can’t be supplied by that server to a second server. I.e. we can’t get off the same box with the credentials. I know you’re saying that localhost isn’t leaving the same box. However, from the perspective of Windows — it might. You see localhost isn’t really that special. It just happens that it’s defined in the hosts file. Other than that it could be some other computer. (In fact you can map localhost to something other than the local computer if you want to — but I wouldn’t advise it.) What Windows sees is a request coming in on one URL (servera, for instance) and leaving on another. that’s a double hop and it’s blocked for NTLM traffic.
If you’re using Kerberos and you’re seeing problems it may be because the application pool account isn’t trusted for delegation (in other words, it’s not allowed to wrap credentials and send them on.) It’s easy enough to trust the account for delegation — but this creates a pretty large exposure area for that account and isn’t generally something that should be the first choice.
So what’s the answer? Simply, pick off the fully qualified host name off the current request and then manipulate the path to get to your web service. If you do this you stay on the same box (in the same application pool/application domain in most cases). This eliminates the double hop issue and substantially reduces the ways that Windows can get generally upset with your application from a security perspective.
So don’t reference your web services via localhost — if you want things to work.
[[ Note: I’ve framed this in the perspective of SharePoint, however, if you’re calling yourself in any application you should do it from the URL the user used when you can. ]]