Showing posts with label WCF. Show all posts
Showing posts with label WCF. Show all posts

Monday, October 6, 2014

Migrating from WCF MessageSecurity with custom username/password to TransportSecurity with custom username/password

In performing a migration from WCF MessageSecurity with custom username/password to TransportSecurity with custom username/password, I learned some things the hard way. So they are therefore documented here.

First, TransportSecurity does not support custom username/password. If you try to use TransportSecurity with clientCredentialType="Basic", you get an exception "The HTTP request is unauthorized with client authentication scheme 'Basic'. The authentication header received from the server was..."So you need to use "mixed mode", which is configured like this:
<security mode="TransportWithMessageCredential">
      <message clientCredentialType="UserName"/>
 </security>
Good links to study more on this are here and here.

When doing this migration, if you have been using a test certificate, it might not suit its new use. The test certificate for TransportSecurity should be created with a locally-created CA (Certificate Authority). Also, the name of the certificate (CN/SubjectName) must be the same as the service domain (for example service1.hunterhrms.com), otherwise you get an exception "The remote certificate is invalid according to the validation procedure".
So create your test certificate according to this link. Note that the test certificate does not have to be installed on the client, only the CA.
To complement the data in the above link:

To create the certificates, open a cmd window as administrator and navigate to Microsoft SDK's bin folder.
From there, to create the CA run something like:
> makecert -n "CN=NiloosoftCA" -r -sv NiloosoftCA.pvk NiloosoftCA.cer

To create the test certificate, run something like:
> makecert -sk service1.hunterhrms.com -iv NiloosoftCA.pvk -n "CN=service1.hunterhrms.com" -ic NiloosoftCA.cer -sr localmachine -ss my -sky exchange -pe 
You can write "CN=*.hunterhrms.com" instead of the "CN=..." above, to allow the certificate to be used on all services with the given domain (wildcard certificate). Otherwise, you would need to create a separate test-certificate for each service. 

Service Configuration:
In the service behaviour, no need for the <serviceCertificate> element under <serviceCredentials> - the certificate is set on the IIS site's https binding (just like any https site).

Client-side client endpoint configuration:
I haven't found the <identity> element to be of any meaning.
Also, in the endpoint behaviour, no need for the <serviceCertificate> element under <clientCredentials>. Looks like the client simply checks the server's certificate against an existing Certificate Authority.

The writer is R&D team leader at Niloosoft Hunter HRMS

Sunday, August 26, 2012

Why WCF always gives CommunicationObjectFaultedException?

I have been frustrated regarding WCF - it always seemed to give the same obscure exception:
CommunicationObjectFaultedException - The communication object cannot be used because it is in the Faulted state

Finally I found out why.

Actually WCF usually throws clear exceptions. You just have to use it right.
I have been using WCF proxys with a C# using statement. And here the trouble lies.
What the C# using statement does is this: it wraps up the using block in a try clause, and in the finally clause it disposes the object given in the using clause. In other words, it ensures the object gets disposed even if an exception occured inside the block.
This is very good for working with files, etc. But with WCF it is a problem. Why? because the WCF proxy's Dispose method actually calls the proxy's Close method. But this Close method has a catch: if the proxy is in a Faulted state, Close() throws the infamous exception CommunicationObjectFaultedException.
So what happens is this: you call a method on a service and get an exception. This puts the proxy in a faulted state. Then the using block calls Dispose on the proxy, and the CommunicationObjectFaultedException is thrown.
A WCF proxy in a faulted state still holds some resources. And to dispose of them, you need to call the proxy's Abort method. This method does not throw an exception if the proxy is in a faulted state.

So the recommended pattern to use a WCF proxy is this:

// Create the proxy object here
try
{
     proxy.MyMethod();
}
finally
{
    if (proxy != null)
    {
        if (proxy.State == System.ServiceModel.CommunicationState.Faulted)
        {
            proxy.Abort();
        }
        else
        {
            proxy.Close();
        }
    }
}




The writer is a .Net team leader at Niloosoft Hunter HRMS