Authenticated messaging is one limitation in WF 4 as currently there is no API for setting up credentials to be used with a Send activity. Having said that, ChannelFactory used by Send activity still picks up the behaviour configuration from the config file.

So you can potentially write a custom behaviour to supply additional credentials to the Send activity. Let’s see a simple clientCredentialsAdapter behaviour which will enable you to setup userName/Password in config file. It’s almost always a bad idea to keep unencrypted password in config files so it is recommended that you should use config encryption to encrypt the behaviour section.

<behavior name="credentialAdapter">

  <clientCredentials> 

    <serviceCertificate>

      <authentication certificateValidationMode="None"/>

      <defaultCertificate findValue="f7ad5a9dcc35f21ffc691925515f48eb44f5e07a" x509FindType="FindByThumbprint" storeLocation="CurrentUser" storeName="My"/>

    </serviceCertificate>

  </clientCredentials>

 

  <clientCredentialsAdapter>

    <userName userName="configUser" password="p@ssw0rd!"/>

  </clientCredentialsAdapter>

</behavior>

At this point, you can configure this behaviour on an endpoint used by a Send activity. This change will enable Send activity to use this userName/Password for securing outgoing messages.

public class ClientCredentialsAdapterBehavior : IEndpointBehavior

{

    ClientCredentialsAdapterBehaviorElement configElement;

 

    public ClientCredentialsAdapterBehavior(ClientCredentialsAdapterBehaviorElement configElement)

    {

        this.configElement = configElement;

    }

 

    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters){}

 

    public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)

    {

        var clientCredentials = endpoint.Behaviors.Find<ClientCredentials>();

        Adapt(clientCredentials);

    }

 

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { }

 

    public void Validate(ServiceEndpoint endpoint){}

 

    void Adapt(ClientCredentials orignalCredentials)

    {

        orignalCredentials.UserName.UserName = configElement.UserName.UserName;

        orignalCredentials.UserName.Password = configElement.UserName.Password;

    }

}

So that was simpleJ What about a scenario where you have userName/Password as part of workflow state and you want to use that instead?

Well, in that case there is more work involved which I’ll discuss in next post.