I was particularly interested to try this with TCP binding and it looks like custom binding is the only way.
For the http I started with the Federated HTTP binding, but since the custom binding took shape, you get more control this way, so I formulated an https equivalent here too.
Note this is for illustration purposes it's certainly not production ready.
1. Get token from ACS
private static SecurityToken GetIdentityProviderToken(string acsEndpoint, string serviceEndpoint)
{
var factory =
new WSTrustChannelFactory(new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential), acsEndpoint)
{
TrustVersion = TrustVersion.WSTrust13
};
factory.Credentials.ClientCertificate.SetCertificate(
StoreLocation.LocalMachine,
StoreName.My,
X509FindType.FindBySubjectName,
"[cert dns/hostname]");
var rst = new RequestSecurityToken
{
RequestType = RequestTypes.Issue,
AppliesTo = new EndpointAddress(serviceEndpoint),
//specify URI realm that ACS token will apply to
//AppliesTo = new EndpointAddress( new Uri( "urn:federation:customer:222:agent:11" ) ),
KeyType = KeyTypes.Symmetric
};
factory.Credentials.UserName.UserName = ClientUsername;
factory.Credentials.UserName.Password = ClientPassword;
var channel = factory.CreateChannel();
return channel.Issue(rst);
}
2. Http Client config (code)
private static ChannelFactory GetCustomHttpBoundService(SecurityToken token, string address)
{
var securityBootStrap = SecurityBindingElement.CreateIssuedTokenForCertificateBindingElement(new IssuedSecurityTokenParameters());
var security = SecurityBindingElement.CreateSecureConversationBindingElement(securityBootStrap, requireCancellation: true);
Console.WriteLine("Include timestamp " + security.IncludeTimestamp);
Console.WriteLine("Allow insecure transport " + security.AllowInsecureTransport);
Console.WriteLine("Client: Detect replays " + security.LocalClientSettings.DetectReplays);
Console.WriteLine("Client: Max clock skew " + security.LocalClientSettings.MaxClockSkew);
Console.WriteLine("Server: Detect replays " + security.LocalServiceSettings.DetectReplays);
Console.WriteLine("Server: Max clock skew " + security.LocalServiceSettings.MaxClockSkew);
var customBinding = new CustomBinding(new List
{
security,
new BinaryMessageEncodingBindingElement(),
new HttpsTransportBindingElement()
});
var factory = new ChannelFactory(customBinding,
new EndpointAddress(new Uri(address), EndpointIdentity.CreateDnsIdentity("[cert dns/hostname]")));
factory.ConfigureChannelFactory();
Debug.Assert(factory.Credentials != null);
factory.Credentials.SupportInteractive = false;
factory.Credentials.ServiceCertificate.SetDefaultCertificate(StoreLocation.LocalMachine,
StoreName.My,
X509FindType.FindBySubjectName,
"[cert dns/hostname]");
return factory;
}
3. TCP Client config (code)
private static ChannelFactory GetCustomTcpBoundService(SecurityToken token, string address)
{
var securityBootStrap = SecurityBindingElement.CreateIssuedTokenForCertificateBindingElement(new IssuedSecurityTokenParameters());
var security = SecurityBindingElement.CreateSecureConversationBindingElement(securityBootStrap, requireCancellation: true);
Console.WriteLine("Include timestamp " + security.IncludeTimestamp);
Console.WriteLine("Allow insecure transport " + security.AllowInsecureTransport);
Console.WriteLine("Client: Detect replays " + security.LocalClientSettings.DetectReplays);
Console.WriteLine("Client: Max clock skew " + security.LocalClientSettings.MaxClockSkew);
Console.WriteLine("Server: Detect replays " + security.LocalServiceSettings.DetectReplays);
Console.WriteLine("Server: Max clock skew " + security.LocalServiceSettings.MaxClockSkew);
var customBinding = new CustomBinding(new List
{
security,
new BinaryMessageEncodingBindingElement(),
new SslStreamSecurityBindingElement {RequireClientCertificate = false},
new TcpTransportBindingElement()
});
var factory = new ChannelFactory(customBinding,
new EndpointAddress( new Uri(address), EndpointIdentity.CreateDnsIdentity("[cert dns/hostname]")));
factory.ConfigureChannelFactory();
Debug.Assert(factory.Credentials != null);
factory.Credentials.SupportInteractive = false;
factory.Credentials.ServiceCertificate.SetDefaultCertificate(StoreLocation.LocalMachine,
StoreName.My,
X509FindType.FindBySubjectName,
"[cert dns/hostname]");
return factory;
}
4. Http Server config
<binding name="customfedhttps">
<security authenticationmode="SecureConversation" requiresecuritycontextcancellation="true">
<secureconversationbootstrap authenticationmode="IssuedTokenForCertificate">
</secureconversationbootstrap>
</security>
<binarymessageencoding>
<httpstransport requireclientcertificate="false">
</httpstransport></binarymessageencoding>
</binding>
5. TCP Server config
<binding name="customfedtcp">
<security authenticationmode="SecureConversation" requiresecuritycontextcancellation="true">
<secureconversationbootstrap authenticationmode="IssuedTokenForCertificate">
</secureconversationbootstrap>
</security>
<binarymessageencoding>
<sslstreamsecurity requireclientcertificate="false">
<tcptransport>
</tcptransport></sslstreamsecurity></binarymessageencoding>
</binding>
6. Server behaviour
<behaviors>
<servicebehaviors>
<behavior name="fedbehaviour">
<servicemetadata httpsgetenabled="true">
<federatedservicehostconfiguration>
</federatedservicehostconfiguration></servicemetadata></behavior>
</servicebehaviors>
</behaviors>
<extensions>
<behaviorextensions>
<add name="federatedServiceHostConfiguration" type="Microsoft.IdentityModel.Configuration.ConfigureServiceHostBehaviorExtensionElement, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
</add></behaviorextensions>
</extensions>
7. Identity model config
<microsoft.identitymodel>
<service>
<audienceuris>
<add value="https://localhost/Service1.svc">
<add value="net.tcp://localhost:997/Service2.svc">
</add></add></audienceuris>
<servicecertificate>
<certificatereference findvalue="[cert dns/hostname]" storelocation="LocalMachine" storename="My" x509findtype="FindBySubjectName">
</certificatereference></servicecertificate>
<issuernameregistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<trustedissuers>
<add name="[cert dns/hostname]" thumbprint="[cert thumb print]">
</add></trustedissuers>
</issuernameregistry>
<certificatevalidation certificatevalidationmode="None">
</certificatevalidation></service>
</microsoft.identitymodel>
Useful links: