few reads
http://msdn.microsoft.com/en-us/library/ms733098.aspx
http://msdn.microsoft.com/en-us/library/ms751516.aspx
http://stackoverflow.com/questions/1570939/wcf-message-security-without-certificate-and-windows-auth
and create two certificates - for client/server.
Server
ICalculator.cs
using System.ServiceModel;
namespace MySimpleCalculator
{
[ServiceContract]
public interface ICalculator
{
[OperationContract]
int Add(int num1, int num2);
[OperationContract]
string GetCallerIdentity();
}
}
Calculator.svc
<%@ ServiceHost Language="C#" Debug="true" Service="MySimpleCalculator.Calculator" CodeBehind="Calculator.svc.cs" %>
Calculator.svc.cs
using System.ServiceModel;
namespace MySimpleCalculator
{
public class Calculator : ICalculator
{
public int Add(int num1, int num2)
{
return num1 + num2;
}
public string GetCallerIdentity()
{
// The client certificate is not mapped to a Windows identity by default.
// ServiceSecurityContext.PrimaryIdentity is populated based on the information
// in the certificate that the client used to authenticate itself to the service.
return ServiceSecurityContext.Current.PrimaryIdentity.Name;
}
}
}
web.config
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceCredentialsBehavior">
<serviceCredentials>
<serviceCertificate findValue="CN=Server"
x509FindType="FindBySubjectDistinguishedName"/>
<clientCertificate>
<authentication certificateValidationMode="PeerOrChainTrust"
revocationMode="NoCheck" />
</clientCertificate>
</serviceCredentials>
<!-- To avoid disclosing metadata information, set the value below to false
and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- 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="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="MySimpleCalculator.Calculator" behaviorConfiguration="ServiceCredentialsBehavior">
<endpoint contract="MySimpleCalculator.ICalculator" address="/SimpleCalculator"
binding="wsHttpBinding"
bindingConfiguration="MessageUsingCertificate" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="MessageUsingCertificate">
<security mode="Message">
<message clientCredentialType="Certificate"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
------------------------------------------------------------------------
client
class Program
{
static void Main(string[] args)
{
ServiceReference1.CalculatorClient client = new ServiceReference1.CalculatorClient();
Console.WriteLine(client.Add(1, 2));
Console.WriteLine(client.GetCallerIdentity());
Console.ReadLine();
}
}
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_ICalculator">
<security>
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="endpointCredentialsBehavior">
<clientCredentials>
<clientCertificate findValue="CN=client"
storeLocation="LocalMachine"
x509FindType="FindBySubjectDistinguishedName" />
<serviceCertificate>
<authentication revocationMode="NoCheck"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint address="http://localhost:18499/Calculator.svc/SimpleCalculator"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ICalculator"
contract="ServiceReference1.ICalculator" name="WSHttpBinding_ICalculator"
behaviorConfiguration="endpointCredentialsBehavior">
<identity>
<certificate encodedValue="server certificate value" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>
Issues
1. {"The request for security token could not be satisfied because authentication failed."} - It means
Server tries to authenticate Client certificate and its revocation status. So add 'No Revocation'
@ server side for client certificate.
2. SOAP security negotiation with "uri" fails.
The X.509 certificate CN=subject chain building failed. The certificate that was used has
a trust chain that cannot be verified. Replace the certificate or change the
certificateValidationMode. The revocation function was unable to check revocation for
the certificate. - This happens if server certificate is not trusted by client, add no revocation.