views:

273

answers:

1

So I've been trying to set up certificate authentication for my clients and services. The eventual goal is to partition data based on the certificate a client connects with (i.e. the certificate becomes their credentials in to the greater system and their data is partitioned based on these credentials).

I have been able to set it up successfully on both the client and the server side. I have created a certificate and a private key, installed them on my computer, and set up my server such that 1) it has a certificate-based service credential and 2) if a client connects without providing a certificate-based credential an exception is thrown.

What I then did was create a simple client and add a certificate credential to the configuration and try to call a simple operation on the service.

It looks like the client connects OK, and it looks like the certificate is accepted by the server, but I do get this:

SecurityNegotiationException:

"The caller was not authenticated by the service."

That seems rather ambiguous to me. Note that I am using wsHttpBinding, which supposedly defaults to Windows auth for transport security...but all of these processes are being run as my user account as I'm running in my debug environment.

Here is my server configuration:

<system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="MyServiceBinding">
          <security mode="Message">
            <transport clientCredentialType="None"/>
            <message clientCredentialType="Certificate"/>
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <services>
      <service behaviorConfiguration="MyServiceBehavior" name="MyService">
        <endpoint binding="wsHttpBinding" bindingConfiguration="MyServiceBinding" contract="IMyContract"/>
        <endpoint binding="mexHttpBinding" address="mex" contract="IMetadataExchange">
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MyServiceBehavior">
          <serviceMetadata httpGetEnabled="true" policyVersion="Policy15" />
          <serviceDebug includeExceptionDetailInFaults="false" />
          <serviceCredentials>
            <serviceCertificate storeLocation="CurrentUser" storeName="My" x509FindType="FindBySubjectName" findValue="tmp123"/>
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>

Here is my client config -- note that I'm using the same cert for the client that I use on the service:

<system.serviceModel>
    <bindings>
        <wsHttpBinding>
            <binding name="WSHttpBinding_IMyService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
                <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
                <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false"/>
                <security mode="Message">
                    <!--<transport clientCredentialType="Windows" proxyCredentialType="None" realm=""/>-->
                    <message clientCredentialType="Certificate" negotiateServiceCredential="true" algorithmSuite="Default"/>
                </security>
            </binding>
        </wsHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://localhost:50120/UserServices.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IMyService" behaviorConfiguration="IMyService_Behavior" contract="UserServices.IUserServices" name="WSHttpBinding_IMyService">
            <identity>
                <certificate encodedValue="Some RSA stuff"/>
            </identity>
        </endpoint>
    </client>
    <behaviors>
      <endpointBehaviors>
        <behavior name="IMyService_Behavior">
          <clientCredentials>
            <clientCertificate storeLocation="CurrentUser" storeName="My" x509FindType="FindBySubjectName" findValue="tmp123"/>
          </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>
</system.serviceModel>

Can anyone please help provide some insight as to what might be up here?

Thanks,

A: 

Can't see anything obvious but check out this link CodePlex: Message Security With Certificates Guide, might see something on there that you're missing. One thing I noticed in the guide there was that the server config identity block gets commented out.

Tanner
Yeah, I tried removing that to no avail -- same issue. I also tried generating a cert for the client and a cert for the service, also to no avail.I'm wondering how the service knows what certs to accept...there is no mapping in the config, it looks like...is it just trusted certs to the user running the service?
Brad Heller