views:

1275

answers:

4

Hi.

I want to check client certificates in my WCF service.

My goal is to allow only clients with certificates with specific thumbprints to be able to communicate with my service.

My WCF service is hosted in IIS, I'm using basicHttpBinding and security mode="transport" with credential type "Certificate". IIS requires client certificates for communication with the service.

Thanks in advance for help.

UPDATE: My configuration:

<basicHttpBinding>
<binding 
    name="testBinding"
         maxReceivedMessageSize="2147483647">
      <readerQuotas 
     maxDepth="2147483647"
                maxStringContentLength="2147483647"
                maxArrayLength="2147483647"
                maxBytesPerRead="2147483647"
                maxNameTableCharCount="2147483647" />
 <security mode="Transport">
     <transport clientCredentialType="Certificate"/> 
    </security>

</binding>
</basicHttpBinding>

Behavior:

<serviceBehaviors>
    <behavior name="SomeServiceBehavior">
      <serviceMetadata httpsGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="true" />
      <serviceCredentials>
        <clientCertificate>
          <authentication certificateValidationMode="Custom" customCertificateValidatorType="SomeService.CustomCertificateValidator,SomeService"  />
        </clientCertificate>
      </serviceCredentials>         
     </behavior> 
   </serviceBehaviors>

Service configuration:

<service 
         behaviorConfiguration="SomeServiceBehavior"
               name="SomeService">
        <endpoint 
         address=""
                  binding="basicHttpBinding"
                  bindingConfiguration="testBinding"
                  contract="ISomeService">
        </endpoint>
      </service>

And for test purpose I implemented validator in this way:

public class CustomCertificateValidator : X509CertificateValidator
    {
        public override void Validate(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate)
        {                
            throw new SecurityTokenValidationException("TEST Certificate was not issued by a trusted issuer TEST");
        }
    }

And this doesn't work. I can connect to my service with any valid certificate.

+2  A: 

You can create a class derived from X509CertificateValidator and use it to do custom validation of the incoming certificate. Throw an SecurityTokenValidationException if you want to fail validation for some reason.

Set the certificateValidationMode to Custom and specify your validator in the clientCertificate service behavior section of the config file.

How to: Create a Service that Employs a Custom Certificate Validator

Maurice
I tried to add custom validator in clientCertificate but it doesn't work. It seems that it is designed to validate client certificate that the service will be using in duplex mode. I need to validate incoming certificate (certificate the client is sending). Have you tried this option in this scenario?
empi
This can work on either the client or service side and is used to validate the incoming message certificate.
Maurice
Make sure you add this to the <serviceBehaviors> to validate the client in the service which is what you want. The <endpointBehaviors> is used only on the client to validate the service.
Maurice
I've added my configuration. Do you need any more information?
empi
The part of the config you added seems correct. However you didn't add your actual service configuration. so please check if you are actually using "SomeServiceBehavior" with your service. It's happened to me quit a few times that I create a service behavior but forgot to add it to my service.
Maurice
Just noticed you are using transport instead if message level security. For this to work you need to use message level security instead.
Maurice
I've posted my service configuration. I think that behaviorConfiguration is set correctly. What else could be the problem? At first, I tried to configure it on iis http://stackoverflow.com/questions/1559213/wcf-is-it-possible-to-disable-anonymous-access-in-iis-and-have-service-over-htt but it also doesn't work. Is there any other way to access cerificate sent by the client and check it? Or maybe there is something wrong with my configuration/code?
empi
And is it possible to use message level security over https?
empi
You can use TransportWithMessageCredential as the security mode. This uses a combination of HTTPS with message security.
Maurice
When I change it to this value I get: The SSL settings for the service 'None' does not match those of the IIS 'Ssl, SslNegotiateCert, SslRequireCert".
empi
Did you add <message clientCredentialType="Certificate"/> and remove the <transport clientCredentialType="Certificate"/> ?
Maurice
yes, it looks like this:<security mode="TransportWithMessageCredential"> <message clientCredentialType="Certificate" /></security>
empi
In IIS anonymous access is allowed, no other checkboxes are checked in that window. In communication windows require SSL is checked and require client certificates is chosen. Certificate mapping is not checked. I don't know exact names of these fields / windows because it is not english version of iis.
empi
I also cannot find any mex bindings in my configuration that some people point as the reason of the problem.
empi
In IIS you should not have anything checked about the client supplying certificates. The client certificate should be part of the message, if not WCF will not receive the certificate and IIS is doing the client validation.
Maurice
It seems to work! Thank you very much! You were extremely helpful. I'm finishing my work for today, but tomorrow I'll check this solution. Hope it will work as expected. Thanks again.
empi
I've tested this solution today and didn't find any problems with it.
empi
+5  A: 

I do NOT think there is anyway to have 'Custom Certificate Validation' with 'Transport Security'. It only works with 'Message Security'.

http://blog.coditate.com/2009/04/confusing-errors-using-wcf-transport.html

Sharjeel Ahmed
A: 

Hello

I do have the same problems. Even if I did change Transport security mode to

security mode="TransportWithMessageCredential">

custom validation on server side is not triggered ? What can be possible cause ? All other relevant parameters are pretty much the same.

Regards, Gregor

Gregor
Could you please post some more details? IIS configuration, your web.config, etc. Maybe I or someone else will be able to help you.
empi
Btw, if you could post it as a new question and add link to your new question it will be easier to help you.
empi
A: 

YES, you can use basicHttpBinding with security set to Transport and you need to hook to the ServiceHost creation in IIS - see Custom Service Host. You should be able to validate thumbprint values, certificates or any other data if you create custom config section to define list of validation criteria.

Sample code for the implementation of all of the above is available in the code download from this CodeProject artticle.

Emil