Having an issue while making POX REST call using WCF with WebHttpBinding set to Basic Authentication (HttpClientCredentialType.Basic)
Instead of one call from the client with “Authorization: Basic” specified in HTTP Header, two calls are made. First call without authentication at all to which service responses with 401 Unauthorized error, second call with proper authentication info.
This seems to be handled by WCF service with no hiccup at all. Calling third party services obviously creates a problem since they respond with error immediately.
Service Code:
[ServiceContract]
public interface IService
{
[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.Bare,
RequestFormat = WebMessageFormat.Xml,
UriTemplate = "")]
Message SendData(Message message);
}
public class Service : IService
{
public Message SendData(Message message)
{ return Message.CreateMessage(MessageVersion.None, String.Empty, "test");
}
}
Client Code:
public class Client: WebChannelFactory<IService>, IService
{
public Client(Uri baseUri, string userName, string password)
: base(CreateBinding(),
baseUri)
{
Credentials.UserName.UserName = userName;
Credentials.UserName.Password = password;
}
public Message SendData(Message requestMessage)
{
var channel = CreateChannel();
Message responseMessage = channel.SendData(requestMessage);
return responseMessage;
}
private static Binding CreateBinding()
{
var binding = new WebHttpBinding();
binding.Security.Mode = WebHttpSecurityMode.TransportCredentialOnly;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
return binding;
}
}
Using TcpTrace I’m seeing these to requests back to back:
POST / HTTP/1.1
Content-Type: application/xml; charset=utf-8
VsDebuggerCausalityData: uIDPo2lH6p+lUOdFmrqDKGWYeQkAAAAA7+Y4QR6wNUWZmwCaasMx7xrfcJZxph9NocstwCh8NQsACQAA
Host: localhost:9090
Content-Length: 89
Expect: 100-continue
Connection: Keep-Alive
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">test request</string>
POST / HTTP/1.1
Content-Type: application/xml; charset=utf-8
VsDebuggerCausalityData: uIDPo2lH6p+lUOdFmrqDKGWYeQkAAAAA7+Y4QR6wNUWZmwCaasMx7xrfcJZxph9NocstwCh8NQsACQAA
Authorization: Basic dGVzdDp0ZXN0
Host: localhost:9090
Content-Length: 89
Expect: 100-continue
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">test request</string>
Note only second call contains: Authorization: Basic dGVzdDp0ZXN0 How to stop the first request (without authorization) to be made?
Sample solution with TcpTrace utility can be downloaded here:
The problem actually lies with those third parties. Per RFC 2617 Basic authentication is done in two calls, just like Digest. The server should respond at the first call with a challenge containing a realm:
The WCF endpoint will pre-authenticate only subsequent calls after the first one. The very first call made by an appdomain to any resource will not contain the basic header user name and password.
See also What happened to the PreAuthenticate flag in WCF.
So based on Remus's answer this is my workaround
I'm simply forcing first request to go out with Basic Authorization