-->

17/10/2011

WCF - Implementing Message Level Security


Lets start this topic with a comparison between Transport and Message level security.


Transport Level Security
Message Level Security
Scenarios when we should be using one of them
When there are no intermediate systems in between this is the best methodology.  
If it’s an intranet type of solution this is most recommended methodology.
When there are intermediate systems like one more WCF service through which message is routed then message security is the way to go.
Advantages
Does not need any extra coding as protocol inherent security is used.
Performance is better as we can use hardware accelerators to enhance performance.
There is lot of interoperability support and communicating clients do not need to understand WS security as it’s built in the protocol itself.
Does not need any extra coding as protocol inherent security is used.
Performance is better as we can use hardware accelerators to enhance performance.
There is lot of interoperability support and communicating clients do not need to understand WS security as it’s built in the protocol itself.
Disadvantages
As it’s a protocol implemented security so it works only point to point.
As security is dependent on protocol it has limited security support and is bounded to the protocol security limitations.

Needs application refactoring to implement security.
As every message is encrypted and signed there are performance issues.
Does not support interoperability with old ASMX webservices/


So, both Transport and Message level security have their pros and cons.
But, in real time internet scenarios, message level security will be the best pick.

Message Level Security:
Message security uses the WS-Security specification to secure messages. The specification describes enhancements to SOAP messaging to ensure confidentiality, integrity, and authentication at the SOAP message level (instead of the transport level).


In brief, message security differs from transport security by encapsulating the security credentials and claims with every message along with any message protection (signing or encryption). Applying the security directly to the message by modifying its content allows the secured message to be self-containing with respect to the security aspects. This enables some scenarios that are not possible when transport security is used.
 
Lets see how to implement Message level security in WCF.
Step 1 :  As we are dealing with Sample programs, we don't need Thawte, Verisign, GeoTrust etc approved certificates. So let's generate our own.
We need to create both Server and Client certificates.
makecert.exe -sr CurrentUser -ss My -a sha1 -n CN=WCfMsgTestServer -sky exchange -pe
makecert.exe -sr CurrentUser -ss My -a sha1 -n CN=WcfMsgTestClient -sky exchange -pe

In order to do so, you need to install SDK tools from microsoft. If you install , you may find makecert.exe
in "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin".
Now traverse to the path mentioned above in command prompt. Execute above code snippet.
Please note that "WCFMsgTestServer" and "WCFMsgTestClient" are the certificate names i have used.
Step 2: Both the certificates are created but they are not still under trusted category. For that Open Microsoft Management Console. Go to Run --> execute "MMC"
Now console is opened, go to File --> Click on "Add/Remove Snap-in" --> Now select Certificates on left pane and click "Add" button.
Now, certificates were added to console view. There will be different categories of certificates. If you open Personal folder, we can find the certificates we created in earlier steps. Copy them to Trusted People folder.
Close the console.

Step 3: Create a WCF Service (Server) application and change the GetData() method in service definition to set up a custom message.
namespace WCFMsgSecServer
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
    public class Service1 : IService1
    {
        public string GetData(int value)
        {
            return string.Format("Message transfered from server to client using Message Security, You eneterd: {0}", value);
        }

        public CompositeType GetDataUsingDataContract(CompositeType composite)
        {
            if (composite == null)
            {
                throw new ArgumentNullException("composite");
            }
            if (composite.BoolValue)
            {
                composite.StringValue += "Suffix";
            }
            return composite;
        }
    }
}
Step 4: Insert below code snippets in you server config file.
Binding Behavior:
<bindings>
      <wsHttpBinding>
        <binding name="wsHttpEndpointBinding">
          <security>
            <message clientCredentialType="Certificate" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
Service Credentials:
<serviceCredentials>
      <clientCertificate>
         <authentication certificateValidationMode="PeerTrust"/>
      </clientCertificate>
      <serviceCertificate findValue="WCfMsgTestServer"
         storeLocation="CurrentUser"
         storeName="My"
         x509FindType="FindBySubjectName" />
   </serviceCredentials>
Please note that <ServiceCertificate> tag has your server certificate name.
We are all set from server side.

