Scenario: The adapter needs the client credentials for establishing connection with the target system.  How can a WCF client pass these credentials to the adapter?

Remeber, the WCF-based adapter built using WCF LOB Adapter SDK is surfaced within a WCF Binding.  The Adapter Consumer uses the WCF client programming model to comply with the appropriate security policy supported by the adapter. WCF LOB Adapter SDK uses the standard WCF class Client Credentials to obtain the client credentials that can be authenticated by the Target Application / System.  The Client Credentials class provides properties for many types of credentials – such as client certificates, HTTP Digest, Issued Token Once set by the Adapter Consumer, these credentials can be extracted accordingly in the adapter and passed to the target application for authentication/authorization in the format the target application expects.  In Beta 2, the Adapter SDK has support for the following client credential types – None, Windows, UserName and Certificate.   

The type of credential support can differ per adapter.   

For example, a Firebird database adapter may set the username/password obtained from the Client Credentials in the target database connection string as shown below for a Firebird database.

User=SYSDBA;Password=masterkey;Database=SampleDatabase.fdb;DataSource=localhost;Port=3050;Dialect=3;Charset=NONE;Role=;Connection lifetime=15;Pooling=true;MinPoolSize=0;MaxPoolSize=50;Packet Size=8192;ServerType=0;

 

While an Oracle database adapter may warrant the adapter to set the target Oracle database credentials in the following format.

Driver={Microsoft ODBC for Oracle};Server=myServerAddress;Uid=myUsername;Pwd=myPassword;

 

Note: WCF Security is a massive topic and there are many articles and posts available on the internet for you to gain more knowledge on this topic. 

 

Best Practice for Adapter Developers: Even though the support for the username/password can be added in the Connection Uri, it's recommended to use the WCF security classes to get back-end sysem credentials from the client developer. 

 

Let’s see how the Adapter Consumer can pass credentials to the adapter in both design and runtime scenarios. 

 

Content

1.       Design Time – Using Add Adapter Service Reference Visual Studio Plug-In/Consume Adapter Service BizTalk Project Add-In

2.       Run Time – Using Proxy Programming

3.       Run Time – Using WCF Configuration

4.       Run Time – Using Channel Programming

5.       Run Time – Using BizTalk WCF Adapter

1. Design Time – Using Add Adapter Service Reference Visual Studio Plug-In/Consume Adapter Service BizTalk Project Add-In

Click on Configure button.  The user can select one of the following available client credential types.  The support for each client credential type will vary depending on the type of credentials the adapter supports.  Note: In Beta 2, the Adapter SDK UI cannot discover the client credentials types supported by the adapter, so the Adapter Developer needs to provide the support information to the adapter consumer via other means such as documentation.  Since ASDK doesn’t have this knowledge, he UI doesn’t filter the credentials types for the selected adapter and the consumer may select the types that are not accepted by the adapter.

·         None

·         Windows

·         Username

·         Certificate

 

Once the appropriate credentials are set, go back to the main screen and click on Connect. Underneath, the UI will use the adapter metadata WCF proxy (that uses the IMetadataRetrievalContract contract) to communicate with the adapter.  

2. Run Time – Using Proxy Programming

The WCF generated client proxy has a property for Client Credentials. 

The following code snippet shows how the client proxy can pass the username/password to the adapter.  Following the security best practices, it is not recommended to have the username/password in clear the way I have in the sample below.   The client application can query some SSO source to get the credentials and set them on the proxy.

        static void Main(string[] args)

        {

            HelloWorldClient proxy = new HelloWorldClient("HelloWorldAdapterBinding_HelloWorld");

            // specify username/password credentials

            proxy.ClientCredentials.UserName.UserName = "sonua";

            proxy.ClientCredentials.UserName.Password = "password";

            // invoke method on the proxy

            Console.WriteLine(proxy.SayHelloWorld("Bonjour"));

            // close proxy

            proxy.Close();

        }

If the adapter supports the Windows integrated authentication, this is how the windows impersonation level can be set in the code.

        static void Main(string[] args)

        {

            HelloWorldClient proxy = new HelloWorldClient("HelloWorldAdapterBinding_HelloWorld");

            WindowsClientCredential windowsClientCredential = proxy.ClientCredentials.Windows;

            Console.WriteLine("AllowedImpersonationLevel: {0}", windowsClientCredential.AllowedImpersonationLevel);

            Console.WriteLine("AllowNtlm: {0}", windowsClientCredential.AllowNtlm);

            Console.WriteLine("Domain: {0}", windowsClientCredential.ClientCredential.Domain);

            Console.WriteLine("Username: {0}", windowsClientCredential.ClientCredential.UserName);

            // change the allowed impersonation level to Delegate

            windowsClientCredential.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Delegation;

            proxy.Close();

        }

