Recently, I needed to send a message from BizTalk to an external WCF service with Windows Authentication.
For easy testing, I created a Windows console application that will act as the client. I used basicHttpBinding with the security-mode set to TransportCredentialOnly. In the transport-node I chose for Windows as clientCredentialType.
The web.config file looks like this:
<basicHttpBinding>
<binding name=”DemoWebService_Binding” textEncoding=”utf-16″>
<security mode=”TransportCredentialOnly”>
<transport clientCredentialType=”Windows” />
</security>
</binding>
</basicHttpBinding>
Before sending the test message, I needed to authenticate myself and insert the Windows Credentials:
proxy.ClientCredentials.Windows.ClientCredential.Domain = “xxx”;
proxy.ClientCredentials.Windows.ClientCredential.UserName = “xxx”;
proxy.ClientCredentials.Windows.ClientCredential.Password = “xxx”;
This works, so now to get it right in BizTalk!
Problem:
Nothing special, just a Send Port, WCF-Custom with basicHttpBinding as Binding Type and the same binding configuration as in the console application:
I thought I just needed to add the credentials to the Credentials-tab in BizTalk to be able to do proper authentication.
Unfortunately, this does not work!
Apparently, when “Windows” is chosen as clientCredentialType, the Credentials-tab is ignored and the credentials of the Host-Instance running the Send Port are used instead.
Solution:
After some searching, I found the answer thanks to Patrick Wellink’s blog post on the Axon Olympos blog: http://axonolympus.nl/?page_id=186&post_id=1852&cat_id=6.
The credentials of the Host Instance can’t be right, because the web-service is from an external party.
To use the Windows Credentials, a custom Endpoint Behaviour has to be created.
So I’ve created a new Class Library in Visual Studio with a class that inherits from both BehaviorExtensionElement and IEndpointBehavior:
public class WindowsCredentialsBehaviour : BehaviorExtensionElement, IEndpointBehavior
For extensibility, the class needs to have these public properties:
[ConfigurationProperty(“Username”, DefaultValue = “xxx”)]
public string Username
{
get { return (string)base[“Username”]; }
set { base[“Username”] = value; }
}
[ConfigurationProperty(“Password”, DefaultValue = “xxx”)]
public string Password
{
get { return (string)base[“Password”]; }
set { base[“Password”] = value; }
}
[ConfigurationProperty(“Domain”, DefaultValue = “xxx”)]
public string Domain
{
get { return (string)base[“Domain”]; }
set { base[“Domain”] = value; }
}
In the function “AddBindingParameters”, I’ve added this piece of code that sets the Windows Credentials:
public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
if (bindingParameters != null)
{
SecurityCredentialsManager manager = bindingParameters.Find<ClientCredentials>();
var cc = endpoint.Behaviors.Find<ClientCredentials>();
cc.UserName.UserName = this.Domain + @”” + this.Username;
cc.UserName.Password = this.Password;
cc.Windows.ClientCredential.UserName = this.Username;
cc.Windows.ClientCredential.Password = this.Password;
cc.Windows.ClientCredential.Domain = this.Domain;
if (manager == null)
bindingParameters.Add(this);
}
else
{
throw new ArgumentNullException(“bindingParameters cannot be null.”);
}
}
Now after building and putting the assembly in the GAC, we need to let BizTalk know that it can use this custom Endpoint Behavior:
We need to add this line below to the behaviorExtensions (system.serviceModel – extensions) in the machine.config (32-bit and 64-bit):
<add name=”WindowsCredentialsBehaviour” type=”BizTalk.WCF.WindowsCredentials.WindowsCredentialsBehaviour, BizTalk.WCF.WindowsCredentials, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1de22c2808f4ac2e” />
Restart the host instance that runs the send port and you will be able to select the custom EndpointBehavior:
Subscribe to our RSS feed