2
votes

I'm trying to understand WCF and all of it's (complex) security options. I have developed a Wcf webservice with wsHttpBinding on localhost. I'm creating a Console Application that I will distribute to a few clients. Each client has it's own username and password which I will validate against my own database. To do so, I've followed the following tutorial on codebetter.com: http://codebetter.com/petervanooijen/2010/03/22/a-simple-wcf-service-with-username-password-authentication-the-things-they-don-t-tell-you/

  • I got the selfsigned certificate, and granted permissions
  • I got the server & client all setup and running perfectly on localhost to localhost.

Question 1:

I added the svc service using VS2010 Add Service dialog and it added the folowing tag to my app.config:

<certificate encodedValue="AwA<...>" />

For learning purposes, I changed that value a couple of times, but it did not had any effect. It kept working perfectly. I use Fiddler to see the encrypted communication.

Question 2: Deploy on Test server with SSL

I've deployed the Webapplication, hosting WCF service, on a Test server with IIS7.5 and SSL configured. When I tried the client application to connect to the test-server, it threw a generic error. I discovered that when I changed from https:// to http:// it worked. Fiddler showed nice http communication with encrypted values.

But I also want to use HTTPS, together with my message-level encryption. I think this is not possible. I got it all working, just set the Security Mode to "TransportWithMessageCredential" and it's done. But when I do that, I can remove all certificate info on the client, and it still works. Therefore I can make the conclusion that Transport security (kind of) overrules the Message security.

So am I making the right conclusion:

  • Don't got https Transport security? Use certificates (pfx on server, cert on the clients)
  • Got https Transport security? Don't use the certificates, SSL is enough.

I hope I make myself clear :). Many thanks in advance.

Below a few (anonymized) configs:

Server

<bindings>
  <wsHttpBinding>
    <!--The maximum size, in bytes, for a message that is processed by the binding-->
    <binding name="Binding1" maxReceivedMessageSize="4194304">
      <readerQuotas maxDepth="32" maxStringContentLength="10485760" maxArrayLength="10485760"
        maxBytesPerRead="10485760" maxNameTableCharCount="10485760" />
      <security mode="TransportWithMessageCredential">
        <message clientCredentialType="UserName" negotiateServiceCredential="false" />
      </security>
    </binding>
  </wsHttpBinding>
</bindings>
<behaviors>
  <serviceBehaviors>
    <behavior name="ApiWcfCustomBehavior">
      <serviceMetadata httpGetEnabled="true"/>
      <serviceCredentials>
        <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="CustomUserNameValidator, SupplierAPI"/>
        <serviceCertificate findValue="xxxxApiv3" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName"/>
      </serviceCredentials>
    </behavior>
  </serviceBehaviors>
</behaviors>

* Client *

var endPoint = new EndpointAddress(new Uri(apiUrl), EndpointIdentity.CreateDnsIdentity(endpointDnsEntity));

var binding = new WSHttpBinding();
//binding.Security.Mode = SecurityMode.TransportWithMessageCredential;
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
binding.Security.Message.NegotiateServiceCredential = false;

using (var client = new SupplierServiceClient(binding, endPoint))
{
    client.ClientCredentials.UserName.UserName = supplierUID;
    client.ClientCredentials.UserName.Password = supplierPassword;

    client.ClientCredentials.ServiceCertificate.SetDefaultCertificate(
         System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine,
         System.Security.Cryptography.X509Certificates.StoreName.My,
         System.Security.Cryptography.X509Certificates.X509FindType.FindBySubjectName,
         endpointDnsEntity);
 }
1
re: question 1 - you change that certificate value in your config, and still see the data as encrypted... is that over HTTPS?Mark B
@MarkB, thanks for your comment. No it isn't over HTTPS. When using Fiddler and HTTPS, I only see one result, not readable (ssl). This test I did, I was normal HTTP and I could see a few http-request, with in the bodies encrypted data. Changing the client value, did not do anything.JonHendrix
@MarkB Offcourse I started to doubt and did my tests again. Setup was as follows: Laptop (no certificates preinstalled) with a new Console App in VS2012. Added WCF service reference from the test-server (non-https). Identity/certificate@encodedValue is added to the app.config. Did few tests, worked perfect. Changing the encodedValue (replacing some characters) didn't do anything. Only completely removing the Identity tag made the console app throw an error.JonHendrix
@Tweek In my experience it had effect after changing the 6th character.riezebosch

1 Answers

0
votes

I'm trying to do something similar right now (SSL, Message encryption, username/password authentication), and I'm also starting to think it's not possible, at least not without some hacking that I don't know about. If I understand this post correctly, when your client machine connects directly to your service machine over SSL you'll have a point-to-point connection meaning it's secured via SSL, and the authentication (username/password values) are secured with WS-Security.

An interesting analogy used in that post is online banking over SSL. Since the client and Server have a point-to-point connection, you'll have a secure channel.

this is just what I've found, so if someone thinks it's incorrect please let me know.