3. Run Time – Using WCF Configuration

In the client configuration file (app.config or web.config) add an <endpointBehaviours> element  to include the <clientCredentials>.   The complete schema reference for the endpointBehaviors can be found at this MSDN reference.

Use SvcConfigEditor to add an EndpointBehavior with <clientCredentials> extension.  Alternatively you can also browse through the System.ServiceModel.Configuration.ClientCredentialsElement in the Object Browser within Visual Studio to see what sub-elements are needed. 

 

Select File - Save to save to a configuration (.config) file.

Setting client certificate using configuration file

Add <clientCertificate> element within the <clientCredentials> endpoint behavior.

  <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">

      <system.serviceModel>

          <client>

              <endpoint address="hello:/"

                        binding="helloWorldBinding"

                        bindingConfiguration="HelloWorldAdapterBinding"

                        behaviorConfiguration = "clientEndpointCredential"

                        contract="HelloWorld"

                        name="HelloWorldAdapterBinding_HelloWorld" />

          </client>

          <behaviors>

            <endpointBehaviors>

              <behavior name="clientEndpointCredential">

                <clientCredentials>

                  <clientCertificate

                      findValue="Microsoft"

                      storeLocation="CurrentUser"

                      x509FindType="FindBySubjectName"

                      storeName="My" />

                </clientCredentials>

              </behavior>

            </endpointBehaviors>

          </behaviors>       

      </system.serviceModel>

  </configuration>

Setting windows integrated authentication using configuration file

Add the <windows> element within the <clientCredentials> endpoint behavior

  <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">

      <system.serviceModel>

          . . . . .

          <behaviors>

            <endpointBehaviors>

              <behavior name="clientEndpointCredential">

                <clientCredentials>

                  <windows allowNtlm="false" allowedImpersonationLevel="Delegation" />  

                </clientCredentials>

              </behavior>

            </endpointBehaviors>

          </behaviors>

      </system.serviceModel>

  </configuration>

4. Run Time – Using Channel Programming

How does the channel factory know about the client credentials?  Pass a BindingParameterCollection that includes Client Credentials when creating a channel factory. The following code snippet shows how to do that. 

            // instantiate the binding

            HelloWorldAdapterBinding binding = new HelloWorldAdapterBinding();

            // set the custom binding property

            binding.Count = 3;

            // provide client credentials to the channel

            ClientCredentials clientCredentials = new ClientCredentials();

            clientCredentials.UserName.UserName = "sonua";

            clientCredentials.UserName.Password = "password";

            BindingParameterCollection bindingParms = new BindingParameterCollection();

            bindingParms.Add(clientCredentials);

            // Create EndpointAddress

            EndpointAddress address = new EndpointAddress("hello://");

            // create channel factory using channel shape IRequestChannel

            IChannelFactory<IRequestChannel> requestChannelFactory = binding.BuildChannelFactory<IRequestChannel>(bindingParms);

            // open channel factory

            requestChannelFactory.Open();

            ...

Once the channel factory is successfully opened based on the client credentials, continue to create the channel, open the channel and send/receive WCF messages to/from the channel.

5. Run Time – Using BizTalk WCF Adapter

Configure WCF-Custom transport type in the Send Port. 

Setting client certificate and windows settings

Select Behavior tab.  Right-click on EndpointBehavior, click on Add Extension and select clientCredentials endpoint behavior extension.  This should now look very similar to the SvcConfigEditor endpoint behavior interface.  Select the clientCertificate or windows based on your requirements and set the appropriate properties.

Selecting client credential behavior

Adding Client Credentials Endpoint Behavior

 

 

Setting username and password

Select Credentials tab.  Enter the username / password or use SSO.

Note: BizTalk WCF Adapter supports importing and exporting configuration files.  You can choose to configure the WCF-Custom transport type by importing a WCF configuration file that already contains the endpoint behavior or use the Send Port WCF-Custom Transport Properties UI to add the client credential endpoint behavior.   

To Import or Export the configuration, select the Import/Export tab.  The exported configuration (see an example below) should look very similar to setting the application configuration file in other .NET applications as shown in previous sections of this post.

<configuration>

  <system.serviceModel>

    <client>

      <endpoint

              address="hello://"

              behaviorConfiguration="EndpointBehavior"

              binding="helloWorldBinding"

              bindingConfiguration="helloWorldBinding"

              contract="BizTalk"

              name="HelloWorldBinding_SendPort" />

    </client>

    <behaviors>

      <endpointBehaviors>

        <behavior name="EndpointBehavior">

          <clientCredentials>

            <windows allowedImpersonationLevel="Impersonation" />

          </clientCredentials>

        </behavior>

      </endpointBehaviors>

    </behaviors>

  </system.serviceModel>

</configuration>