This took me WAY longer to figure out that either a) it shoudl have or b) I had hoped it would. I finally got it working last week though. I now have my client calling the server via a Dual Contract using IssuedToken security (requires a SAML token), said token being obtained from an STS written by me, which takes a custom token from the client for authentication.
On the plus side, I know a whole bunch more about the depths of the ServiceModel now than I did before.
It turns out (as far as I can tell) that the binding I needed for client and server cannot be described in a .config file, and must be created in code. That code looks like this on the server
public static Binding CreateServerBinding(Uri baseAddress, Uri issuerAddress)
CustomBinding binding = new CustomBinding();
IssuedSecurityTokenParameters issuedTokenParameters =
issuedTokenParameters.IssuerAddress = new EndpointAddress(issuerAddress);
issuedTokenParameters.IssuerBinding = CreateStsBinding();
issuedTokenParameters.KeyType = SecurityKeyType.SymmetricKey;
issuedTokenParameters.KeySize = 256;
and essentially the same on the client, with the addition of setting the clientBaseAddress on the CompositeDuplexBindingElement.
This works just fine, getting the token from the STS under the covers and then calling the Dual Contract server interface with the token.
I ended up with a custom binding to the STS itself, mostly because I needed to pass more credentials than just user name and password. So the STS binding gets created thusly:
public static Binding CreateStsBinding()
Binding binding = null;
= new SymmetricSecurityBindingElement();
= new X509SecurityTokenParameters( X509KeyIdentifierClauseType.Thumbprint);
x509ProtectionParameters.InclusionMode = SecurityTokenInclusionMode.Never;
messageSecurity.ProtectionTokenParameters = x509ProtectionParameters;
HttpTransportBindingElement httpBinding = new HttpTransportBindingElement();
binding = new CustomBinding(messageSecurity, httpBinding);
Not as easy as I had hoped it would be, but it's working well now, so it's all good. If you go the route of the custom token, it turns out there are all kinds of fun things you can do with token caching, etc. It does require a fair amount of effort though, since there are 10-12 classes that you have to provide.