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.