I've got a WCF enabled Windows service on our server which I'd like to consume. Both server and client should have appropriate certificates in their stores so these certificates can be used to secure the communication.
I'm not very experienced in WCF configuration and it turns out to be a nightmare with lots of different settings and elements, not all of them documented as good as I would have wished.
The relevant part of my current client configuration is as follows (seems that the code formatting doesn't work propertly on my version of IE I have to use, hopefully I'll fix that later at home):
<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="wsHttpBinding">
<security mode="Message">
<message
clientCredentialType="Certificate"
negotiateServiceCredential="false"
algorithmSuite="Default" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="wsHttpCertificateBehavior">
<clientCredentials>
<clientCertificate
findValue="MyCert"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName"/>
<serviceCertificate>
<authentication
certificateValidationMode="PeerOrChainTrust"
revocationMode="NoCheck"
trustedStoreLocation="LocalMachine"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint
address="http://someserver:1234/wcf/service/"
behaviorConfiguration="wsHttpCertificateBehavior"
binding="wsHttpBinding"
contract="SomeNamespace.ISomeInterface"
name="wsHttpEndpoint">
<identity>
<servicePrincipalName value="what to put here?"/>
<certificateReference
findValue="MyCert"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName"/>
</identity>
</endpoint>
</client>
</system.serviceModel>
The server configuration is like this:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true"/>
</system.web>
<system.serviceModel>
<services>
<service
name="Os2CentralWcf.CentralAdUserManager"
behaviorConfiguration="wsHttpCertificateBehavior">
<host>
<baseAddresses>
<add baseAddress="http://someserver:1234/wcf/service/"/>
</baseAddresses>
</host>
<endpoint
address=""
binding="wsHttpBinding"
bindingConfiguration="wsHttpEndpointBinding"
contract="SomeNamespace.ISomeInterface"
name="wsHttpEndpoint">
<identity>
<dns value="MyCert"/>
</identity>
</endpoint>
<endpoint
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange"
name="mexEndpoint"/>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="wsHttpEndpointBinding">
<security mode="Message">
<message
establishSecurityContext="false"
negotiateServiceCredential="false"
clientCredentialType="Certificate"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="wsHttpCertificateBehavior">
<serviceMetadata
httpGetEnabled="true"
httpsGetEnabled="false"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceAuthorization principalPermissionMode="None"/>
<serviceCredentials>
<clientCertificate>
<authentication
certificateValidationMode="PeerOrChainTrust"
revocationMode="NoCheck"/>
</clientCertificate>
<serviceCertificate
findValue="MyCert"
storeLocation="LocalMachine"
x509FindType="FindBySubjectName"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
When not specifying a servicePrincipalName
in the client's configuration, I get the following:
System.ServiceModel.Security.MessageSecurityException: Client cannot determine the Service Principal Name based on the identity in the target address 'http://someserver:1234/wcf/service' for the purpose of SspiNegotiation/Kerberos. The target address identity must be a UPN identity (like acmedomain\alice) or SPN identity (like host/bobs-machine).
When trying to add such an element (e.g. <servicePrincipalName value=HOST/someserver:1234"/>
, as suggested in the post referred to below), I end up with:
System.ServiceModel.Security.SecurityNegotiationException: Secure channel cannot be opened because security negotiation with the remote endpoint has failed. This may be due to absent or incorrectly specified EndpointIdentity in the EndpointAddress used to create the channel. Please verify the EndpointIdentity specified or implied by the EndpointAddress correctly identifies the remote endpoint.
Now my actual question is whether I have to use the identity
sub element at all (the error message seems to indicate this, but I don't understand why). I also couldn't find any detailed documentation about what to put in the dns
element and how to specify a servicePrincipalName (if really needed - this post didn't really help either).
Running both client and server (service) locally within Visual Studio 2010 works fine. I hope I supplied enough information, otherwise please feel free to ask - Unfortunately WCF configuration seems to be quite confusing if you start digging deeper into it...
Update
Using basicHttpBinding at the moment to be able to get both parties to communicate with each other works fine, locally as well as on the server.