“HTTP 401: Access Denied” error trying to call WSE web service

This one has been in the back of my mind for a few weeks as something I knew I had to fix. Starting looking at it again yesterday and after 3-4 hours of refactoring and config. changes I still couldn’t get it to work.
Of course, leave it over night, start afresh in the morning, do a new web search using terminology discovered in my sleep and an answer presented itself, and what’s more it was so bleeding obvious I had to kick myself!
I was getting an HTTP 401: Access Denied error trying to call a web-service on my local machine. I’m also using certificate encryption and message signing via WSE 2.0 so I thought it was something to do with that. The calling app was a WebForms test harness so I created a WinForms test harness just to make sure it wasn’t something to do with that. It wasn’t, same error whether calling from ASP.NET or WinForms.
In the end, turns out that web service calls are not made in the context of the user running the calling app. The request actually has no credentials associated with it, so if the web service resource on the web server, in this case the .asmx file, requires authentication you’ll get, surprise surprise, a 401 error. Duh!
So, two choices to fix. Either make the web service accept anonymous requests by changing the security config of the application’s virtual folder in IIS (and ASP.NET), or pass some credentials along with the web service call. The second one is easily achieved by setting the Credentials property of the web service proxy class to some valid credentials, this line sets it to the current user’s credentials:
    proxy.Credentials = System.Net.CredentialCache.DefaultCredentials;
(see this MSDN article for more details)
But in our scenario I’ve chosen to let the web service accept anonymous requests as it makes deployment a lot easier and doesn’t sacrifice any security because we are using message-level authentication, authorisation, encryption and signing via WSE to secure the transaction.
Looking back at it now I can’t believe we didn’t see it eariler, but hey that’s coding.