How to get WCF Service Running over SSL? - c#

I'm running a C# web service in IIS6 and trying to get it to work over SSL. When doing a tcpdump it shows the initial call as https but every other call over http. My SSL certificate is self signed and https works fine in my web browser. I'm using PHP SoapClient for the client.
Does anyone know what would cause this?
In the wsdl the address location is set to http. Should this be https? How do I change it?
<wsdl:service name="Service">
<wsdl:port name="BasicHttpBinding_Service" binding="i0:BasicHttpBinding_Service">
<soap:address location="http://example.com/Service.svc"/>
</wsdl:port>
</wsdl:service>

You must configure your service to use HTTPS:
<bindings>
<basicHttpBinding>
<binding name="https">
<security mode="Transport" />
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="metadata">
<serviceMetadata httpsGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="..." behaviorConfiguration="metadata">
<endpoint address="..." contract="..." binding="basicHttpBinding"
bindingConfiguration="https" />
</service>
</services>
This will allow calling your service only over HTTPS because there is no unsecured endpoint exposed. WSDL will also be accessible only over HTTPS because HTTP GET is not enabled.

Related

Problem with configuring HTTPS on my WCF service

I am trying to add transport security layer to my WCF service. But after following all the instructions i still get error "Could not find a base address that matches scheme https for the endpoint with binding BasicHttpBinding. Registered base address schemes are [http]."
Already did all needed configurations in IIS Manager and add need code in web.config but i still have a feeling i am missing something
web.config:
<system.serviceModel>
<services>
<service name="MyNameSpace.MyService" behaviorConfiguration="secureBehavior">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="secureHttpBinding" contract="MyNameSpace.IMyService" />
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="secureHttpBinding">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="secureBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
There is no problem with your present configuration, configure an https endpoint and it uses Transport security mode. One more thing we need to do is configuring an https binding address in IIS binding module. Like below.
It locates in the IIS site binding module.
Then we could use the above https service address to access it.
https://IP:4431/Service1.svc (service base address)
Feel free to let me know if the problem still exists.

WCF showing 403 Forbidden using SSL and client certificates