Step 5: Create a client application consuming WCF Service. Add the service reference and i created a test page which will send a number to one of the methods in service. The result will be our custom message that method will be returning.
Below is the UI of my client
Client Code :
namespace WCFMsgSecClient
{
    public partial class ClientTestPage : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {           
        }

        protected void btnSubmit_Click(object sender, EventArgs e)
        {
            try
            {
                Service1Client svc = new Service1Client();
                int PARAM = txtValue.Text == "" ? 0 : Convert.ToInt32(txtValue.Text);
                lblServerMsg.Text = svc.GetData(PARAM);
            }
            catch (Exception ex)
            {
                lblServerMsg.Text = ex.Message;
            }
        }
    }
}
Please note the exception handling which will display if there are any exception messages.

Step 6 : Hit the service. The out put will be:
Oops. We got an error saying "client certificate is not provided". So, the client is unable to decode / break the message level security without presence of Client certificate installed in its trusted pool.
But, we already have everything installed in our system, but haven't configured that in my client code.

Step 7 : Configure client certificate credentials in client code.
Please do the following changes in web.config of client application to associate the Client certificate to the code.
Config change1: Set the endpoint behavior.
<behaviors>
      <endpointBehaviors>
        <behavior name="CustomBehavior">
          <clientCredentials>
            <clientCertificate findValue="WcfMsgTestClient" x509FindType="FindBySubjectName" storeLocation="CurrentUser" storeName="My" />
            <serviceCertificate>
              <authentication certificateValidationMode="PeerTrust"/>
            </serviceCertificate>
          </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>
Config Change 2: Change the endpoint definition by associating the behavior to end point and pointing the identity of end point to server certificate.
<client>
      <endpoint address="http://localhost:39487/Service1.svc" binding="wsHttpBinding"
        bindingConfiguration="WSEndpoint" contract="WCFMsgSecService.IService1"
        name="WSEndpoint" behaviorConfiguration="CustomBehavior">
        <identity>
          <dns value="WcfMsgTestServer"/>
        </identity>
      </endpoint>
    </client>

Step 8: Now verify the client app.
Now the client is able to break Message level security, using client certificate. So, until Admin sent this certificate to the consumer party, they will not be able to consume our service at any cost.

We will discuss in detail about certificates and the logic behind them in upcoming posts.

Happy Coding :)
Code:
Click Here
Is it helpful for you? Kindly let me know your comments / Questions.

11 comments:

  1. nice articles, but could you please provide code samples? thanks

    ReplyDelete
  2. Hi,

    It's really what I am looking for.But I have one question,the implementation of both Message and transport security in same.What is the difference b/w both implementation vise?As in both the case we have to use certificates.

    Thanks for the nice articular..

    Cheers..
    Nishant

    ReplyDelete
  3. Hi pratapReddy,

    This is raja, there is scenario, need to develop the soap based and rest based ,services.

    but need to implement the security for the soapbased only, then how we proceed.

    thanks.

    ReplyDelete
  4. Hi Pratap,
    This is nice article. Am facing issue implementing it.
    I created the certificates and service app as u described. further created client without specifying web.config setting in client app. But in my case running client app -> click of button is not throwing any exception, am getting correct answer.
    I moved ahead adding client config settings. Now it is throwing exception "the caller was not authenticated by the service".

    Kindly Help

    ReplyDelete
    Replies
    1. You can download the code and compare the service configuration and client configuration. I believe the error message is saying that service is expecting different authentication mechanism, which client is providing.

      Delete
    2. Hey,
      The service is running fine after doing following changes
      storeName="TrustedPeople" instead of storeName="My"
      In both client and service :)

      Delete
    3. Hey thanks for nice post but as shoab mentioned its working storeName="TrustedPeople" instead of storeName="My"
      could you please make this change in your post so that it will be easier to understand.

      Delete
  5. nice article,,,easy to understand,,,thanks pratap,,,
    Please share few more on wcf and rest,,,

    ReplyDelete
  6. Nice article but let's assume the client & service are not on same machine. In real scenarios they will be on different machines/internet. So can you please share which certificate will going in which machine/stores.

    ReplyDelete
  7. Hello, what app or code do you use for the images to enlarge the images when the cursor is over?

    ReplyDelete