WCF with SSL hosted by iis 7.5 or consolehost - wcf

this is a very straightforward and easy question.
So please give me an easy answer(tutorial would be good)..
And not a very difficult expert anwswer(what I all the time find on google..)
So the question is:
1. How do you create a simple webservice that will be hosted by iis 7.5 and has SSL
How do you create a simple webservice that will be hosted by console and has SSL
If you create a client that use a SSL wcf host then you first need to select Yes or No, how can the computer automatically select YES?

To configure IIS hosted WCF service work with SSL you need:
1. Install Certificate
2. Set SSL is required in your application settings in inetmgr.
3. Configure security in WCF service settings. Here is an example of security settings of WCF service
...
<service behaviorConfiguration="YourServiceBehavior" name="...">
...
<behaviors>
<serviceBehaviors>
<behavior name="YourServiceBehavior">
...
<serviceCredentials>
<serviceCertificate findValue="CerttificateName" storeLocation="CertificateStoreLocation"
storeName="CertificateStoreName" x509FindType="FindBySubjectName" />
</serviceCredentials>
...
</behavior>
</serviceBehaviors>
</behaviors>
...
<bindings>
<basicHttpBinding>
<binding name="YourBindingName" ...>
...
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Basic" proxyCredentialType="None"/>
<message clientCredentialType="UserName"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
...
I don't have an answer for you about console hosted WCF service and SSL.
Also I'm not sure what do you mean when asking how can the computer automatically select yes. It seems you are talking about accept using of certificate considered as not valid. Line of code below should help to do that.
ServicePointManager.ServerCertificateValidationCallback = delegate(object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; };

Related

Issue with WCF Transport Security SSL

I have a set of WCF Services on one server that is being called from my website on another server. Without any security and just basicHttpBinding, this works just fine. Now I want to completely secure the same setup using SSL Transport with a self-signed certificate.
First I tried to use IIS on the Services Server to create a self-signed certificate, but the issue is that it is always creating the cert with the subject in mixed case but the url is lower case. Not sure if that will cause an issue, but I didn't succeed with it.
So I used makecert to (1) create a root cert that I then installed the *.cer file on the client server and service server into the Root CA stores and then (2) created another cert, using the root as the CA, that will be used for signing. I copied this one *.pfx and installed into the Personal store of the LocalComputer for both servers again.
So, now on my Services server, I went into IIS and setup the binding for 443 using the client cert. Then I selected my virtual directory and setup SSL requiring SSL and then selecting 'Required' for Client Certificates.
Now, if I just try to bring up the virtual directory in IE, using https and the full name as it shows in the cert, I get 403.7. I can't seem to get passed this error.
If I try to hit this virtual directory from the website server, I get a plain 403.
If I change my IIS setup to 'Accept' client certs instead of 'Require', the I can browse to my services on both boxes.
Somethings missing...but can't seem to find it.
Update:
Ok, so I created a one-page website and locked it down Requiring the same cert and was able to install that cert into IE on a client and hit the website. Finally, after installing the cert into IT, it allowed me to browse my Services virtual directory and even bring up the page on one of my services.
Question 1: When installing the server cert, I installed the private key version on both Server and Client machine into the LocalMachine -> Personal location. Is this correct or should I just install the public key into the client? It seems to be working.
Still problem - when making a WCF call now I'm getting the following:
SecurityNegotiationException: Could not establish secure channel for SSL/TLS with authority 'myserver.mydomain.com'.
Here's my server configuration:
<system.serviceModel>
<protocolMapping>
<add scheme="https" binding="basicHttpBinding"/>
</protocolMapping>
<bindings>
<basicHttpBinding>
<binding name="SecureCertBinding">
<security mode="Transport">
<transport clientCredentialType="Certificate"></transport>
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="MyName.MyService" behaviorConfiguration="SecureBehavior">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="SecureCertBinding" name="SecureAlertService" contract="MyName.IMyService"></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="SecureBehavior">
<serviceMetadata httpsGetEnabled="true" />
<serviceCredentials>
<serviceCertificate findValue="myserver.mydomain.com" storeName="My" storeLocation="LocalMachine" x509FindType="FindBySubjectName"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Here's my client configuration:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_SmallData" maxReceivedMessageSize="5000000">
<readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="524288" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="Transport">
<transport clientCredentialType="Certificate"></transport>
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="SecureEndpoint">
<clientCredentials>
<clientCertificate findValue="myserver.mydomain.com" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName"/>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint address="https://myserver.mydomain.com/Services/MyService.svc" binding="basicHttpBinding" behaviorConfiguration="SecureEndpoint"
bindingConfiguration="BasicHttpBinding_SmallData" contract="MyName.IMyService" name="BasicHttpBinding_IMyService"/>
</client>
</system.serviceModel>
How can I tell if the client is sending the certificate with the request?
Got it!! Finally.
I restarted the whole process, including creating new certs and all. Once I got passed the part where IE couldn't even navigate to the Services Virtual Directory, I knew from that point I was mainly up against WCF.
I use a service account on my Services Server for the application pool that has proper authority to the database. This way my connection strings are Windows Auth.
Make sure this service account has Full Permissions to the Cert (Snap-in...Manage Private Keys).
After doing this, I was still getting an error but I found an entry in my System Event Logs that stated an error occurred when trying to retrieve the private key from a cert. This finally helped.
My website (aka...Services client) is still running the application pool with ApplicationPoolIdentity. If this is the case:
Make sure to give the group 'IIS_Usrs' Full Permissions to the Cert.
Bingo...everything worked from this point forward...complete security.

