I am trying to create a secure webservice.
Here is the contract and service implementation
[ServiceContract()]
public interface ICalculatorService
{
[OperationContract()]
int Add(int x, int y);
}
[ServiceBehavior(IncludeExceptionDetailInFaults=true)]
public class CalculatorService : ICalculatorService
{
public int Add(int x, int y)
{
return x + y;
}
}
Here i have the service code
var b = new WSHttpBinding(SecurityMode.Transport);
b.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
b.Security.Message.ClientCredentialType = MessageCredentialType.None;
Type contractType = typeof(ICalculatorService);
Type implementedContract = typeof(CalculatorService);
Uri baseAddress = new Uri("https://localhost:8006/CalculatorService");
ServiceHost sh = new ServiceHost(implementedContract);
sh.AddServiceEndpoint(contractType, b, baseAddress);
//ServiceMetadataBehavior sm = new ServiceMetadataBehavior();
//sm.HttpsGetEnabled = true;
//sm.HttpsGetUrl = new Uri("https://localhost:8006/CalculatorServiceMex");
//sh.Description.Behaviors.Add(sm);
sh.Credentials.Peer.PeerAuthentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.PeerTrust;
sh.Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.TrustedPeople, X509FindType.FindBySubjectName, "localhost");
sh.Open();
Console.WriteLine("Service is Listening");
Console.ReadLine();
sh.Close();
Here is the client code
var b = new WSHttpBinding(SecurityMode.Transport);
b.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
b.Security.Message.ClientCredentialType = MessageCredentialType.None;
var factory = new ChannelFactory<ICalculatorService>(b);
factory.Credentials.Peer.PeerAuthentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.PeerTrust;
factory.Credentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.TrustedPeople, X509FindType.FindBySubjectName, "localhost");
var client = factory.CreateChannel(new EndpointAddress(new Uri("https://localhost:8006/CalculatorService")));
ServicePointManager.ServerCertificateValidationCallback =
((sender, certificate, chain, sslPolicyErrors) =>
{
return true;
});
ICommunicationObject comObject = client as ICommunicationObject;
int result = -1;
try
{
comObject.Open();
result = client.Add(10, 2);
}
catch (Exception ex)
{
}
Console.WriteLine(string.Format("Service say 10 + 2 = {0}", -1));
Console.ReadLine();
The service runs fine and when the ServicePointManager.ServerCertificateValidationCallback check is made there are no policy errors, with the correct certificate chain built.
I have my CA in the trusted root and the server/client cert in the TrustedPeople store. Also if I navigate to the site from a browser I see a page returned. No errors
I have updated IIS to what I think are the required, bound the certificate in in IIS
and via command line below.
I've set the SSL settings to accept certificates
and enabled anonymous authentication.
Does anyone know what steps I've not done correctly or see anything amiss? I keep getting the same error "The HTTP request was forbidden with client authentication scheme 'Anonymous'."
Another reason for this is the certificate itself on the server you are hitting. Ensure you have imported the PRIVATE KEY. In MMC this will show up with a "Friendly Name". This took me days to figure out. Once I imported the private key the Anonymous error went away and all was well!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With