Web Service access + internal traffic + 407 Proxy Authentication Required
This had me stumped for a while. I was developing a SharePoint-based client to consume a simple web service. I started by writing a console app version of the code before deploying to SharePoint. Fairly straight-forward - added a web reference to my VS2010 project, and used
MyWebService srv = new MyWebService(); srv.DoSomething();
Early on in the project, I didn’t give much to the fact that when calling the method on the web service, I was given a 407 Proxy Authentication Error. I just setup a simple proxy for it:
WebProxy prox = new WebProxy("192.168.0.1:80"); // where 192.168.0.1 is the address of the proxy. prox.UseDefaultCredentials = true; // Tell the service to use the proxy srv.Proxy = prox;
This “fixed” the issue - until the point where I deployed the code in to SharePoint with multiple application / frontend servers, and I unwittingly encountered the double hop authentication problem. In short, by using the “UseDefaultCredentials” option, you’re saying “use the credentials of the person currently logged in”. This will therefore work in a Windows Auth / NTLM scenario (assuming that user is allowed to authenticate against the proxy) where everything is all happening on the same server. But when you have multiple servers, and the action happens on Server A, which triggers something on Server B, to authenticate against Server C (i.e., your web service), then things fall over because NTLM does not support user delegation. See here for a really neat explanation of it.
After faffing about a lot with credentials, and the proxy server involved, googling and so on, my brain finally engaged: All traffic is internal, why is the proxy server even involved?! The proxy server is designed to marshal access to the outside world. All internal traffic should be fine! I went back to basics. My console app still suffered the error, but the excellent SoapUI which I use for testing web services didn’t need any proxy authentication! It turns out that by default, .NET applications will attempt to use a proxy, even if it doesn’t need one. Allegedly, if it doesn’t have a proxy override configured, then it will attempt to use the Internet Options configured on the machine it’s running on. The problem though is that if you do need a proxy for some stuff, and don’t need a proxy for other stuff (in this case) then you’re in a spot of bother. The trick is to tell your .NET app (or indeed your IIS website) to not use a default proxy. This can be done by adding this to your app.config or your web.config:
<system .net> <defaultproxy enabled="false" useDefaultCredentials="false"> <proxy></proxy> <bypasslist></bypasslist> <module></module> </defaultproxy> </system>
Enjoy.