WCF: Windows authentication and streaming support
Issue:
We had a requirement to use STREAMING protocol along with WINDOWS AUTHENTICATION.
Above binding configuration will not help us here and we will end up seeing below error.
Error Message:
$exception {"HTTP request streaming cannot be used in conjunction with HTTP authentication. Either disable request streaming or specify anonymous HTTP authentication.\r\nParameter name: bindingElement"} System.ArgumentException
at System.ServiceModel.Channels.HttpChannelFactory`1..ctor(HttpTransportBindingElement bindingElement, BindingContext context)
ANALYSIS
As per HttpChannelFactory ctor https://referencesource.microsoft.com/\#System.ServiceModel/System/ServiceModel/Channels/HttpChannelFactory.cs,9739a9339ab039dc it is not allowed.
if (TransferModeHelper.IsRequestStreamed(bindingElement.TransferMode) && bindingElement.AuthenticationScheme!= AuthenticationSchemes.Anonymous)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("bindingElement", SR.GetString(SR.HttpAuthDoesNotSupportRequestStreaming));
}
Response from WCF PG:
The problem is that a stream can't be replayed without buffering.
1. When using authentication, the first request to the server has no authentication and the server will respond with an authentication challenge.
2. WCF uses the Expect 100-Continue header to avoid the request body being sent in the non-authenticated first request.
3. The client then needs to send the request a second time.
4. If there is a very high latency to the server, Expect-100 continue mechanism effectively is disabled. Also, the server might not support the Expect 100-Continue capability.
5. If we need to resend the body, this works fine if the request is buffered.
6. But, we always have a chance if the body needs to be re-sent when using authentication.
This becomes fundamentally incompatible with streamed mode as it is unpredictable whether any one request will succeed.
As for a potential workaround (where performance is a constraint), there are several possibilities, but the simplest is probably to use WebSockets.
With WebSockets, the authentication is done on the HTTP WebSocket upgrade handshake. So, there’s no problem with the payload being part of the authentication conversation. WebSockets can handle streamed mode without any issue.
The binding will be similar to this:
Hope this information helps!
Content created by:
Nadim Akhtar
Content published by:
Saurabh Somani