title: WCF Authentication with Supporting Tokens over Non HTTP Transport
body: <p>I followed a guide, found here <a href="http://weblogs.asp.net/cibrax/archive/2008/03/26/authenticating-users-with-supporting-tokens-in-wcf-binding-extension.aspx" rel="nofollow">http://weblogs.asp.net/cibrax/archive/2008/03/26/authenticating-users-with-supporting-tokens-in-wcf-binding-extension.aspx</a> for creating a security policy that meets my needs. I have it working as described in the article using a WCF HTTP transport. </p>
  
  <p>However, I haven't been able to configure the customBinding for dealing with a non-Http transport such as plain WCF TCP. I keep getting the error message:</p>
  
  <pre><code>Binding 'CustomBinding' doesn't support creating any channel types. This often
  indicates that the BindingElements in a CustomBinding have been stacked incorrectly 
  or in the wrong order. A Transport is required at the bottom of the stack. The 
  recommended order for BindingElements is: TransactionFlow, ReliableSession, 
  Security, CompositeDuplex, OneWay, StreamSecurity, MessageEncoding, Transport.
  </code></pre>
  
  <p>Does anyone have any suggestions for configuring the customBinding for using TCP transport?</p>
  
  <p>Binding Example from Page:</p>
  
  <pre><code>&lt;customBinding&gt;
    &lt;binding name="MutualCertificateBinding"&gt;
      &lt;security authenticationMode="MutualCertificate"/&gt;
      &lt;httpTransport/&gt;
    &lt;/binding&gt;
  &lt;/customBinding&gt;
  </code></pre>
  
  <p>I did find this blog post <a href="http://blog.ploeh.dk/2009/06/22/CustomTokensOverNonHTTPTransports.aspx" rel="nofollow">http://blog.ploeh.dk/2009/06/22/CustomTokensOverNonHTTPTransports.aspx</a> about a potential solution, but it doesn't appear to work in this case as this uses message security and a streaming transport doesn't work the message security. Then if I change to 'buffered', I received the same error.</p>
  
  <p>For Completeness: The problem I am solving is passing the user name of the logged on user from an ASP.NET MVC website to a WCF service that needs to know the user in order to only return data specific to that user.</p>
  
  <p>EDIT: 
  As Request, my binding configuration:
  Working Http Client Config:</p>
  
  <pre><code>&lt;system.serviceModel&gt;
      &lt;bindings&gt;
          &lt;customBinding&gt;
              &lt;binding name="MutualCertificate"&gt;
                  &lt;security authenticationMode="MutualCertificate" /&gt;
                  &lt;httpTransport/&gt;
              &lt;/binding&gt;
          &lt;/customBinding&gt;
          &lt;trustedWeb&gt;
              &lt;binding name="MyTrustedWeb"
                       bindingReference="MutualCertificate" /&gt;
          &lt;/trustedWeb&gt;
      &lt;/bindings&gt;
      &lt;client&gt;
          &lt;endpoint address="http://localhost:8732/Design_Time_Addresses/DataServices/MyDataService"
                    binding="trustedWeb"
                    bindingConfiguration="MyTrustedWeb"
                    behaviorConfiguration="ClientBehavior"
                    contract = "IMyDataService"&gt;
              &lt;identity&gt;
                  &lt;dns value="MyDns" /&gt;
              &lt;/identity&gt;
          &lt;/endpoint&gt;
      &lt;/client&gt;
      &lt;behaviors&gt;
          &lt;endpointBehaviors&gt;
              &lt;behavior name="ClientBehavior"&gt;
                  &lt;clientCredentials&gt;
                      &lt;clientCertificate findValue="CN=ClientCert"
                                         storeLocation="LocalMachine"
                                         storeName="My"
                                         x509FindType="FindBySubjectDistinguishedName" /&gt;
                      &lt;serviceCertificate&gt;
                          &lt;defaultCertificate findValue="CN=ServiceCert"
                                              storeLocation="LocalMachine"
                                              storeName="My"
                                              x509FindType="FindBySubjectDistinguishedName" /&gt;
                          &lt;authentication revocationMode="NoCheck"
                                          certificateValidationMode="None" /&gt;
                      &lt;/serviceCertificate&gt;
                  &lt;/clientCredentials&gt;
              &lt;/behavior&gt;
          &lt;/endpointBehaviors&gt;
      &lt;/behaviors&gt;
      &lt;extensions&gt;
          &lt;bindingExtensions&gt;
              &lt;add name="trustedWeb"
                   type="TrustedWebExtension.TrustedBindingCollectionElement, TrustedWebExtension"/&gt;
          &lt;/bindingExtensions&gt;
      &lt;/extensions&gt;
  &lt;/system.serviceModel&gt;
  </code></pre>
  
  <p>Working Http Service Config:</p>
  
  <pre><code>&lt;system.serviceModel&gt;
  &lt;bindings&gt;
      &lt;customBinding&gt;
          &lt;binding name="MutualCertificate"&gt;
              &lt;security authenticationMode="MutualCertificate" /&gt;
              &lt;httpTransport /&gt;
          &lt;/binding&gt;
      &lt;/customBinding&gt;
      &lt;trustedWeb&gt;
          &lt;binding name="MyTrustedWeb"
                   bindingReference="MutualCertificate" /&gt;
      &lt;/trustedWeb&gt;
  &lt;/bindings&gt;
  &lt;services&gt;
      &lt;!-- Use this service when testing with authentication, as you will need a custom client with username / password ability. --&gt;
    &lt;service behaviorConfiguration="MyDataServiceBehavior"
      name="MyDataService"&gt;
        &lt;endpoint address="/DataServices/MyDataService"
                  binding="trustedWeb"
                  bindingConfiguration="MyTrustedWeb"
                  contract="IMyDataService" &gt;
            &lt;identity&gt;
                &lt;dns value="MyDns"/&gt;
            &lt;/identity&gt;
        &lt;/endpoint&gt;
  
        &lt;endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /&gt;
      &lt;host&gt;
        &lt;baseAddresses&gt;
            &lt;add baseAddress="http://localhost:8732/Design_Time_Addresses" /&gt;
            &lt;add baseAddress="net.tcp://localhost:30000"/&gt;
        &lt;/baseAddresses&gt;
      &lt;/host&gt;
    &lt;/service&gt;
  &lt;/services&gt;
  &lt;behaviors&gt;
    &lt;serviceBehaviors&gt;      
      &lt;behavior name="MyDataServiceBehavior"&gt;
        &lt;!-- To avoid disclosing metadata information, 
        set the value below to false and remove the metadata endpoint above before deployment --&gt;
        &lt;serviceMetadata httpGetEnabled="True"/&gt;
        &lt;!-- 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 --&gt;
        &lt;serviceDebug includeExceptionDetailInFaults="True" /&gt;
          &lt;serviceCredentials&gt;
              &lt;!-- &lt;userNameAuthentication userNamePasswordValidationMode="MembershipProvider"
                                      membershipProviderName="SqlMembershipProvider" /&gt; --&gt;
              &lt;serviceCertificate findValue="CN=ServiceCert"
                                  storeLocation="LocalMachine"
                                  storeName="My"
                                  x509FindType="FindBySubjectDistinguishedName" /&gt;
              &lt;clientCertificate&gt;
                  &lt;!-- &lt;authentication certificateValidationMode="None" /&gt; --&gt;
                  &lt;authentication revocationMode="NoCheck"
                                  certificateValidationMode="PeerTrust" /&gt;
              &lt;/clientCertificate&gt;
              &lt;userNameAuthentication userNamePasswordValidationMode="Custom"
                                      customUserNamePasswordValidatorType="TrustedWebExtension.UsernameBlankPasswordValidator, TrustedWebExtension"/&gt;
          &lt;/serviceCredentials&gt;
      &lt;/behavior&gt;
    &lt;/serviceBehaviors&gt;
  &lt;/behaviors&gt;
    &lt;extensions&gt;
        &lt;bindingExtensions&gt;
            &lt;add name="trustedWeb"
                 type="TrustedWebExtension.TrustedBindingCollectionElement, TrustedWebExtension"/&gt;
        &lt;/bindingExtensions&gt;
    &lt;/extensions&gt;
  </code></pre>
  
  <p></p>
  
  <p>Non Working TCP Service Side Config:
  Change <code>&lt;httpTransport/&gt;</code> to <code>&lt;tcpTransport /&gt;</code> and try to start the service. The Wcf Service Host throws the error above. I've tried a few variations on that theme of specifying more values for the transport and customBinding stack, but haven't been able to make anything work.</p>