WCF svcutil with client certificate

ultraviolet picture ultraviolet · Jul 30, 2012 · Viewed 7.5k times · Source

I've developed a WCF service that uses transport security with a required client certificate. It is hosted on IIS 7.5 and require client certificate is checked. I've setup a mex endpoint and am able to view the wsdl in my browser at https://mydomain.com/Folder/Service.svc/mex?wsdl. Using SoapUI, I am able to successfully connect and the service works perfectly.

However, I want to setup a test client using svcutil.exe because this is what my client will be doing to create their client. But, when I run:

svcutil https://mydomain.com/Folder/Service.svc/mex?wsdl /svcutilConfig:app.config

I get the following error:

C:\Program Files\Microsoft Visual Studio 9.0\VC>svcutil https://mydomain.com/Folder/Service.svc/mex?wsdl /svcutilConfig:app.config
Microsoft (R) Service Model Metadata Tool
[Microsoft (R) Windows (R) Communication Foundation, Version 3.0.4506.2152]
Copyright (c) Microsoft Corporation.  All rights reserved.

Attempting to download metadata from 'https://mydomain.com/Folder/Service.svc/mex?wsdl' using WS-Metadata Exchange or DISCO.
Microsoft (R) Service Model Metadata Tool
[Microsoft (R) Windows (R) Communication Foundation, Version 3.0.4506.2152]
Copyright (c) Microsoft Corporation.  All rights reserved.

Error: Cannot obtain Metadata from https://mydomain.com/Folder/Service.svc/mex?wsdl

If this is a Windows (R) Communication Foundation service to which you have access, please check that you have enabled metadata publishing at the specified address.  For help enabling metadata publishing, please refer to the MSDN documentation at http://go.microsoft.com/fwlink/?LinkId=65455.

WS-Metadata Exchange Error
URI: https://mydomain.com/Folder/Service.svc/mex?wsdl

Metadata contains a reference that cannot be resolved: 'https://mydomain.com/Folder/Service.svc/mex?wsdl'.

The HTTP request was forbidden with client authentication scheme 'Anonymous'.

The remote server returned an error: (403) Forbidden.

HTTP GET Error
URI: https://mydomain.com/Folder/Service.svc/mex?wsdl

There was an error downloading 'https://mydomain.com/Folder/Service.svc/mex?wsdl'.

The request failed with HTTP status 403: Forbidden.

Here is the relevant configuration from my server web.config file:

<system.serviceModel>
<bindings>
  <wsHttpBinding>
    <binding name="MyServices">
      <security mode="Transport">
        <transport clientCredentialType="Certificate"/>
      </security>
    </binding>
  </wsHttpBinding>
</bindings>
<services>
  <service behaviorConfiguration="ServiceBehavior" name="MyService.MyServiceManager">
    <endpoint address="" binding="wsHttpBinding" bindingConfiguration="MyServices"
     name="MyServices" contract="MyService.IMyServiceManager">
      <identity>
        <dns value="mydomain.com" />
      </identity>
    </endpoint>
    <endpoint address="mex" binding="wsHttpBinding"  bindingConfiguration="MyServices"
        name="mexEndpoint" contract="IMetadataExchange"/>
  </service>
</services>
<behaviors>
  <serviceBehaviors>
    <behavior name="ServiceBehavior">
      <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
      <serviceMetadata httpsGetEnabled="true" httpsGetUrl="https://mydomain.com:443/Folder/Service.svc/mex"/>
      <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
      <serviceDebug includeExceptionDetailInFaults="false"/>
      <serviceCredentials>
        <clientCertificate>
          <certificate storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectDistinguishedName" findValue="CN=tempClientcert"/>
        </clientCertificate>
      </serviceCredentials>
    </behavior>
  </serviceBehaviors>
</behaviors>

Here is my client /svcutilConfig:app.config file:

<configuration>
    <system.serviceModel>
        <client>
            <endpoint name="mexEndpoint" address="mex" binding="wsHttpBinding" contract="IMetadataExchange" behaviorConfiguration="MyBehavior" />
        </client>
        <behaviors>
            <endpointBehaviors>
                <behavior name="MyBehavior">
                    <clientCredentials>
                        <clientCertificate storeName="My" storeLocation="LocalMachine" x509FindType="FindBySubjectDistinguishedName" findValue="CN=tempClientcert" />
                    </clientCredentials>
                </behavior>
            </endpointBehaviors>
        </behaviors>
    </system.serviceModel>
</configuration>

I can't figure out why this configuration won't work. Also, all the wsdl imports do resolve to the correct FQDN url and anonymous authentication is enable in IIS.

Any assistance would be appreciated. Thanks a bunch for your help.

Answer

snappieT picture snappieT · Dec 19, 2012

Hit this too. The only thing I can think of is that you're referencing a certificate that can't be found, svcutil doesn't seem to just fail properly in this case. Was that certificate definitely in the right store and had that distinguished name (not just 'regular' subject name)?

In any case, I tacked this problem long enough that I decided to write a blog post about how to do it, it's available here: http://blogs.msdn.com/b/stephens_scratchpad/archive/2012/12/19/client-certificates-for-https-wcf-services.aspx - hope it helps someone!