I am using WCF service with Transport mode. I need to make this service secure using Certificates.
I followed the steps given in the below link and got it working in my local
http://www.codeproject.com/Articles/36683/simple-steps-to-enable-X-certificates-on-WCF
The issues i am facing now are:-
In the above mentioned steps, i had the service running locally as well as my client application that calls the service, running locally. Now for my QA deployment i have the service hosted on one server and my Client application on another server.
I dont have visual studio commant prompt in both these servers to create the certificates using makecert.
My service will be in https.
I will be using some third party to get the certificates for my production, but now i am not able to figure out how to get this working for my QA environment.
I have tried creating a Certificate to Act as Root Certificate Authority and installed it in both the servers. In this approach also i am stuck as to how will i create my client and server certificates under this root authority.
Kindly let me know how can i get this working.
Thanks in advance.
Finally got it working. I had to create certificates using makecert in my local and then had to import them in my QA environment (will be using certificates from a trusted third party for my production environment). My requirement was to make my service secure and not allow unauthorised clients to consume it.
My service web-config.
Changes in the binding
<bindings>
<basicHttpBinding>
<binding name="basicHttpEndpointBinding">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="Certificate" />
</security>
</binding>
</basicHttpBinding>
</bindings
Changes in behavior.
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="ChainTrust" revocationMode="NoCheck" />
</clientCertificate>
</serviceCredentials>
My Client web-config.
Changes in binding
<binding name="">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="Certificate" />
</security>
</binding>
Add behavior
<behaviors>
<endpointBehaviors>
<behavior name="CustomBehavior">
<clientCredentials>
<clientCertificate findValue="RootCATest"
x509FindType="FindByIssuerName"
storeLocation="LocalMachine"
storeName="My"/>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
Attach this behavior to the endpoint
behaviorConfiguration="CustomBehavior"
Related
I'm a beginner with WCF services. Trying to implement a Certificated based authentication on a WCF service and facing an issue. The service expects a specific Certificate from the calling client. The server throws an authentication error if the client is not passing any certificate. But at the same time, the service call is passing authentication with any certificates provided by the client(The service suppose to authenticate if the client provides a specific certificate).
Following is the code snippet of server config :
Service Config :
<bindings>
<wsHttpBinding>
<binding name="MyWsHttpBinding" maxReceivedMessageSize="2147483647" receiveTimeout="00:30:00">
<readerQuotas maxStringContentLength="2147483647" maxBytesPerRead="2147483647" maxDepth="2147483647" maxArrayLength="2147483647"/>
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None"/>
<message clientCredentialType="Certificate" algorithmSuite="Default"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="ChainTrust" />
</clientCertificate>
<serviceCertificate findValue="e616ebcd940951794736624acc6484802018c8d4" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" />
</serviceCredentials>
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="true"/>
<CustomBehaviorExtensionElement/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="MyEndpointBehavior">
<MySchemaValidator validateRequest="True" validateReply="False">
<schemas>
<add location="App_Data\model-service.xsd"/>
</schemas>
</MySchemaValidator>
</behavior>
</endpointBehaviors>
<services>
<service name="MyService" behaviorConfiguration="MyServiceBehavior">
<endpoint binding="wsHttpBinding" bindingConfiguration="MyWsHttpBinding" contract="MyExchangeService" behaviorConfiguration="MyEndpointBehavior" bindingNamespace="http://www.mycompany.com/exchange/"/>
<endpoint contract="IMetadataExchange" binding="mexHttpsBinding" address="mex" name="mex"/>
</service>
</services>
The cause of the problem is the security mode you use is transport, so only the following code works:
<transport clientCredentialType="None" proxyCredentialType="None"/>
The following message settings have no effect:
<message clientCredentialType="Certificate" algorithmSuite="Default"/>
Change the value in transport to certificate, you can also download the wcf demo on the official website, there are examples of related certificate verification, and there are tutorials corresponding to the demo.
I see that the certificate validation mode used in your code is ChainTrust.
<clientCertificate>
<authentication certificateValidationMode="ChainTrust" />
</clientCertificate>
As mentioned in Microsoft Docs, using ChainTrust means -
The certificate is valid if the chain builds to a certification authority in the trusted root store
Meaning, the client need not send certificate with the exact same thumbprint as mentioned in your service web.config. Infact, any certificate whose Root / Intermediate Certification Authority is present in your VM's Trusted Root Store will pass validation.
To make sure that the client is able to use only a specific certificate to authenticate to your service, change ChainTrust to PeerTrust and add the certificate to the trusted people store on your VM's Certificate Store (certmgr).
<authentication certificateValidationMode="PeerTrust" />
References:
MS Docs - Working with certificates in WCF
Authentication element in web.config
More info on Certificate Chain of Trust
I've got a small WCF service in intranet and I need to implement authentication in it. This service communicates with different Java clients over http (uses basicHttpBinding). I've tried to configure binding like so
<basicHttpBinding>
<binding>
<security mode="None">
<message clientCredentialType="UserName"/>
</security>
</binding>
</basicHttpBinding>
And added service behaviour
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="LocalTasks.Services.Validators.IntegrationUserNameValidator,LocalTasks.Services"/>
</serviceCredentials>
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
But calls to this service do not hit my custom UserNamePassword validator.
I've also tried the same variant but with security mode set to Message and added a certificate. In this case validator worked fine.
How to configure service to authenticate users via basicHttpBinding without any message or transport security?
You cannot do that. You need either message or transport security, in order to have the credentials encrypted when they travel from the client to the server.
You really should use Message or Transport security.
You could also use TransportCredentialOnly, which will not require an SSL certificate, but that is recommended for testing only.
<basicHttpBinding>
<binding name="Authentication" >
<security mode="TransportCredentialOnly" >
<message clientCredentialType="UserName"/>
</security>
</binding>
</basicHttpBinding>
If I have an issued SSL certificate from a trusted CA, do I still have to import the SSL certificate to the client machine when connecting to a WCF service over net.tcp?
When I was using wsdualhttpbinding I could simply connect via https. Now I switched to net.tcp and added
<bindings>
<netTcpBinding>
<binding name="InsecureTcp" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="Certificate"/>
</security>
</binding>
</netTcpBinding>
</bindings>
to the web.config file.
I can access the WSDL-file via https but when I try to connect from my client I get the following error:
Additional information: The client certificate is not provided. Specify a client certificate in ClientCredentials.
I have tried to add a custom behavior to the client config file:
<behaviors>
<endpointBehaviors>
<behavior name="CustomBehavior">
<clientCredentials>
<clientCertificate findValue="example.com" x509FindType="FindBySubjectName"
storeLocation="LocalMachine" storeName="My" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
But this only works in combination with importing the certificate to my local cert store...
I hope I get your point - you don't want to use client certificates for authentication? Then modify <security mode="TransportWithMessageCredential">
<message clientCredentialType="Certificate"/>
</security>
the clientCredentialType to one of the following:
http://msdn.microsoft.com/en-us/library/system.servicemodel.httpclientcredentialtype(v=vs.110).aspx
You can use multiple authentication mechanisms, if you want:
http://msdn.microsoft.com/de-de/library/ms731316(v=vs.110).aspx
I want to secure my WCF service using client certificates, i.e. only client certificates from a specific root CA should be allowed to call my service.
For testing purposes I've created a single client certificate without a CA first. I registered the client certificate at the server's certificate store (under current user -> trusted people).
Within VS2013 I've enabled SSL on the WCF service project in order to have an HTTPS endpoint. I've adapted the following Web.config file of the service as follows:
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="PeerTrust"/>
</clientCertificate>
...
</serviceCredentials>
<wsHttpBinding>
<binding name="wsHttpEndpointBinding">
<security mode="Transport">
<transport clientCredentialType="Certificate"/>
</security>
</binding>
</wsHttpBinding>
Furthermore I've adapted the App.config file of my client application as follows:
<clientCredentials>
<clientCertificate findValue="Client" x509FindType="FindBySubjectName" storeLocation="CurrentUser" storeName="TrustedPeople" />
<serviceCertificate>
<authentication certificateValidationMode="PeerTrust"/>
</serviceCertificate>
</clientCredentials>
<wsHttpBinding>
<binding name="WSHttpBinding_IService1">
<security mode="Transport">
<transport clientCredentialType="Certificate"/>
</security>
</binding>
</wsHttpBinding>
However, this does not work, I get the following exception message:
An error occurred while making the HTTP request to https://localhost:44300/Service1.svc. This could be due to the fact that the server certificate is not configured properly with HTTP.SYS in the HTTPS case. This could also be caused by a mismatch of the security binding between the client and the server.
If I switch to message security (instead of transport security) and switch to the HTTP protocol everything seems to work just fine. So I guess I've missed some HTTPS-enabling step?! How to make transport security work?
Your certificate is not configured properly.Follow below steps
Copy the thumbprint of the certificate and run below command from command prompt in elevated mode
netsh http add sslcert [Ipaddress:port] certhash=[thumbprint of certifcate]
appid={unique id for application.you can use GUID for this]
[Ipaddress:port] Ipaddress and port
[thumbprint of certifcate]: thumbprint of certificate without spaces
appid :unique id you can use guid
How to generate GUID from command prompt
Open visual studio command prompt and run below command
c:>uuidgen
I am currently using a netTcpBinding with Windows authentication (program written in C#). I will be moving away from the domain authentication (adding new clients that won't be on the domain) and am looking to set up a certificate security with username/pass authentication. From what I've been reading so far, I don't necessarily need a client certificate (which is good; I won't be able to install the service's certificate on every client). My thinking is the along the same lines as navigating to a secure website with a certificate from a trusted CA; it recognizes it's trusted and doesn't ask any questions or give any hassle, it just accepts the certificate!
So far I have the service certificate set up (we have a wildcard cert from GoDaddy), however I can't figure out what changes I have to make to the app.config file(s) to not require the client certificate.
Service app.config:
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="false" />
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="None" revocationMode="NoCheck" />
</clientCertificate>
<serviceCertificate findValue="*.xxxxxx.com"
storeLocation="LocalMachine"
storeName="TrustedPublisher"
x509FindType="FindBySubjectName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
Client app.config:
<security mode="Transport">
<transport clientCredentialType="Certificate" protectionLevel="EncryptAndSign" />
<message clientCredentialType="UserName" />
</security>
I'm aware I'll have to set up a custom validator for the username portion, but I figure one step at a time. Thanks, and let me know if you need further details.
change clientCredentialType to None. Also do this on the server config.