In this series divided into three-part, I will demonstrate how to use the SoapUI API tool to invoke a secured WCF SOAP service. The first post will focus on creating a service where it will be the system under test. The second post will approach the steps required to invoke it while secured by a basic authentication mechanism. And in the last part, I will make a slight change to the initial service, allowing it to be guarded by the certificate authentication mechanism. In this same post, I will demonstrate how to invoke it using SoapUI as well.
WCF Basic Authentication Service
The access to the resource in the service to be implemented in this post is secured using Basic Authentication transport security mechanisms. One of many provided by the Windows Communication Foundation. This kind of mechanism is used in conjunction with HTTPS to provide confidentiality.
This service exposes one endpoint that calculates a very big sum. To get started quickly we will use the default template of the WCF Service Application provided in Visual Studio 2019.
From Menu File, New, then Project, or click on Start Page to start a new project. Let’s name the solution and the project to AVeryBigSum_BasicAuthentication.
Now you’ll see a couple of files already added to the WCF Service project. We have the option to delete the interface IService1.cs and service Service1.svc file to create new ones. Otherwise, we can rename both files, therefore pay attention to renaming as well as the markup of the Service.svc file, by right click on it -> View Markup and changing to that below.
<%@ ServiceHost Language="C#" Debug="true"
Service="AVeryBigSum_BasicAuthentication.Avbs" CodeBehind="Avbs.svc.cs" %>
After renaming both files, open the IAvbs.cs, copy the following code and add it to the modified interface.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace AVeryBigSum_BasicAuthentication
{
[ServiceContract]
public interface IAvbs
{
[OperationContract]
long AVeryBS(long[] ar);
}
}
In case you chose to delete those files you can add a new interface by right-clicking on the project and Add a new item. Select the Interface template and rename it to IAvbs. As well you need to copy the code above and add it to the newly created interface.
The service implements only one operation defined in the interface contract. To implement it, we need to modify the default file created by VStudio or add a new service class Avbs.svc which will implement the above-defined interface.
using System;
/*...*/
namespace AVeryBigSum_BasicAuthentication
{
public class Avbs : IAvbs
{
public long AVeryBS(long[] ar)
{
long aVeryBigSum = 0;
foreach (long i in ar) aVeryBigSum += i;
return aVeryBigSum;
}
}
}
So far we have defined a service contract, an operation with a sample definition. Now we have to define its endpoints. To add an endpoint, we need to change the configuration file (web.config). Apart from copying and pasting, we need to understand the importance of each of these WCF tags.
1-Secure WCF SOAP using SoapUI – AppSettings
Hence, let’s start with the AppSettings element. This element contains custom application settings. The element stores custom application configuration information, such as database connection strings, file paths, XML Web service URLs, or any other custom configuration information for an application.
We use this element to store the Service´s User and Password credentials. The key/value pairs specified in the element are accessed in code using the ConfigurationSettings library in this way ConfigurationManager.AppSettings[“AVeryBigSum_User”].
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
<add key="AVeryBigSum_User" value="AVeryBigSum"/>
<add key="AVeryBigSum_Pass" value="12345"/>
</appSettings>
Thus, we can change these credentials without the need to rebuild the dynamic link libraries files (DLL) of our project.
Despite the advantage of using the element above, all the magic related to the definition of the service happens in the boundaries of the ServiceModel tag.
2-Secure WCF SOAP using SoapUI – Behaviors
This tag defines the protocol elements consumed by endpoints and services respectively. The service credentials element is essential to define. It specifies the custom validation mode used in the authentication process.
<behaviors>
<serviceBehaviors>
<behavior name="DebugModeBehavior">
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
<!--For UserPass Authentication-->
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="AVeryBigSum_BasicAuthentication.ServiceAuthenticator, AVeryBigSum_BasicAuthentication"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
Inside service credentials, another important property is defined to specify the settings for username and password validation. The userNamePasswordValidationMode property sets how the credential is validated. Our service uses a custom class to validate the credentials. This class AVeryBigSum.ServiceAuthenticator can be found in the AVeryBigSum project.
3-Secure WCF SOAP using SoapUI – Bindings
Each endpoint in a WCF service requires a binding to be well-specified. A binding consists of an ordered stack of binding elements, each of which specifies a part of the communication information required to connect to a service endpoint.
As we can see we are using WSHttpBinding. It represents an interoperable binding that supports distributed transactions, and secure, reliable sessions.
<bindings>
<wsHttpBinding>
<!-- configure wsHttp binding with Transport security mode and clientCredentialType as Certificate -->
<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"/>
<!--For UserPass Authentication-->
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" establishSecurityContext="false"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
WSHttpBinding uses the HTTP transport and provides message security, transactions, reliable messaging, and WS-Addressing, either enabled by default or available through a single control setting.
Inside the WSHttpBinding element, we define the security mode as TransportWithMessageCredential. The transport determines the actual mechanism that provides transport-level security. For HTTP, the mechanism is Secure Sockets Layer (SSL) over HTTP (HTTPS);
4-Secure WCF SOAP using SoapUI – Service
Finally, at the service element, we define endpoints, exposing the service metadata. It is useful to publish metadata like Web services Description Language (WSDL) document that describes all methods and data types employed by a service. It will be used by SoapUi in the next post of this saga, to retrieve and invoke all serviceable endpoints.
<services>
<service behaviorConfiguration="DebugModeBehavior" name="AVeryBigSum_BasicAuthentication.Avbs">
<endpoint address="endpointAVeryBigSum_BasicAuthentication" binding="wsHttpBinding"
bindingConfiguration="wsHttpBinding_LargeBinding" name="EndpointAVeryBigSum_BasicAuthentication"
contract="AVeryBigSum_BasicAuthentication.IAvbs" />
<endpoint address="mex" binding="wsHttpBinding" bindingConfiguration="wsHttpBinding_LargeBinding"
name="mexEndpoint" contract="IMetadataExchange" />
</service>
</services>
5-Secure WCF SOAP using SoapUI – Custom Validator Class
The custom validator extends the UserNamePasswordValidator class and overrides the method Validate. This validator is defined in Service Behaviors as the default Authorization manager, as shown above in the behavior section. This class compares the information received by the client call to those defined in the AppsSetting element.
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IdentityModel.Selectors;
using System.Linq;
using System.ServiceModel;
using System.Web;
namespace AVeryBigSum_BasicAuthentication
{
public class ServiceAuthenticator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password))
throw new SecurityTokenException("Username and password required");
if (!(userName == ConfigurationManager.AppSettings["AVeryBigSum_User"] && password == ConfigurationManager.AppSettings["AVeryBigSum_Pass"]))
throw new FaultException(string.Format("Wrong username ({0}) or password ", userName));
}
}
}
For this class to work properly, we need to add two external libraries to the project. We can do this by right click on the project -> Manage NuGet Packages, and browsing for Microsoft.IdentityModel.Logging and Microsoft.IdentityModel.Tokens packages and add both.
Now that we have defined the endpoint, next, we will host the service in the local development server.
Deploy and Run the service
1 – To host our service in IIS, right-click on the project and go to Properties. In the properties, the window selects the Web tab.
2- Now under Servers on Web settings, you’ll see the following details, change the “IIS Express” to “IIS Server”.
3 – Now Click on Create Virtual Directory with Visual Studio running As Administrator. You’ll get a message The Virtual directory was created successfully! Otherwise, you’ll receive an error message and you need to launch Visual Studio again as Administrator.
Now press F5 and your application will be up and running on the IIS server instead of your IIS Express.
Conclusion
By the end of this demonstration, we have a secure service to be invoked by SoapUI. Our next post will demonstrate step-by-step how to do that.
Also, the sample is accessible from the GitHub repository; to download it, please follow this link.