locked
AuthenticationMode UserNameForCertificate and Tcp Transport RRS feed

  • Question

  •  

    I am trying to implement the following:

    Smart client using static proxy to access service via STS.

    Client provides username, password, and certificate sent to STS to be auth'd against AD and custom cert auth. AD auth is done via a custom UserNamePassword Validator.

     

    I have the custom bindings / behaviors set up initially and working correctly to validate using username and password. In trying to implement the custom cert auth validator, I started using a custom binding simialr to the wcf Supporting Token example, except using tcp transport, which is our preference. I am doing this in order to get access to the client supplied cert, and hopefully get my customCertValidator to be called. I suspect I could do this with a custom token, manager, provider, authenticator et al, but I would like to use something out of the box if possible.

     

    I get an error when starting the self-hosting wcf service that says that the channel could not be created.

     

    Here is the binding I am using:

    <binding name="UserNameForCertificateCustomBinding" closeTimeout="00:10:00"

    openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00">

    <security authenticationMode="UserNameForCertificate" requireDerivedKeys ="false">

    <issuedTokenParameters keyType="SymmetricKey" tokenType="X509Certificate">

    </issuedTokenParameters>

    </security>

    <tcpTransport/>

    </binding>

     

    Here is the error:

     

    System.InvalidOperationException: 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. .

     

    I get this error even with the most simple binding config that uses tcpTransport. I can replicate this behavior in the Supporting Token example by changing the transport type to tcpTransport. Is the some incompatibility here that I am unaware of. Is the UserNameForCert authMode not supported on tcp transport, or is there a tcp transport specific attribute that defaults to an unacceptable value?

     

     

    I have also been struggling a bit to find a good example of how to mimic the in code configuration from the SupportingToken example using configuration files. For example, I have not been able to successfully include the inclusionMode attribute, or figure out how to secifiy the token as an endorsing token. Any pointers to good samples of this would be appreciated.

     

    In fact, any feedback at all would be appreciated.

     

    Thanks,

     

    JF

    Tuesday, September 25, 2007 5:16 PM

Answers

  • Message security over tcp requires session in most cases, so you want

     

     <binding>

      <security authenticationMode="SecureConversation" requireDerivedKeys ="true">

        <secureConversationBootstrap authenticationMode="UserNameForCertificate" />

      </security>

      <tcpTransport/>

    </binding>

     

    Supporting token parameters and inclusion mode aren't supported in config.

    Wednesday, September 26, 2007 5:02 AM

All replies

  • Message security over tcp requires session in most cases, so you want

     

     <binding>

      <security authenticationMode="SecureConversation" requireDerivedKeys ="true">

        <secureConversationBootstrap authenticationMode="UserNameForCertificate" />

      </security>

      <tcpTransport/>

    </binding>

     

    Supporting token parameters and inclusion mode aren't supported in config.

    Wednesday, September 26, 2007 5:02 AM
  • Thanks Todd, I did not notice the exclusion of inclusion mode in the config docs I was reading.

    Does this seem to be a reasonable approach to acquiring both username / password and certificate data from the client for validation by the STS? When I get the code based version of this binding working with tcp transport that includes the supporting token, do you know if wcf will call more than one custom validator if I have one defined for both username and client cert? Or is the way of the custom token and authenticator and validator(s) preferable from a design standpoint in you mind?

    Thanks,

    JF
    Thursday, September 27, 2007 3:12 AM
  • Like Todd said, you would need to add supporting token parameters through the code.

    Parse through the binding elements, grab the securityBindingElement and add X509SecurityTokenParameters as supportingTokenParameters. This way, both the Username and X509Certificate tokens would be sent to the STS.

     

    Yes, WCF will call all the custom validators plugged in.

    Thursday, September 27, 2007 5:46 PM
  • I thooght I was doing this, but I am still not getting a supporting token in the message on the STS side. I probably just ned to carefully examine all my configurations. I am still using the configuration as before, but then both prior to issing the open statement on the STS service, and just after Proxy construction, I have added the following code.

    For the Proxy:

          IList<BindingElement> bindingElements = this.ChannelFactory.Endpoint.Binding.CreateBindingElements();
          foreach (BindingElement element in bindingElements)
          {
            if (element is SymmetricSecurityBindingElement)
            {
              SymmetricSecurityBindingElement symmetricElement = element as SymmetricSecurityBindingElement;
              // Create supporting token parameters for the client X509 certificate.
              X509SecurityTokenParameters clientX509SupportingTokenParameters = new X509SecurityTokenParameters();
              // Specify that the supporting token is passed in message send by the client to the service
              clientX509SupportingTokenParameters.InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient;
              // Turn off derived keys
              clientX509SupportingTokenParameters.RequireDerivedKeys = false;
              symmetricElement.EndpointSupportingTokenParameters.Endorsing.Add(clientX509SupportingTokenParameters);

    For the Service:

            IList<BindingElement> bindingElements = STSHost.Description.Endpoints[0].Binding.CreateBindingElements();
            foreach (BindingElement element in bindingElements)
            {
              if (element is SymmetricSecurityBindingElement)
              {
                SymmetricSecurityBindingElement symmetricElement = element as SymmetricSecurityBindingElement;
                // Create supporting token parameters for the client X509 certificate.
                X509SecurityTokenParameters clientX509SupportingTokenParameters = new X509SecurityTokenParameters();
                // Specify that the supporting token is passed in message send by the client to the service
                clientX509SupportingTokenParameters.InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient;
                // Turn off derived keys
                clientX509SupportingTokenParameters.RequireDerivedKeys = false;
                symmetricElement.EndpointSupportingTokenParameters.Endorsing.Add(clientX509SupportingTokenParameters);
    I only have one endpoint for the service.

    Does this look reasonable? I am still pursuing why I am not gettting a supporting token at the STS.

    Thx,

    JF
    Thursday, September 27, 2007 6:05 PM
  •  

    This looks correct. Are you overriding the endpoint bindings with the modified ones?
    Thursday, September 27, 2007 11:12 PM
  • Ok, I got this resolved in useful way. I am able to use the UserNameForCertificate Authentication mode over tcp transport to send both a client cert and username token for consumption by two custom validators on an STS that then provides an Issued token for access to the service that the client requested. The problem was on the Client Credential side. Initially, I was adding the supporting token to the wrong binding. The client endpoint uses a custom issued token binding that directs the communication process to the STS as the issuer. I needed to extract the STS binding from that custom binding, and add the supporting token there. Once I did that, it worked the way I epxected and wanted. I can use my custom validators without having to create custom credentials / token /Managers / Provider etcc..

     

    Thanks for your help.

     

    JF

     

    Monday, October 1, 2007 4:35 PM