Thursday 21 February 2013

Delegating Windows credentials to a WCF service from a load-balanced Web application: 403 Forbidden

I have a Web application that uses Windows Authentication to gather the client's credentials and then passes those credentials to a back-end Web service for delegation (so that the Web service can operate under those user's credentials).

This all works fine until you deploy it to an environment that uses load-balanced Web servers.

If you navigate to MyServerA.Domain then the credentials are accepted by the WCF service.

The same if you navigate to it's load-balanced peer, MyServerB.Domain.

However, if you go via the load-balanced DNS entry, e.g. MyLoadBalancer.Domain, the call to the Web service fails, with the old favourite:

2013-02-20 17:28:28,194 [5] ERROR TradeValidatorWebsite - The HTTP request was forbidden with client authentication scheme 'Negotiate'.
2013-02-20 17:28:28,194 [5] ERROR TradeValidatorWebsite - The remote server returned an error: (403) Forbidden.
2013-02-20 17:28:28,194 [5] ERROR TradeValidatorWebsite - Call stack follows:
2013-02-20 17:28:28,209 [5] ERROR TradeValidatorWebsite - 
Server stack trace: 
   at System.ServiceModel.Channels.HttpChannelUtilities.ValidateAuthentication(HttpWebRequest request, HttpWebResponse response, WebException responseException, HttpChannelFactory factory)
   at System.ServiceModel.Channels.HttpChannelUtilities.ValidateRequestReplyResponse(HttpWebRequest request, HttpWebResponse response, HttpChannelFactory factory, WebException responseException, ChannelBinding channelBinding)
   at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

You don't get this error if you navigate to each server individually.

In the failure mode the authentication fails because the client identified to the server does not match the hostname of the machine.

This is described here: http://support.microsoft.com/kb/325608

Some other articles
http://blogs.msdn.com/b/crminthefield/archive/2012/10/03/kerberos-in-load-balanced-environments.aspx
http://support.citrix.com/article/CTX129314
http://support.microsoft.com/kb/907272 (good)
http://support.microsoft.com/kb/810572
http://support.microsoft.com/kb/929650 (very good, current)

http://technet.microsoft.com/en-us/library/ee176972.aspx a script to query for duplicates

No comments:

Post a Comment