{{announcement.body}}
{{announcement.title}}

WCF Transport Security With Certificate Authentication — Test Validation With MSTest V2.

DZone 's Guide to

WCF Transport Security With Certificate Authentication — Test Validation With MSTest V2.

This post demonstrates the use of X.509 certificates for server and client authentication when using WCF transport security.

· Security Zone ·
Free Resource

This post demonstrates the use of X.509 certificates for server and client authentication when using WCF transport security. This security mode is ideal for communication between enterprise applications inside the intranet network.

Our demo creates a service that will implement a simple, repeated string algorithm. In this scenario, the service is hosted under Internet Information Services (IIS), which is configured with Secure Sockets Layer (SSL) and configured with an SSL certificate to allow clients to verify the identity of the server [1].

On the other hand, our client is a parameterized test project that will validate the logic of our service. The client is also configured with an X.509 certificate that allows the service to verify the identity of the client. The server’s certificate must be trusted by the client, and the client’s certificate must be trusted by the server in a request/reply message pattern, as illustrated by the following diagram [1].

Request/reply message patterns [1].

Transfer Security Mode and Message Security Level

WCF offers diverse transfer security modes and message security level to ensure a secured communication between a client and a server. One of those is Transport. It is the easiest way to achieve a secured transfer of message via the use of communication protocols such as TCP, IPC, HTTPS, and MSMQ. This mode is more effective when the transfer is point-to-point and is used mostly in a controlled environment (i.e., intranet applications [8]).

The message security level is not dependent on WCF protocols. It is employed with message data itself by encrypting the data by using a standard algorithm [8]. The certificate message security level, along with message encryption, allows both the client and the service to get authentication with a certificate.

Configuring the Service

Our service defines the repeatedString operation that should return an integer representing the number of occurrences of a in the prefix length of Lili lowercase English letters that were repeated infinitely many times.

Interface

The interface defines RepeatedString as the only method/operation. The operation allows the insertion of two parameters, one of type string, as a string that repeats infinitely many times and an integer, as the number of characters to consider in counting the repeated character. The operation will return an object with the count of the letter a's in the first number letters of the infinite repeated string.

...
namespace RepeatedString
{
    [ServiceContract]
    public interface IRepeatedString
    {
        [OperationContract]
        long RepeatedString(string repeatedString, long number);
    }
}


Implementation

The operation interacts through the repeated string, counting the number of a character occurrence. With performance in mind, we should calculate the factor and the remainder of the repeated string, avoiding interact through all characters.

...
namespace RepeatedString
{
    public class RepeatedString : IRepeatedString
    {
        long IRepeatedString.RepeatedString(string repeatedString, long number)
        {
            long count_repeated_a = 0,  factor = number / repeatedString.Length, remainder = number % repeatedString.Length;

            for (int i = 0; i < repeatedString.Length; i++)
            {
                if (repeatedString[i] == 'a') count_repeated_a += (i < remainder) ? factor + 1 : factor;
            }
            return count_repeated_a;
        }
    }
}


Binding

Since the service in this scenario is hosted under IIS, it is configured with a web.config file. The following web.config shows how to configure the WSHttpBinding to use transport security and X.509 client credentials [1]. To mimic a large binding, we define the timeout connection in sending, receive,as well in openand close attributes. Also, we define the maximum amount of memory allocated in bytes for the buffer manager [2] in maxBufferPoolSize and for a message that can be received on a channel [3] maxRecievedMessageSize. At security tag, we define a transportmode with clientCredentialType="Certificate" highlighted in line 21 of the code.

...
<bindings>
  <wsHttpBinding>
    <binding name="wsHttpBinding_LargeBinding"
      closeTimeout="00:01:00"
      openTimeout="00:01:00"
      receiveTimeout="00:10:00"
      sendTimeout="00:10:00"
      bypassProxyOnLocal="false"
      transactionFlow="false"
      hostNameComparisonMode="StrongWildcard"
      maxBufferPoolSize="250000000"
      maxReceivedMessageSize="250000000"
      messageEncoding="Text"
      textEncoding="utf-8"
      useDefaultWebProxy="true"
      allowCookies="false">
      <readerQuotas maxDepth="2000000" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
      <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
      <security mode="Transport">
        <transport clientCredentialType="Certificate" />
      </security>
    </binding>
  </wsHttpBinding>    
</bindings>
...


Behavior

At service behaviors, we disable includeExceptionDetailInFaults to avoid disclosure of sensitive information.

During development, you may want your service to also send other exceptions back to the client to assist you in debugging. This is a development-only feature and should not be employed in deployed services [4].

...
<behaviors>
  <serviceBehaviors>
    <behavior name="DebugModeBehavior">
      <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="false"/>
    </behavior>
  </serviceBehaviors>
</behaviors>
...


Services

Finally, at the services tag, we define our service, exposing two endpoints. One for metadata exchange<endpoint address="mex"that exposes metadata about the service. It is useful to publish metadata about the service like Web services Description Language (WSDL) document that describes all of the methods and data types employed by a service. Returning metadata about a WCF service allows consumers of service to easily create clients for the service [4].

With the behavior and binding defined posteriorly, we complete the attributes for our main endpoint<endpoint address="endpointRepeatedStringService" binding=
"wsHttpBinding".

