Search code examples
c#.netwcfiisweb-config

WCF SOAP Web Service with Windows Authentication stops working, after adding an HTTPS binding to IIS


I'm seeing strange behavior. My web service stops working when i add a HTTPS binding to IIS. This happens regardless of whether i use my Service, through a URL starting with "http://" or "https://".

Error message from my Service

The authentication schemes configured on the host ('IntegratedWindowsAuthentication') do not allow those configured on the binding 'BasicHttpsBinding' ('Anonymous'). Please ensure that the SecurityMode is set to Transport or TransportCredentialOnly. Additionally, this may be resolved by changing the authentication schemes for this application through the IIS management tool, through the ServiceHost.Authentication.AuthenticationSchemes property, in the application configuration file at the element, by updating the ClientCredentialType property on the binding, or by adjusting the AuthenticationScheme property on the HttpTransportBindingElement.

The HTTPS binding that i added in IIS

enter image description here

Authentication of my Service in IIS

enter image description here

The web.config of my Service

<?xml version="1.0"?>
<configuration>

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5"/>
  </system.web>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="">
          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Windows" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <protocolMapping>
        <add binding="basicHttpsBinding" scheme="https" />
    </protocolMapping>    
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <!--
        To browse web app root directory during debugging, set the value below to true.
        Set to false before deployment to avoid disclosing web app folder information.
      -->
    <directoryBrowse enabled="true"/>
  </system.webServer>

</configuration>

Questions

  • What is the cause of this error?
  • How can i avoid this Tight Coupling?

Solution

  • It looks like IIS assumes a basicHttpsBinding with Anonymous Authentication, by default. I solved it by adding a basicHttpsBinding with Windows Authentication (again nameless so that it overrides the default), below my already existing nameless basicHttpBinding.

    <basicHttpsBinding>
      <binding name="">
        <security mode="Transport">
          <transport clientCredentialType="Windows" />
        </security>
      </binding>
    </basicHttpsBinding>
    

    I used the WCF Configuration Editor, built into Visual Studio for this. In case anyone is wondering where all these settings are coming from:

    enter image description here

    enter image description here

    • It now works regardless of there being an HTTPS binding in IIS
    • Also my Service now works through URLs starting with "http://" or "https://"

    Microsoft should have given the web.config the same structure as IIS, where the Authentication is independent of the binding. Even better would have been if they left the configuration to IIS so that the settings can't conflict. They really dropped the ball on this one.

    The new web.config of my Service

    <?xml version="1.0"?>
    <configuration>
    
      <appSettings>
        <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
      </appSettings>
      <system.web>
        <compilation debug="true" targetFramework="4.5" />
        <httpRuntime targetFramework="4.5"/>
      </system.web>
      <system.serviceModel>
        <bindings>
          <basicHttpBinding>
            <binding name="">
              <security mode="TransportCredentialOnly">
                <transport clientCredentialType="Windows" />
              </security>
            </binding>
          </basicHttpBinding>
          <basicHttpsBinding>
            <binding name="">
              <security mode="Transport">
                <transport clientCredentialType="Windows" />
              </security>
            </binding>
          </basicHttpsBinding>
        </bindings>
        <behaviors>
          <serviceBehaviors>
            <behavior>
              <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
              <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
              <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
              <serviceDebug includeExceptionDetailInFaults="true"/>
            </behavior>
          </serviceBehaviors>
        </behaviors>
        <protocolMapping>
            <add binding="basicHttpsBinding" scheme="https" />
        </protocolMapping>    
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
      </system.serviceModel>
      <system.webServer>
        <modules runAllManagedModulesForAllRequests="true"/>
        <!--
            To browse web app root directory during debugging, set the value below to true.
            Set to false before deployment to avoid disclosing web app folder information.
          -->
        <directoryBrowse enabled="true"/>
      </system.webServer>
    
    </configuration>