Configuring WCF Transport security for IIS6 over SSL

I've been attempting to set up WCF transport security using SSL on IIS6.
The client is on a seperate machine on the same domain.
I understand the premise of certificates, root CA etc and have a working set of certs for message security and can use these no probs in the same enviroment set up. (i've learn't a lot over the last week :)
I'm having an nightmare trying to get my client to authenticate against the IIS 6 service when i switch it to SSL. Always recieving 'annonymous authetication not allowed' when calling.
IN IIS i have
a root signed CA cert set on the site for SSL port 443
(if i browse the https:// svc page i can see the IE padlock and the page says you need a cert to communicate)
under secure communications i have
require SSL channel
require 128 bit encryption
require client certificates
enable client certificate mapping (set up with a many to 1 mapping to a admin account on the IIS box for now matched on the cert subject O field )
under web site security (authentication and access control)
Anonymous access = ON
Intergrated Windows Authentication = OFF
basic Authentication = ON
For the client wsHttpBinding i have a certificate ready to authenticate and a custom endpoint behaviour to supply this info but i don't think its getting this far!
UPDATED SERVER CONFIG
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="CertificateWithTransport">
<security mode="Transport">
<transport clientCredentialType="Certificate"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="WCFServiceCertificate.Service1" behaviorConfiguration="credentialConfig">
<endpoint address="https://svnvmig02/Service1.svc"
binding="wsHttpBinding"
bindingConfiguration="CertificateWithTransport"
contract="WCFServiceCertificate.IService1">
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="credentialConfig">
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="false"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
UPDATED CLIENT CONFIG
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IService1">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://svnvmig02/Service1.svc" binding="wsHttpBinding" behaviorConfiguration="CustomBehavior"
bindingConfiguration="WSHttpBinding_IService1" contract="ServiceReference1.IService1"
name="WSHttpBinding_IService1">
</endpoint>
</client>
<behaviors>
<endpointBehaviors>
<behavior name="CustomBehavior">
<clientCredentials>
<clientCertificate findValue="svnvmig02" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My"/>
<serviceCertificate>
<authentication certificateValidationMode="PeerTrust"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
EDIT:
Probably worth mentioning that my VS projects are 3.5 but IIS6 is running .net4
With the amended config (thanks Fabio ;) i can now IE browse the address https://svnvmig01/Service1.svc from the client machine and see the generated svc page which allows me to click on the wsdl URl which is also available.
The majority of the pages i have found on the net refer to selfhosting or IIS7....I'm hoping IIS7 support is better ;)
Any help would be greatly appreciated :)
Your config includes:
https://svnvmig02:8091/Service1.svc
The normal port for ssl is 443.
It may be that the request is not going to the site that you expect it to go to. Therefore, you are getting and unexpected error message.
Check the IIS logs to make sure which site is receiving the request.
I think your issue here may be that you have IIS set to:
Anonymous access = OFF
I use transport security on several of my servers, and all the IIS6 ones have that setting ON, not OFF. This also corresponds to the error message you provided:
'annonymous authetication not allowed'
Without anon access off, IIS will either want the user to enter a username/password, or pass along a windows / active directory / kerberos credentials.

WCF - SSL Service

I have a service that uses SSL. When I try to browse to the service I get the following error:
The SSL settings for the service 'SslRequireCert' does not match those of the IIS 'None'.
My config is as follows:
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
I am using IIS Express and I have "Enable SSL" checked (verified in WebMatrix).
Any ideas what else I need to do?
Ok. It looks like I needed to update the applicationhost.config file (in IIS Express). I added a location for my site and set sslFlags="Ssl, SslAcceptCert, SslRequireCert". This allowed me to enable SSL authentication. Then when I tried to access the service with a client I got a message that there was an error establishing a trust relationship. This was because I did not have the server's certificate in my trusted people folder (or it might have been the client, I'm not sure as the service and client is on my local PC). After doing that, the service will work, however we do not want to have to give our certificate to the client, so I ended up using the TransportWithMessageCredential security mode.
Modify your behaviour to include SSL as below;
<behaviors>
<serviceBehaviors>
<behavior name="MyService">
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True" />
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
and remove
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
This is implying that you will be using certificate authentication
This has absolutely nothing to do with the absence of the mex line, unless it's configured incorrectly in which case removing it will have an effect but IIS still might give the same error.
Make sure IIS has SSL Settings of 'Require SSL' and 'Accept' (easier) or 'Require' user certificates - then RESTART IIS. Although IIS says changes are applied - im my experience they are not always - or at least not done immediately.

WCF Service (wsHttpBinding binding) behind F5 load balancer