...
<services>
  <service behaviorConfiguration="DebugModeBehavior" name="RepeatedString.RepeatedString">
    <endpoint address="endpointRepeatedStringService" binding="wsHttpBinding" name="EndpointRepeatedString" bindingConfiguration="wsHttpBinding_LargeBinding" contract="RepeatedString.IRepeatedString" />
    <endpoint address="mex" binding="wsHttpBinding" bindingConfiguration="wsHttpBinding_LargeBinding" name="mexEndpoint" contract="IMetadataExchange" />
  </service>
</services>
...


MSTest V2 Parameterized Test Client

The new Visual Studio MSTest V2 allows us to use parameters in the tests class. This class could contain multiple test methods, and each method is executed with the different parameters provided. It helps save time when executing the same tests with different inputs and expected results, as described below in[DataRow("ababbaa", 10, 6). The first parameter is a string to be repeated, the second is the number of characters to consider, and the last one is the expected result.

Test class implementation

The test project generates the WSDL document of our service describes as RepeatedStringReference. In the arrange, we instantiate the client object and we actcalling the  client.RepeatedString(repeatedString, number) . To validate, we assert that the expected results have occurred.

...
namespace UnitTest_TransportSecurity_W_CertificateAuth
{
    [TestClass]
    public class RepeatedString_UnitTest
    {
        [DataRow("ababbaa", 10, 6)]
        [DataRow("aaaaa", 123, 123)]
        [DataRow("ccc", 1000000000000, 0)]
        [DataRow("a", 1000000000000, 1000000000000)]
        [DataTestMethod]
        public void RepeatedStringTest(string repeatedString, long number, long expected)
        {
            RepeatedStringReference.RepeatedStringClient client = new RepeatedStringReference.RepeatedStringClient();

            Assert.AreEqual(client.RepeatedString(repeatedString, number), expected);

            client.Close();
        }
    }
}


Client Binding

The client can be configured problematically or in an app.config file. In this config, the client binding does not differ from service configuration binding. Both have the same timeout config as well as other attributes. Another important defined tag is XmlDictionaryReaderQuotasIt contains configurable quota values for XML dictionary readers, which limit the amount of memory utilized by an encoder while creating a message [5].

...
<bindings>
  <wsHttpBinding>
    <binding name="wsHttpBinding_LargeBinding"
      closeTimeout="00:01:00"
      openTimeout="00:01:00"
      receiveTimeout="00:10:00"
      sendTimeout="00:10:00"
      bypassProxyOnLocal="false"
      transactionFlow="false"
      hostNameComparisonMode="StrongWildcard"
      maxBufferPoolSize="250000000"
      maxReceivedMessageSize="250000000"
      messageEncoding="Text"
      textEncoding="utf-8"
      useDefaultWebProxy="true"
      allowCookies="false">
      <readerQuotas maxDepth="2000000" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
      <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
      <security mode="Transport">
        <transport clientCredentialType="Certificate" />
      </security>
    </binding>
  </wsHttpBinding>    
</bindings>
...


Client Behavior

At client behavior, we add a < clientCredentials > element to the < behaviors > element [6]. Bear in mind that it is crucial to set the required name attribute to an appropriate value. We also add a < clientCertificate > element to the < clientCredentials > element — setting these attributes storeLocation, storeName, x509FindType, and findValueto appropriate values certificate information [6].

...
<behaviors>
  <endpointBehaviors>
    <behavior name="endpointCredentialBehavior">
      <clientCredentials>
        <clientCertificate findValue="Certificate Subject Name"
                            storeLocation="CurrentUser"
                            storeName="My"
                            x509FindType="FindBySubjectName" />
      </clientCredentials>
    </behavior>
  </endpointBehaviors>
</behaviors>
...


Client Endpoint

When configuring the client, we should specify the behavior by setting the behaviorConfiguration attribute at the < endpoint > element. The endpoint element is a child of the < client > element. Also, we need to specify the name of the binding configuration by setting thebindingConfiguration attribute to the binding for the client [6].

If we generated the configuration file, the binding's name is automatically generated.

...
<client>
  <endpoint name="EndpointRepeatedString" address="https://localhost/RepeatedString/RepeatedString.svc/endpointRepeatedStringService" behaviorConfiguration="endpointCredentialBehavior" binding="wsHttpBinding" bindingConfiguration="wsHttpBinding_LargeBinding" contract="RepeatedStringReference.IRepeatedString" />
</client>
...


Run a Unit Test and Download the Source Code


Test Explorer

  1. To run the unit test, open Test Explorer by choosing Test > Windows > Test Explorer from the top menu bar [7].

  2. Run your unit tests by clicking Run All.

After the tests have completed, a green checkmark indicates that a test passed. A red x icon indicates that a test failed [7].

The source code is hosted on Git Hub. To download it, please follow this link.

References:

[1] Transport Security with Certificate Authentication

[ 2] WSHttpBindingBase.MaxBufferPoolSize Property

[3] BasicHttpBinding.MaxReceivedMessageSize Property

[4] IMetadataExchange Interface

[5] XmlDictionaryReaderQuotas Class

[6] <behaviors>

[7] Run unit tests with Test Explorer

[8] WCF - Security

Topics:
wcf ,mstest v2 ,x.509 certificates ,soap ,security ,tutorial

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}