WCF - SSL Service - wcf

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.

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.

WCF with SSL hosted by iis 7.5 or consolehost

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; };

Configure a WCF service to authenticate the client by using X509 certificates but without server credentials

I have developed a ASP.NET MVC website that also hosts a WCF 4 service; and I have created a .NET Windows application that complements the website and interacts with it by consuming that web service via the internet. Both programs were created using .NET 4 in Visual Studio 2010. The binding used with the WCF service is a WsHttpBinding.
My only security requirement is that the WCF service is not consumed by some unknown party, as that would contaminate the information in my website's database. I have no need for any privacy: I don't care if some third party gets to see the messages I am sending to the web service (i.e., no need for encryption)
Considering that single requirement, and as far as my knowledge about security in web services goes, the best way to implement that security scenario would be for the client to sign each SOAP message with a X509 Certificate, and have the web service trust any message signed with a certificate present in its "trusted people" store. Since certificates use Public/Private key pairs, even if the message is not encrypted it cannot be reproduced by an unauthorized third party without the private key used to sign the message. This would also assure me message integrity.
Considering that decision, I have created a test certificate using makecert.exe. I installed the version with both the private and public key in the client machine (the one with the windows application), in the "Current User" "My" certificate store. Then, I exported the certificate (without the private key), and installed it in "Trusted People" of "Local Machine" certificate store of the web server.
My (unsuccessful) attempt to configure that scenario so far goes like this:
Binding is configured to use Message security, where the Message expects client credentials of the certificate type. Also, the server is configured to use PeerTrust instead of ChainTrust, since the test certificate is not emitted by a trusted CA:
<bindings>
<wsHttpBinding>
<binding>
<security mode="Message">
<transport clientCredentialType="None" proxyCredentialType="None" />
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="Standard">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode = "PeerTrust" trustedStoreLocation="LocalMachine"/>
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
The configuration on the client windows application sets the certificate as its credential. The binding configuration is identical to the one in the server.
<behaviors>
<endpointBehaviors>
<behavior name="CertificateCredential">
<clientCredentials>
<clientCertificate findValue="ErrEye"
storeLocation="CurrentUser"
storeName="My"
x509FindType="FindBySubjectName" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
The problem is that with this configuration, when I try to check if the Web Service host was started successfully, I get the following error:
The service certificate is not provided. Specify a service certificate in ServiceCredentials.
My problem is, I don't WANT to specify a "service certificate". As far as I understand, the service certificate would allow the client to authenticate the service, but I don't need that; I just want the service to authenticate the client and that's it. I do understand this means that if someone impersonates the web server (by tampering the DNS settings of my client computer, for example) it would receive the messages from my client and the client would not know it is not communicating with its intended recipient: I don't mind if that happens.
In summary, my question is: How do I configure in WCF the security scenario I've described?
Thanks in advance for your help.
As long as its .net to .net (and remains so) - add this
negotiateServiceCredential=true
to:
<message clientCredentialType="Certificate" />
But beware, you will lose interoperability with non .net clients.

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.

REST WCF Service hosting(https) in Windows Service on Win2003

I am self hosting a REST WCF service in Windows service. The service exposes a method which returns a boolean and I am able to get the REST webservice to work on WinXp. I also generated a development certificate using makecert and assigned it to the port(1443) that the service listens on. Https also works well on WinXp. But When I use the same in Win2003, and type the URL in IE, it says "The page cannot be displayed". There were no errors in hosting the service, the service listens on the port(the ServiceHost.Open didnt have any errors and its successful). Is there an settings that has to be done in Win2003 for this? Win2003 is the production environment and https has to work on that.
Here is the config file I used,
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="httpBinding">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</webHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="spectrumServiceBehavior" name="MyApp.TestService">
<host>
<baseAddresses>
<add baseAddress="https://localhost:1443/" />
</baseAddresses>
</host>
<endpoint address=""
binding="webHttpBinding"
bindingConfiguration ="httpBinding"
contract="MyApp.ITestService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="spectrumServiceBehavior">
<!-- 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" />
<serviceMetadata httpsGetEnabled ="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
Any ideas?
I've experienced the same problem. WinXP development environment working with HTTPS, certificate created locally and assigned to a custom port with httpcfg.
Production environment on Windows 2003 with the imported certificate and the same httpcfg configuration giving "interrupted connection" while trying to obtain the WSDL of the service.
Looking at the Windows log I finally found this error:
Event Source: Schannel
A fatal error occurred when attempting to access the SSL server credential private key. The error code returned from the cryptographic module is 0x80090016.
My problem was that I imported the certificate in the user-account store, and then copied in the local store. In this way the private-key is left behind... http://support.microsoft.com/kb/939616 (without even a warning!!!)
despite, opening the certificate in the new location, shows the presence of a private-key!
I expect that on Windows 2003 you must allow application to listen on port (unless it runs as admin) and you must assign SSL certificate to the port - both is performed by httpcfg.exe. Also check that there is no firewall blocking the communication on the port.