Search code examples
wcfhttpswcf-bindingwcf-securityasp.net-4.0

WCF call gets "Access is denied" over HTTPS on .NET 4


Never had problems before but after upgrading to .NET 4, I am getting "Access is Denied" when trying to invoke a WCF method over HTTPS. If I use HTTP instead of HTTPS, everything works fine. Any possible solutions for this? I can provide more specific information if requested.

web.config

    <system.serviceModel>
            <behaviors>
              <serviceBehaviors>
                <behavior name="some_product.SomeServiceAspNetAjaxBehavior">
                  <serviceDebug includeExceptionDetailInFaults="true" />
                </behavior>
              </serviceBehaviors>
              <endpointBehaviors>
                <behavior name="some_product.SomeServiceAspNetAjaxBehavior">
                  <enableWebScript />
                </behavior>
              </endpointBehaviors>
            </behaviors>
            <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
            <services>
              <service name="some_product.SomeService">
                <endpoint address="" behaviorConfiguration="some_product.SomeServiceAspNetAjaxBehavior" bindingConfiguration="BasicHttpBinding_SomeService" binding="webHttpBinding" contract="some_product.SomeService"/>
              </service>
            </services>
            <bindings>
              <basicHttpBinding>        
<binding name="BasicHttpsBinding_SomeService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="true" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
       <readerQuotas maxDepth="32" maxStringContentLength="8192" 
                     maxArrayLength="16384" maxBytesPerRead="4096" 
                     maxNameTableCharCount="16384"/>
       <security mode="Transport">
          <transport clientCredentialType="Windows" 
                     proxyCredentialType="None" realm=""/>
        </security>
     </binding>
                <binding name="BasicHttpBinding_SomeService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="true" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
                  <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
                  <security mode="None">
                    <transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
                    <message clientCredentialType="UserName" algorithmSuite="Default"/>
                  </security>
                </binding>
              </basicHttpBinding>
              <webHttpBinding>
                <binding name="BasicHttpBinding_SomeService" maxReceivedMessageSize="300000" allowCookies="true"  >
                  <readerQuotas maxStringContentLength="300000" />
                </binding>
              </webHttpBinding>
            </bindings>
            <client>
              <endpoint address="/someurl/SomeService.svc" binding="webHttpBinding" bindingConfiguration="BasicHttpBinding_SomeService" contract="some_product.SomeService" name="BasicHttpBinding_SomeService"/>
<endpoint address="/someurl/SomeService.svc" binding="webHttpBinding" bindingConfiguration="BasicHttpsBinding_SomeService" contract="some_product.SomeService" name="BasicHttpsBinding_SomeService"/>
            </client>
          </system.serviceModel>

Note: Works PERFECTLY fine over HTTP. Problem ONLY exists under HTTPS.


Solution

  • With your setup, you have no security defined -- thus you can only connect using http:

    <basicHttpBinding>        
        <binding name="BasicHttpBinding_SomeService" .....>
           <readerQuotas maxDepth="32" maxStringContentLength="8192" 
                         maxArrayLength="16384" maxBytesPerRead="4096" 
                         maxNameTableCharCount="16384"/>
           <security mode="None">
              <transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
              <message clientCredentialType="UserName" algorithmSuite="Default"/>
            </security>
         </binding>
     </basicHttpBinding>
    

    If you want to use https, you need to enable transport security:

    <basicHttpBinding>        
        <binding name="BasicHttpBinding_Secure" .....>
           <readerQuotas ..../>
           <security mode="Transport">
              <transport clientCredentialType="Windows" 
                         proxyCredentialType="None" realm=""/>
            </security>
         </binding>
     </basicHttpBinding>
    

    Update: Now that you have defined your secure HTTPS binding configuration:

    <bindings>
       <basicHttpBinding>
            <binding name="BasicHttpsBinding_SomeService" ......>
                <readerQuotas ......../>
                <security mode="Transport">
                    <transport clientCredentialType="Windows" 
                               proxyCredentialType="None" realm=""/>
                </security>
    

    you also need to configure an endpoint to use that binding configuration, of course!

    <services>
       <service name="some_product.SomeService">
          <endpoint 
               address="" 
               behaviorConfiguration="some_product.SomeServiceAspNetAjaxBehavior" 
               binding="webHttpBinding" 
               bindingConfiguration="BasicHttpBinding_SomeService" 
               contract="some_product.SomeService"/>
    
          <!-- add this endpoint !! -->       
          <endpoint 
               address="secure" 
               binding="basicHttpBinding" 
               bindingConfiguration="BasicHttpsBinding_SomeService" 
               contract="some_product.SomeService"/>
        </service>
     </services>
    

    Just defining the binding configuration without having an endpoint that actually refers to it doesn't really help......