Table of Contents
In the article, we will try to apply DUAL security using transport plus message on WCF services. So we will first try to understand the basic concepts of WCF security, i.e., transport and message. Once we understand the concept, we will move step by step into how to implement SSL and user name security on WCF services.
In case you are a complete fresher to WCF, you can start from here.
On a broader basis, WCF supports two kinds of security - transport level and message level security. Transport means the medium on which WCF data travels while message means the actual data packets sent by WCF.
Transport medium can be protocols like TCP, HTTP, MSMQ, etc. These transport mediums by themselves provide security features like HTTP that can have SSL security (HTTPS). WCF has the capability of leveraging underlying transport security features on WCF service calls.
Message level security is provided in the data itself using WS-Security. In other words, it’s independent of the transport protocol. Some examples of message level security are messages encrypted using encryption algorithm, messages encrypted using X509 certificate etc, messages protected using username, etc.
WCF gives you an option to either just use message level security in standalone, transport level in standalone or combination of both. If you are interested in how to do message level security and transport security in a standalone manner, you can read more from here.
The best security is the combination of transport and message. In this article, we will see step by step how to implement dual security using ‘SSL’ plus message security using ‘Username
’ using ‘WsHttpBinding
’.
The first step is to customize your ‘Wshttp
’ binding with proper security mode and credential type. There are three options in security mode ‘Transport
’, ‘Message
’ and ‘TransportWithMessageCredential
’.
As we are implementing dual security, we need to use the last one, i.e., ‘TransportWithMessageCredential
’ where the transport security is provided by SSL and message security is provided using ‘UserName and password’.
The second thing we need to provide is the credential type. There are five different credential types - none, windows, username, certificate and issued token. Credential type defines how the credentials will be passed over the transport layer. For the current instance, we will select ‘UserName
’.
So summing up, we will provide security mode as ‘TransportWithMessageCredential
’ and message security will be provided by ‘UserName
’.
So create a WCF service using the WCF service template and in ‘web.config’ provide the security mode and credential type as shown in the below code snippet:
<bindings>
<wsHttpBinding>
<binding name="Binding1">
<security mode="TransportWithMessageCredential" >
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
Once we have customized the ‘WsHttp
’ binding with security mode and credential type, it’s time to create the custom class which will do authentication of the user name provided.
In order to create your custom class, you need inherit the ‘UserNamePasswordValidator
’ class which belongs to ‘System.IdentityModels.Selector
’.
Below goes the code snippet of ‘MyValidator
’ class. We need to override the ‘Validate
’ method with the authentication logic as shown below:
class MyValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if ((userName == "shiv123") && (password == "pass123"))
{
}
else
{
throw new FaultException("Invalid credentials");
}
}
}
If the credentials are not proper, we have raised the ‘FaultException
’ error which can be caught by the WCF client to display error messages.
So we are almost 50% through now. We have customized the ‘WsHttp
’ binding and created our custom class ‘MyValidator
’ which will do the necessary authentication. The next step is to define behavior.
‘Behaviors
’ define customized run time logic over the binding agreement. Currently we need to execute ‘MyValidator
’ class logic for the ‘UserName
’ provided in the WCF service by WCF client.
To specify the behavior, go to your ‘Web.config’ file and in the ‘servicecredentials
’ tag, specify the ‘userNameAuthentication
’ tag which points to the custom class ‘MyValidator
’.
<behaviors>
<serviceBehaviors>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="MyValidator, app_code"/>
</serviceCredentials>
</behavior>
We have already mentioned transport security will be provided by SSL while message security will be provided by ‘username
’. We have already configured ‘UserName
’ message security using ‘MyValidator
’ class which is specified in the behavior section of ‘web.config’ file. The next step is to configure SSL, i.e., transport security for our WCF service.
We will be using ‘makecert.exe’ which is a free tool given by Microsoft to enable HTTPS for testing purpose. MakeCert (Makecert.exe) is a command-line tool that creates an X.509 certificate that is signed by a system test root key or by another specified key. The certificate binds a certificate name to the public part of the key pair. The certificate is saved to a file, a system certificate store, or both.
You can get the same from “C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\Bin” or you can also get it from Windows SDK.
You can type the below thing through your DOS prompt on “C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\Bin”. Please note “compaq-jzp37md0” is the server name so you need to replace with your PC name.
makecert -r -pe -n "CN= compaq-jzp37md0 " -b 01/01/2000
-e 01/01/2050 -eku 1.3.6.1.5.5.7.3.1 -ss my -sr
localMachine -sky exchange -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12
If you run the same through your command prompt, you should get a succeeded message as shown below:
Now it’s time to assign this certificate to your IIS website. So go to IIS properties, click on directory security tab and you should see server certificate tab.
So click on the server certificate tab and you will then be walked through an IIS certificate wizard. Click ‘Assign an existing certificate’ from the wizard.
You can see a list of certificates. The “compaq-jzp37md0
” certificate is the one which we just created using ‘makecert.exe’.
Now try to test the site without ‘https’ and you will get an error as shown below… That means your certificate is working.
Do not forget to enable IIS anonymous access.
We also need to make a couple of changes in the WCF service ‘Web.config’ ‘endpoint
’ section as shown below. You can see how the address points to HTTPS and binding uses ‘mexHttpsBinding
’.
<service name="Service" behaviorConfiguration="ServiceBehavior">
<endpoint address=https://localhost/Service.svc
binding="wsHttpBinding" contract="IService" bindingConfiguration="Binding1">
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
</service>
It’s time to consume WCF the service application. So click on add service reference and specify your service URL. You will be shown a warning box as shown in the below figure as the certificate is a test certificate. So just let it go.
The next step is to create WCF proxy client object and pass the credentials as shown in the below snippet:
ServicePointManager.ServerCertificateValidationCallback =
new RemoteCertificateValidationCallback(IgnoreCertificateErrorHandler);
ServiceReference1.ServiceClient obj = new ServiceReference1.ServiceClient();
obj.ClientCredentials.UserName.UserName = "shiv123";
obj.ClientCredentials.UserName.Password = "pass123";
Response.Write(obj.GetData(12));
‘makecert.exe’ creates test certificates. In other words, it’s not signed by CA. So we need to suppress those errors in our ASP.NET client consumer. So we have created a function called as ‘IgnoreCertificateErrorHandler
’ which returns true
even if there are errors. This function is attached as a callback to ‘ServicePointManager.ServerCertificateValidationCallback
’ as shown in the above code snippet.
public static bool IgnoreCertificateErrorHandler
(object sender, X509Certificate certificate, X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
return true;
}
If everything goes appropriately, you should be able to run the WCF service. Try changing the use rid and password to something else you should get the fault exception message provided in the ‘MyValidator
’ class.
- WCF FAQ Part 5 – Transactions
- WCF Tracing FAQs
- 8 steps to enable windows authentication on WCF BasicHttpBinding
- Difference between BasicHttpBinding and WsHttpBinding
- 9 simple steps to enable X.509 certificates on WCF
- 7 simple steps to enable HTTPS on WCF WsHttp bindings
- 6 Steps to Enable Transactions in WCF
- WCF FAQ Part 5 – Transactions
- 4 steps to enable instrumentation in WCF
- WCF FAQ Part 3 – 10 security related FAQ
- Windows Communication Foundation FAQ quick starter Part 1
- Windows Communication Foundation FAQ quick starter Part 2
- 20th May, 2010: Initial post
For further reading do watch the below interview preparation videos and step by step video series.