How to redirect a WCF service to an HTTPS endpoint with Windows credentials

Here is the situation I'm trying to deal with:

We have a WCF client that works with the http endpoint and the https endpoint, but not when redirecting (302) from http to https. We have an F5 load balancer that performs the functions of redirection and SSL, but as far as I can tell, this does not do anything unexpected for requests. Forwarding seems to be the culprit when the WCF does not want to provide Kerberos authentication information after the forwarding.

The sequence for a successful call (i.e. http without redirection) is as follows:

  • Client - Sends a POST request for a service using an http scheme.
  • Server - responds with unauthorized 401
  • Client - sends the POST protocol with authorization
  • Server - responds with 100 Continue
  • Client - sending soap data and completing successfully

When the call is redirected and not completed, it looks like this:

  • Client - Sends a POST request for a service using an http scheme.
  • Server - returns 302 with a redirect to the https scheme for the same address
  • Client - sends a GET for the https address (I canโ€™t understand why it is GET, not POST)
  • Server - responds with unauthorized 401
  • The client throws an exception โ€œThe HTTP request was not authorized using the Negotiate client authentication scheme. The authentication header received from the server wasโ€œ Negotiate, NTLM โ€.

It looks like this problem , but not quite the same (and in fact there is no answer there, although it refers to a "WCF protocol violation" that I can find documentation). If we disable the F5 redirection rule, then http and https traffic will work fine. Does WCF really not handle this simple redirect? Is there a workaround or any documentation for this flaw?

Client configuration (note that when testing with https I change TransportCredentialOnly to Transport):

<client> <endpoint address="http://fooserver/MyService.svc/" binding="basicHttpBinding" bindingConfiguration="clientBinding" contract="Contracts.IMyService" /> </client> <bindings> <basicHttpBinding> <binding name="clientBinding"> <security mode="TransportCredentialOnly"> <transport clientCredentialType="Windows" proxyCredentialType="Windows" /> </security> </binding> </basicHttpBinding> 

Server configuration is as follows:

 <system.serviceModel> <serviceHostingEnvironment multipleSiteBindingsEnabled="true" /> <services> <service behaviorConfiguration="MyServiceBehavior" name="MyService"> <endpoint address="" binding="basicHttpBinding" bindingConfiguration="securedBinding" contract="Contracts.IMyService"> </endpoint> </service> </services> <bindings> <basicHttpBinding> <binding name="securedBinding"> <security mode="TransportCredentialOnly"> <transport clientCredentialType="Windows" proxyCredentialType="Windows"/> </security> </binding> </basicHttpBinding> </bindings> <behaviors> <serviceBehaviors> <behavior name="MyServiceBehavior"> <serviceMetadata httpGetEnabled="true"/> <serviceDebug includeExceptionDetailInFaults="true"/> <useRequestHeadersForMetadataAddress> <defaultPorts> <add scheme="http" port="80" /> <add scheme="https" port="443" /> </defaultPorts> </useRequestHeadersForMetadataAddress> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> 
+6
source share
2 answers

I canโ€™t understand why this is GET and not POST

This is the cause of your problem. After receiving a 302 response to the POST, the client is expected to receive a new GET URL. See Below http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

If the status code 302 is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request if it cannot be confirmed by the user, as this can change the conditions under which the request was issued.

In addition, the following SO post has some good info: Response.Redirect with POST instead of Get?

So, WCF does what it should do, refusing to re-POST after redirecting 302. Unfortunately, I'm not sure what can be done to solve your problem, besides indicating the correct protocol for the first time, to avoid 302.

+1
source

I just did something similar, and I can confirm that this does not work. To make matters worse, perhaps this cannot be changed without replacing the default default WCF transport implementation.

Both redirection and authentication are handled directly inside the WCF HTTP processing, which is internal. You cannot handle the redirection manually, which causes problems if you get 301 Moved constantly and the WCF does not use the configured client credentials after the redirection.

The problem with sending a GET instead of a POST after the redirect should theoretically be solved by returning 307 temporary redirects instead of 302 Found.

+1
source

Source: https://habr.com/ru/post/910735/


All Articles