title: Catch-22 prevents streamed TCP WCF service securable by WIF; ruining my Christmas, mental health
body: <p>I have a requirement to <strong>secure a streamed WCF net.tcp service endpoint using WIF</strong>.  It should authenticate incoming calls against our token server.  The service is streamed because it is designed to transfer large amounts of data n stuff.</p>
  
  <p><strong>This appears to be impossible.</strong>  And if I can't get around the catch, my Christmas will be ruined and I'll drink myself to death in a gutter while merry shoppers step over my slowly cooling body.  Totes serious, you guys.</p>
  
  <p>Why is this impossible?  Here's the Catch-22.</p>
  
  <p>On the client, I need to create a channel with the <a href="http://msdn.microsoft.com/en-us/library/system.identitymodel.tokens.genericxmlsecuritytoken%28v=vs.110%29.aspx" rel="noreferrer">GenericXmlSecurityToken</a> I get from our token server.  No problemo.</p>
  
  <pre><code>// people around here hate the Framework Design Guidelines.
  var token = Authentication.Current._Token;
  var service = base.ChannelFactory.CreateChannelWithIssuedToken(token);
  return service.Derp();
  </code></pre>
  
  <p>Did I say "no problemo"?  Problemo.  In fact, <code>NullReferenceException</code> style problemo.  </p>
  
  <p>"Bro, " I asked the Framework, "do you even null check?"  The Framework was silent, so I disassembled and found that </p>
  
  <pre><code>((IChannel)(object)tChannel).
      GetProperty&lt;ChannelParameterCollection&gt;().
      Add(federatedClientCredentialsParameter);
  </code></pre>
  
  <p>was the source of the exception, and that the <code>GetProperty</code> call was returning <code>null</code>.  So, WTF?  Turns out that if I turn on Message security and set the client credential type to <code>IssuedToken</code> then this property now exists in the <code>ClientFactory</code> (protip:  There is no "SetProperty" equivalent in IChannel, the bastard).</p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;binding name="OMGWTFLOL22" transferMode="Streamed" &gt;
      &lt;security mode="Message"&gt;
          &lt;message clientCredentialType="IssuedToken"/&gt;
      &lt;/security&gt;
  &lt;/binding&gt;
  </code></pre>
  
  <p>Sweet. No more NREs.  However, now my client is <em>faulted at birth</em> (still love him, tho).  Digging through WCF diagnostics (protip:  make your worst enemies do this after crushing them and driving them before you but right before enjoying the lamentations of their women and children), I see it's because of a security mismatch between the server and client.</p>
  
  <blockquote>
    <p>The requested upgrade is not supported by 'net.tcp://localhost:49627/MyService'. This could be due to mismatched bindings (for example security enabled on the client and not on the server).</p>
  </blockquote>
  
  <p>Checking the host's diags (again: crush, drive, read logs, enjoy lamentations), I see this is true</p>
  
  <blockquote>
    <p>Protocol Type application/ssl-tls was sent to a service that does not support that type of upgrade.</p>
  </blockquote>
  
  <p>"Well, self," I says, "I'll just turn on Message security on the host!"  And I do.  <sup><sub>If you want to know what it looks like, it's an exact copy of the client config.  Look up.</sub></sup></p>
  
  <p>Result:  <strong>Kaboom.</strong></p>
  
  <blockquote>
    <p>The binding ('NetTcpBinding','<a href="http://tempuri.org/" rel="noreferrer">http://tempuri.org/</a>') supports streaming which cannot be configured together with message level security.  Consider choosing a different transfer mode or choosing the transport level security.</p>
  </blockquote>
  
  <p>So, <strong>my host cannot be both streamed and secured via tokens</strong>.  Catch-22.</p>
  
  <p><strong>tl;dr:  How can I secure a streamed net.tcp WCF endpoint using WIF???</strong></p>