current setup:
- i have got a WCF service with wsHttpBding, see the service config below
- i have implemented a ServiceHostFactory to solve the problem of incorrect schema location and soap addresses, modifying them from machine name to the correct server hostname
- my test client (WCFStorm) i can generate a proxy, see all the methods and invoke them successfully.
- my dev environment (client-> HTTPS -> service) works perfectly.
problems:
- prod environment (client -> HTTPS -> F5 -> HTTP -> service)
- my service is behind F5 load balancer which offloads SSL
- my test client (WCFStorm) i can generate a proxy and see all the methods but when i invoke any of the methods i get a remote server not found 404 error
my service config:
<services>
<service behaviorConfiguration="Service1Behavior"
name="MyService">
<endpoint name="secure" address="" binding="wsHttpBinding" bindingConfiguration="custBinding" contract="IService"/>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="custBinding">
<security mode="Transport">
<transport clientCredentialType="None" />
<message clientCredentialType="None" negotiateServiceCredential="false"
establishSecurityContext="false" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="Service1Behavior">
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="true" httpGetUrl="http://myserver/MyService.svc"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<dataContractSerializer maxItemsInObjectGraph="6553600" />
</behavior>
</serviceBehaviors>
</behaviors>
please note that all my schema locations and soap addresses on the wsdl are correct in prod, but i simply cannot invoke any methods.
please help.
We have a similar situation and here's how we got it working.
in the service - we changed the binding to use basicHttpBinding and added a key that must be passed with every request.
in the client - we changed the http in the config to https and in the basicHttpBindings config changed the security mode to Transport with clientCredentialType="None".
Hope this helps.
UPDATE: I found this article soon after and I updated the configuration and it worked. So now we are using wsHttpBinding instead of basicHttpBinding.
http://blogs.msdn.com/b/morgan/archive/2010/04/15/setting-up-wcf-with-a-load-balancer-using-ssl-in-the-middle.aspx
The problem with your service config is that the security mode is Transport, where in reality it should be None. Because any calls to your service will be HTTP behind F5 load balancer, you can not use Transport security mode there (client -> HTTPS -> F5 -> HTTP -> service). However, when calling the service from your client, the client config will need to be Transport security mode and the endpoint address will need to have an HTTPS address.
<wsHttpBinding>
<binding name="custBinding">
<security mode="None">
<transport clientCredentialType="None" />
<message clientCredentialType="None" negotiateServiceCredential="false" establishSecurityContext="false" />
</security>
</binding>
</wsHttpBinding>
This might be a little late for you, but here is how we do it. Once I have generated the proxy, I just change the http: in the config to https. Now, if I have to sometimes call it with ssl, and othertimes without, I will copy the config section, and give the copy a different name, and then when you construct the client, you can pass in the config name, and it will pick up the correct one.
We couldn't get this working through Layer 7 load balancing - there was various error messages returned from the service. Instead it's set up on Layer 4 load balancing with no issues.

Custom certificate validation in WCF service

I want to check client certificates in my WCF service.
My goal is to allow only clients with certificates with specific thumbprints to be able to communicate with my service.
My WCF service is hosted in IIS, I'm using basicHttpBinding and security mode="transport" with credential type "Certificate". IIS requires client certificates for communication with the service.
Thanks in advance for help.
UPDATE:
My configuration:
<basicHttpBinding>
<binding
name="testBinding"
maxReceivedMessageSize="2147483647">
<readerQuotas
maxDepth="2147483647"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
<security mode="Transport">
<transport clientCredentialType="Certificate"/>
</security>
</binding>
</basicHttpBinding>
Behavior:
<serviceBehaviors>
<behavior name="SomeServiceBehavior">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="Custom" customCertificateValidatorType="SomeService.CustomCertificateValidator,SomeService" />
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
Service configuration:
<service
behaviorConfiguration="SomeServiceBehavior"
name="SomeService">
<endpoint
address=""
binding="basicHttpBinding"
bindingConfiguration="testBinding"
contract="ISomeService">
</endpoint>
</service>
And for test purpose I implemented validator in this way:
public class CustomCertificateValidator : X509CertificateValidator
{
public override void Validate(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate)
{
throw new SecurityTokenValidationException("TEST Certificate was not issued by a trusted issuer TEST");
}
}
And this doesn't work. I can connect to my service with any valid certificate.
You can create a class derived from X509CertificateValidator and use it to do custom validation of the incoming certificate. Throw an SecurityTokenValidationException if you want to fail validation for some reason.
Set the certificateValidationMode to Custom and specify your validator in the clientCertificate service behavior section of the config file.
How to: Create a Service that Employs a Custom Certificate Validator
I do NOT think there is anyway to have 'Custom Certificate Validation' with 'Transport Security'. It only works with 'Message Security'.
YES, you can use basicHttpBinding with security set to Transport and you need to hook to the ServiceHost creation in IIS - see Custom Service Host.
You should be able to validate thumbprint values, certificates or any other data if you create custom config section to define list of validation criteria.
Sample code for the implementation of all of the above is available in the code download from this CodeProject artticle.