Declarative Use of Custom SecurityTokenParameters

It's not the first time I've stated this, but one of the reasons I love WCF is that it's so wonderfully extensible. You can even implement your own custom security token, as this article explains. The only problem with this article is that it uses imperative code to create a custom Binding, and it doesn't explain how you can implement a custom security token mechanism in a declarative way (i.e. using app.config).

The offending part is the custom SecurityTokenParameters, which you can't specify declaratively, but have to attach to a SecurityBindingElement in some way.

So if you still want to be able to specify the use of your custom security token in app.config, how can you implement that?

A simple solution I've found involves creating a custom BindingElement that contains all the custom security token implementation, including the custom SecurityTokenParameters. This BindingElement additionally acts as a Decorator for whatever SecurityBindingElement you really want to use:

 public class CreditCardSecurityBindingElement : BindingElement
 {
     private readonly SymmetricSecurityBindingElement innerBindingElement_;
  
     public CreditCardSecurityBindingElement()
     {
         this.innerBindingElement_ = new SymmetricSecurityBindingElement();
         this.innerBindingElement_.EndpointSupportingTokenParameters.SignedEncrypted.Add(new CreditCardTokenParameters());
  
         //..
     }
  
     //..
 }

To fully implement your custom BindingElement, remember to override all its virtual methods to delegate the functionality to the inner SecurityBindingElement, like this:

 public override T GetProperty<T>(BindingContext context)
 {
     return this.innerBindingElement_.GetProperty<T>(context);
 }

To be able to use your custom BindingElement (CreditCardSecurityBindingElement) declaratively as part of a custom binding in app.config, you need to implement a BindingElementExtensionElement that creates it. Once you have done that, you should be good to go.

Comments

  • Anonymous
    June 05, 2008
    The comment has been removed
  • Anonymous
    October 01, 2008
    I'm trying to realize Declarative binding on your suit. I have the following error occurs:

The security capabilities of binding 'System.ServiceModel.Channels.CustomBinding' do not match those of the generated runtime object. Most likely this means the binding contains a StreamSecurityBindingElement, but lacks a TransportBindingElement that supports Stream Security (such as TCP or Named Pipes). Either remove the unused StreamSecurityBindingElement or use a transport that supports this element.

Could you provide the source code of your example. Thank you very much.

  • Anonymous
    October 01, 2008
    Hi Oleg As you probably have already noticed, I also replied privately to the email you sent, but for the benefit of other readers, I'll repeat my answer here: Normally, I'm only happy to share my sample code, but in rare cases, the code I post is taken directly from customer or production code. In those rare cases, it would be illegal for me to share the code; unfortunately, the code in this particular post is such a case. However, I can share an anonymized customBinding element of one of my .config files: <binding name="...">           <creditCardSecurity />           <binaryMessageEncoding />           <httpTransport /> </binding>

  • Anonymous
    February 19, 2009
    Thanks for this writeup, it was a huge help! I still don't have it fully working, but for implementation, I beleive you can skip the custom BindingElement and just do the work in the BindingElementExtensionElement, like this: public sealed class CentralAuthTokenBindingExtension : BindingElementExtensionElement { public CentralAuthTokenBindingExtension() : base() { } public override Type BindingElementType { get { return typeof(SymmetricSecurityBindingElement); } } protected override System.ServiceModel.Channels.BindingElement CreateBindingElement() { X509SecurityTokenParameters protectionParams = new X509SecurityTokenParameters(); protectionParams.InclusionMode = SecurityTokenInclusionMode.Never; SymmetricSecurityBindingElement innerBindingElement = new SymmetricSecurityBindingElement(); innerBindingElement.EndpointSupportingTokenParameters.SignedEncrypted.Add(new CentralAuthTokenParameters()); //innerBindingElement.MessageProtectionOrder = MessageProtectionOrder.SignBeforeEncrypt; innerBindingElement.ProtectionTokenParameters = protectionParams; return innerBindingElement; }

  • Anonymous
    June 22, 2009
    Hi Lee See my answer to your question over at http://blog.ploeh.dk/2009/06/22/CustomTokensOverNonHTTPTransports.aspx