title: WCF service with certificate authentication: "The caller was not authenticated by the service"
body: <p>I'm trying to setup a WCF service with certificate-based authentication, following this guide: <a href="https://msdn.microsoft.com/en-au/library/ff648360.aspx?f=255&amp;MSPPError=-2147217396" rel="nofollow noreferrer">https://msdn.microsoft.com/en-au/library/ff648360.aspx?f=255&amp;MSPPError=-2147217396</a></p>
  
  <p>I've followed all the steps (I think), which in summary are:<br>
  1) Generated a self-signed CA certificate and installed it as a machine-level trusted CA:  </p>
  
  <p><a href="https://i.stack.imgur.com/8GhgB.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/8GhgB.png" alt="enter image description here"></a></p>
  
  <p>2) Generated a certificate for the service (signed by the CA certificate, <code>CN=QvxServiceCert</code>) and installed it at machine-level:</p>
  
  <p><a href="https://i.stack.imgur.com/NyUvF.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/NyUvF.png" alt="enter image description here"></a></p>
  
  <p>3) configured the WCF service endpoint behavior to use the certificate. My service configuration looks like this:  </p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;configuration&gt;
      &lt;startup&gt; 
          &lt;supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" /&gt;
      &lt;/startup&gt;
  
    &lt;system.serviceModel&gt;
      &lt;bindings&gt;
        &lt;wsHttpBinding&gt;
          &lt;binding name="wsHttpEndpointBinding"&gt;
            &lt;security&gt;
              &lt;message clientCredentialType="Certificate" /&gt;
            &lt;/security&gt;
          &lt;/binding&gt;
        &lt;/wsHttpBinding&gt;
      &lt;/bindings&gt;
      &lt;behaviors&gt;
        &lt;serviceBehaviors&gt;
          &lt;behavior name="QvxServiceBehavior"&gt;
            &lt;serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" /&gt;
            &lt;serviceDebug includeExceptionDetailInFaults="true" /&gt;
            &lt;serviceCredentials&gt;
              &lt;serviceCertificate findValue="CN=QvxServiceCert" /&gt;
            &lt;/serviceCredentials&gt;
          &lt;/behavior&gt;
        &lt;/serviceBehaviors&gt;
      &lt;/behaviors&gt;
      &lt;services&gt;
        &lt;service name="esqQvxScheduler.Service.QvxSchedulerAPI" behaviorConfiguration="QvxServiceBehavior"&gt;
          &lt;endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding"
            name="wsHttpEndpoint" bindingName="" contract="esqQvxScheduler.Service.IQvxSchedulerAPI" /&gt;
          &lt;endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /&gt;
          &lt;host&gt;
            &lt;baseAddresses&gt;
              &lt;add baseAddress="http://localhost:8733/QvxSchedulerAPI/" /&gt;
            &lt;/baseAddresses&gt;
          &lt;/host&gt;
        &lt;/service&gt;
      &lt;/services&gt;
    &lt;/system.serviceModel&gt;
  &lt;/configuration&gt;
  </code></pre>
  
  <p>4) Generated a certificate for the client (again, signed by the CA certificate, this one has <code>CN=QvxClientCert</code>) and installed at user-level:</p>
  
  <p><a href="https://i.stack.imgur.com/1hW5F.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/1hW5F.png" alt="enter image description here"></a></p>
  
  <p>5) configured the WCF client behavior to use it for authentication. This is my client config:</p>
  
  <pre><code>    &lt;?xml version="1.0" encoding="utf-8" ?&gt;
  &lt;configuration&gt;
      &lt;startup&gt; 
          &lt;supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /&gt;
      &lt;/startup&gt;
      &lt;system.serviceModel&gt;
          &lt;behaviors&gt;
              &lt;endpointBehaviors&gt;
                  &lt;behavior name="qvxClientBehavior"&gt;
                      &lt;clientCredentials&gt;
                          &lt;clientCertificate findValue="CN=QvxClientCert" /&gt;
                      &lt;/clientCredentials&gt;
                  &lt;/behavior&gt;
              &lt;/endpointBehaviors&gt;
          &lt;/behaviors&gt;
          &lt;bindings&gt;
              &lt;wsHttpBinding&gt;
                  &lt;binding name="wsHttpEndpoint"&gt;
                      &lt;security&gt;
                          &lt;message clientCredentialType="Certificate" /&gt;
                      &lt;/security&gt;
                  &lt;/binding&gt;
              &lt;/wsHttpBinding&gt;
          &lt;/bindings&gt;
          &lt;client&gt;
              &lt;endpoint address="http://localhost:8733/QvxSchedulerAPI/" binding="wsHttpBinding" behaviorConfiguration="qvxClientBehavior"
                  bindingConfiguration="wsHttpEndpoint" contract="QvxSchedulerAPI.IQvxSchedulerAPI"
                  name="wsHttpEndpoint"&gt;
                  &lt;identity&gt;
                      &lt;certificate encodedValue="[A LONG AUTOGENERATED STRING THE MEANING OF WHICH I HAVE NO IDEA]" /&gt;
                  &lt;/identity&gt;
              &lt;/endpoint&gt;
          &lt;/client&gt;
      &lt;/system.serviceModel&gt;
  &lt;/configuration&gt;
  </code></pre>
  
  <p>6) Gave the user that runs the client access to the certificate, by issuing the following on the command line: <code>cacls "C:\Users\MyUsername\AppData\Roaming\Microsoft\Crypto\RSA\S-1-5-21-742627442-1779984360-2302642487-1000" /E /G "MyUser-PC\MyUsername":R</code></p>
  
  <p>This was all done following the guide, without any issue that I could see. Everything seems ok... but when I try to invoke the service from my client, all I get this frustratingly vague and unhelpful exception:</p>
  
  <pre><code>Unhandled Exception: System.ServiceModel.Security.SecurityNegotiationException: The caller was not authenticated by the service. ---&gt; System.ServiceModel.FaultException: The request for security token could not be satisfied because authentication failed.
     at System.ServiceModel.Security.SecurityUtils.ThrowIfNegotiationFault(Message message, EndpointAddress target)
     at System.ServiceModel.Security.SspiNegotiationTokenProvider.GetNextOutgoingMessageBody(Message incomingMessage, SspiNegotiationTokenProviderState sspiState)
     --- End of inner exception stack trace ---
  
  Server stack trace:
     at System.ServiceModel.Security.IssuanceTokenProviderBase`1.DoNegotiation(TimeSpan timeout)
     at System.ServiceModel.Security.SspiNegotiationTokenProvider.OnOpen(TimeSpan timeout)
     at System.ServiceModel.Security.TlsnegoTokenProvider.OnOpen(TimeSpan timeout)
     at System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout)
     at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
     at System.ServiceModel.Security.CommunicationObjectSecurityTokenProvider.Open(TimeSpan timeout)
     at System.ServiceModel.Security.SymmetricSecurityProtocol.OnOpen(TimeSpan timeout)
     at System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout)
     at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
     at System.ServiceModel.Channels.SecurityChannelFactory`1.ClientSecurityChannel`1.OnOpen(TimeSpan timeout)
     at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
     at System.ServiceModel.Security.SecuritySessionSecurityTokenProvider.DoOperation(SecuritySessionOperation operation, EndpointAddress target, Uri via, SecurityToken currentToken, TimeSpan timeout)
     at System.ServiceModel.Security.SecuritySessionSecurityTokenProvider.GetTokenCore(TimeSpan timeout)
     at System.IdentityModel.Selectors.SecurityTokenProvider.GetToken(TimeSpan timeout)
     at System.ServiceModel.Security.SecuritySessionClientSettings`1.ClientSecuritySessionChannel.OnOpen(TimeSpan timeout)
     at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
     at System.ServiceModel.Channels.ServiceChannel.OnOpen(TimeSpan timeout)
     at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
     at System.ServiceModel.Channels.ServiceChannel.CallOpenOnce.System.ServiceModel.Channels.ServiceChannel.ICallOnce.Call(ServiceChannel channel, TimeSpan timeout)
     at System.ServiceModel.Channels.ServiceChannel.CallOnceManager.CallOnce(TimeSpan timeout, CallOnceManager cascade)
     at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
     at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
     at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
  </code></pre>