We are having a problem with WCF - we are getting the error below when trying to connect. There are tons of suggestions for various configurations, having tried them all we could use some help.
We are using HTTPS for transport security, using a real SSL certificate that we got from GoDaddy. It seems to be installed and working properly when we browse to web pages on the site. With no authentication, we can connect properly to our WCF service.
For authentication, we are using client certificates that we created ourselves. These client certificates were working fine before we switched to HTTPS, when we were using message security with a self-signed server certificate (which was a pain because we had to get the clients to install the server certificate).
Error
The HTTP request was forbidden with client authentication scheme 'Anonymous'.
Inner exception: The remote server returned an error: (403) Forbidden
Server configuration file
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="NewBinding0">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="WcfService1.Service1">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="NewBinding0" contract="WcfService1.IService1" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="PeerTrust" />
</clientCertificate>
<serviceCertificate findValue="....." x509FindType="FindByThumbprint" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add scheme="https" binding="wsHttpBinding" bindingConfiguration="NewBinding0" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Client configuration file
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="NewBehavior0">
<clientCredentials>
<clientCertificate findValue="customuser1"
storeName="TrustedPeople" x509FindType="FindBySubjectName" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="NewBinding0">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://www.insertoursitename.com/WcfService1/Service1.svc"
behaviorConfiguration="NewBehavior0" binding="wsHttpBinding"
bindingConfiguration="NewBinding0" contract="ServiceReference1.IService1"
name="wsHttpBinding_IService1" />
</client>
</system.serviceModel>
My problem was very similar to yours, and i'll describe my scenario before answering the question.
Created a simple WCF service (using custom binding, but that's irrelevant).
Created a self-signed RootCA using makecert, and generated two certs tempCertServer.cer used for SSL encryption, configure IIS to require https, etc.
--> Tested this part, worked ok from the Browser from a different computer.
The second cert tempCertClient.cer was used as a client-cert to be presented to IIS, configure IIS to Require client-cert, etc. --> Tested this part from a browser (best to use IE since you can easily clear SSL state). I get a prompt to choose a client cert, but never connects, the error is exactly the same as per the question:
"The HTTP request was forbidden with client authentication scheme 'Anonymous'. Inner exception: The remote server returned an error: (403) Forbidden."
Replaced tempCertClient with a proper cert (from a known CA), there was no issue, connection was established and WCF page shown; No matter what i tried with the self-signed client cert, always getting above error.
Wasted a whole day++ trying various settings, reading blogs on registry changes, placing the cert server-side under different cert stores, changing config file settings, etc, with no resolution.
The answer was very simple, inspect the LocalComputer\Trusted Root Certification Authorities server-side, and remove any NON-ROOT CA's (i.e. those that should not be there, IssuedTo NOT EQUALS IssuedBy)
The client-cert itself did not need to be installed on the server, only a Root CA that can validate it has to be installed in LocalComputer\Trusted Root Certification Authorities server-side.

Enabling http and https on the same service

I am writing a WCF service which contains a singe contract. I would like web clients to call the service endpoint using either http or https.
My web.config is as follows:
(Some parts have been removed for brevity)
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IDataService" />
<binding name="BasicHttpsBinding_IDataService" >
<security mode="Transport" />
</binding>
</basicHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="DataServiceMetadataBehavior" name="DummyService.DataService">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IDataService"
contract="DummyService.IDataService"/>
<endpoint address=""
binding="basicHttpBinding" bindingConfiguration="BasicHttpsBinding_IDataService"
contract="DummyService.IDataService" name="BasicHttpsBinding_IDataService"
/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="DataServiceMetadataBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add scheme="http" binding="basicHttpBinding" />
<add scheme="https" binding="basicHttpBinding" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
When I try to test the service using the VisualStudio test client, it gives the following error:
Could not find a base address that matches scheme https for the
endpoint with binding BasicHttpBinding. Registered base address
schemes are [http].
Everything works fine with only a single endpoint.
An endpoint consists of address, binding and contract.
http://YourBaseAddress/YourApp/YourService.svc and httpS://YourBaseAddress/YourApp/YourService.svc are different address with different schema name or protocol as well as different ports: 80 and 443 by default, so you can have both endpoints for the service, with the same basicHttpBinding, provided that the https one has a bindingConfiguration for SSL transportation as you had done. The error message is quite informative, so you need to go to IIS (or IIS Express) to make sure there's a http listener, say https binding defined after checking the "Edit Bindings" function of the Website. After you had done so, you should be able to get WSDL through httpS://YourBaseAddress/YourApp/YourService.svc?wsdl in a Web browser.
In fact, many Web services/applications like those from Microsoft and Google support both http and https through the same host name and path.

Add additional SSL behavior for WCF endpoint within Azure Web Role

Our azure web application already uses https port 443 with our site certificate, we have a WCF service within this webrole that has an https endpoint using our cert to authenticate (1-way ssl), this same service needs an additional https endpoint supporting 2-way auth using our cert and the third party's cert. We have uploaded the cert, updated the service definition file, and added an endpoint that we are hoping will work, but in testing we are getting the error: The SSL settings for the service 'SslRequireCert' does not match those of the IIS 'None'.
so the endpoint that does work is: https://environemnt.application.com/Services/Service.svc
the endpoint that generates the error: https://environment.application.com/Services/Service.svc/twa
The key requirement is that it is https, port 443, at the above new endpoint, without altering the SSL behavior of the rest of the role, I have seen entries to change the IIS configuration or use the role editor to add an Https Input endpoint, but as we already have an Https Input endpoint on port 443 using our site cert I don't want to alter/affect the whole role.
If it is helpful the service is a WCF Service which consumes an Mtom encoded soap 1.2 message
here are the new values that we have entered, what else do I need?
<behaviors>
<serviceBehaviors>
<behavior name="SSLServiceBehavior">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="OneWayAuthEndpointBehavior">
</behavior>
<behavior name="TwoWayAuthEndpointBehavior">
<endpointDiscovery enabled="true"></endpointDiscovery>
<clientCredentials>
<clientCertificate findValue="thumprint..." storeLocation="LocalMachine" storeName="CertificateAuthority" x509FindType="FindByThumbprint" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="SSLServiceBehavior" name="Service">
<endpoint address="" behaviorConfiguration="OneWayAuthEndpointBehavior"binding="wsHttpBinding" bindingConfiguration="HttpsMtomOneWay" contract="ITestService" />
<endpoint address="twa" behaviorConfiguration="TwoWayAuthEndpointBehavior" binding="wsHttpBinding" bindingConfiguration="HttpsMtomTwoWay" contract="ITestService"/>
</services>
<bindings>
<wsHttpBinding>
<binding name="HttpsMtomOneWay" messageEncoding="Mtom">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
<binding name="HttpsMtomTwoWay" messageEncoding="Mtom">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
thank you much
Fixed through these steps:
Added serviceCredentials.serviceCertificate (cert details for our cert) to the service behavior
Eliminated Endpoint behavior definitions
Changed the HttpsMtomTwoWay binding to securityMode=Message
Now the message handlers handle the authentication exchange and external cert validation, then pass on to the transport endpoint, and we did not need to mess with the site wide SSL or endpoint settings. Tested and verified with numerous 3rd parties.

Web service contains an empty service tag

I created a WCF service.
In the WSDL I can't see the URL and PORT that the service should bind on.
All I see is:
<wsdl:service name="SimpleWebService"/>
Any idea what am I doing wrong? maybe something in the web.config?
<system.serviceModel>
<client />
<bindings>
<webHttpBinding>
<binding closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" />
</binding>
</webHttpBinding>
</bindings>
<services>
<service name="WS.OS.SimpleWS" behaviorConfiguration="myServiceBehavior">
<endpoint name="webHttpBinding" address="" binding="webHttpBinding" contract="WS.OS.SimpleWS" behaviorConfiguration="webHttp" />
<endpoint name="mexHttpBinding" address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="myServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webHttp">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Creating an endpoint with webHttpBinding creates a REST endpoint. REST endpoints does not have wsdl. In your case you see wsdl generated because you have included the metadata behavior. You will have an endpoint listed in WSDL only for SOAP endpoints. This is a good blog post which helps you to understand this better : http://blogs.msdn.com/b/carlosfigueira/archive/2012/03/26/mixing-add-service-reference-and-wcf-web-http-a-k-a-rest-endpoint-does-not-work.aspx
Looking at the question, and the config, I'm assuming (we all know where that leads) that your service is hosted in IIS. So given the address of "" and no port given, you will have to look in your IIS settings to find the site and the port on which the service is open. The defualt for http is 80 and https is 443.
So quick example, if your service is on the "Default Website" of the IIS then your service will probably be at:
http://YourServer/YourService/YourService.svc
If there is a web application that is hosted on there that is under a specificly different site, you will need to look into the setting of IIS to find it. It is common also to have IIS host the SVC as default page so you could have just the first two parts and not the actual page in your URI. I don't think you will have much luck unless you start digging into your web server.

Categories

Resources