title: Streaming MTOM Attachments in WCF and Certificate Authentication
body: <p>I'm looking for a definitive answer as to whether what I'm trying to do is supported or not. </p>
  
  <p>Basically, I'm using WCF to stream large MTOM attachments (200 Mb), this works perfectly fine. The security requirements for the service is to use HTTPS and certificate-based authentication. I can run the service over HTTPS without any problems, but once I set IIS to “Accept client certificates” or “Require client certificates” (no change in the code), the following error is thrown (but only once the attachments get over about 80 Mb or so):</p>
  
  <pre><code>The socket connection was aborted. 
  This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. 
  Local socket timeout was '00:30:00'.
  </code></pre>
  
  <p>I found some resources, sorry can't find them now, that indicated that the failure is probably related to the fact that the incoming messages either cannot be digitally signed, or verified due to the streaming nature of the message contents. I believe the service would have to hash the whole message contents to verify the cert, but this can't be achieved because portions of the message are in transit while validation is trying to occur.</p>
  
  <p>I've setup the message contract so that the body is a single Stream element, and the other elements are contained within the header:</p>
  
  <pre><code>   &lt;MessageContract()&gt;
  Public Class StreamAttachmentRequest
  
      &lt;MessageHeader(MustUnderstand:=True)&gt;
      Public Property AttachmentName As String
  
      &lt;MessageBodyMember(Order:=1)&gt;
      Public Property Attachment As Stream
  
  End Class
  </code></pre>
  
  <p>The service configuration looks as follows:</p>
  
  <pre><code>&lt;system.serviceModel&gt;
  
  &lt;!-- BINDING --&gt;
  &lt;bindings&gt;
  &lt;basicHttpBinding&gt;
    &lt;binding name="TestCaseBasicBinding"
             messageEncoding="Mtom"
             transferMode="StreamedRequest"
             maxReceivedMessageSize="2147483647"
             closeTimeout="00:30:00"
             openTimeout="00:30:00"
             receiveTimeout="00:30:00"
             sendTimeout="00:30:00"&gt;
      &lt;security mode="Transport"&gt;
        &lt;transport clientCredentialType="None"&gt;&lt;/transport&gt;
      &lt;/security&gt;
      &lt;readerQuotas maxDepth="32"
                        maxStringContentLength="8192"
                        maxArrayLength="16384"
                        maxBytesPerRead="4096"
                        maxNameTableCharCount="16384" /&gt;
    &lt;/binding&gt;
  &lt;/basicHttpBinding&gt;
  &lt;/bindings&gt;
  
  &lt;!-- BEHAVIORS --&gt;
  &lt;behaviors&gt;
    &lt;serviceBehaviors&gt;
  
      &lt;!-- TEST CASE SECURE BEHAVIOR --&gt;
      &lt;behavior name="TestCaseSecureBehavior"&gt;
        &lt;serviceMetadata httpsGetEnabled="true" httpGetEnabled="false" /&gt;
        &lt;serviceDebug includeExceptionDetailInFaults="true"/&gt;
        &lt;serviceCredentials&gt;
          &lt;serviceCertificate
              storeLocation="LocalMachine"
              storeName="My"
              findValue="DistinguishedNameOfCert"
              x509FindType="FindBySubjectDistinguishedName" /&gt;
          &lt;clientCertificate&gt;
            &lt;authentication certificateValidationMode="ChainTrust"/&gt;
          &lt;/clientCertificate&gt;
        &lt;/serviceCredentials&gt;
      &lt;/behavior&gt;
  
    &lt;/serviceBehaviors&gt;
  &lt;/behaviors&gt;
  
  &lt;!-- SERVICES --&gt;
  &lt;services&gt;
    &lt;service name="StreamingMutualAuthTestCase.Web.Service.TestCaseServiceImplementation" 
             behaviorConfiguration="TestCaseSecureBehavior"&gt;
      &lt;!-- SERVICE --&gt;
      &lt;endpoint address=""
                binding="basicHttpBinding"
                bindingConfiguration="TestCaseBasicBinding"
                contract="StreamingMutualAuthTestCase.Web.Service.ITestCaseService" /&gt;
  
      &lt;endpoint contract="IMetadataExchange" binding="mexHttpsBinding" address="mex" /&gt;
  
    &lt;/service&gt;
  &lt;/services&gt;    
  
  &lt;serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /&gt;
  </code></pre>
  
  <p></p>
  
  <p>The client configuration looks like this:</p>
  
  <pre><code> &lt;system.serviceModel&gt;
      &lt;bindings&gt;
          &lt;basicHttpBinding&gt;
              &lt;binding name="BasicHttpBinding_ITestCaseService" closeTimeout="00:30:00"
                  openTimeout="00:30:00" receiveTimeout="00:30:00" sendTimeout="00:30:00"
                  maxReceivedMessageSize="2147483647" messageEncoding="Mtom"
                  transferMode="Streamed"&gt;
                  &lt;readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                      maxBytesPerRead="4096" maxNameTableCharCount="16384" /&gt;
                  &lt;security mode="Transport"&gt;
                      &lt;transport clientCredentialType="Certificate" realm="" /&gt;
                  &lt;/security&gt;
              &lt;/binding&gt;
          &lt;/basicHttpBinding&gt;
      &lt;/bindings&gt;
  
    &lt;!-- BEHAVIORS --&gt;
    &lt;behaviors&gt;
      &lt;endpointBehaviors&gt;
        &lt;behavior name="SecureClientBehavior"&gt;
          &lt;clientCredentials&gt;
            &lt;clientCertificate
              storeLocation="LocalMachine"
              storeName="My"
              findValue="DistinguishedNameOfCert"
              x509FindType="FindBySubjectDistinguishedName"/&gt;
            &lt;serviceCertificate&gt;
              &lt;authentication certificateValidationMode="ChainTrust"/&gt;
            &lt;/serviceCertificate&gt;
          &lt;/clientCredentials&gt;
        &lt;/behavior&gt;
      &lt;/endpointBehaviors&gt;
    &lt;/behaviors&gt;
  
      &lt;client&gt;
          &lt;endpoint address="https://test7/TestCaseService/TestCaseService.svc" 
                    binding="basicHttpBinding" 
                    bindingConfiguration="BasicHttpBinding_ITestCaseService"
                    contract="TestCaseService.ITestCaseService" 
                    name="BasicHttpBinding_ITestCaseService" 
                    behaviorConfiguration="SecureClientBehavior"/&gt;
      &lt;/client&gt;
  &lt;/system.serviceModel&gt;
  </code></pre>
  
  <p>Once again, this will work just fine until I set IIS Client Certs to either Accept or Require.</p>
  
  <p>Also, there is a 413 error in the IIS log...</p>
  
  <pre><code>2011-08-18 15:00:06 W3SVC1 10.39.8.111 POST /TestCaseService/TestCaseService.svc - 443 - 10.75.13.81 - - - test7 413 0 0
  </code></pre>
  
  <p>I've already designed an authentication service on top of my file upload service to work around the issues; but I'd really like to know if what I'm trying to do is 'do-able' or not.</p>
  
  <p>Thanks a ton - Patrick</p>