How can I use WCF with the basichttpbinding only , SSL and Basic Authentication in IIS? - wcf

Is it possible to setup a WCF service with SSL and Basic Authentication in IIS using only the BasicHttpBinding-binding?
(I can’t use the wsHttpBinding-binding)
The site is hosted on IIS 7, with the following authentication set up:
Anonymous access: OFF
Basic authentication: ON
Integrated Windows authentication: OFF
Service Config:
<services>
<service name="NameSpace.SomeService">
<host>
<baseAddresses>
<add baseAddress="https://hostname/SomeService/" />
</baseAddresses>
</host>
<!-- Service Endpoints -->
<endpoint address="" binding="basicHttpBinding"
bindingNamespace="http://hostname/SomeMethodName/1"
contract="NameSpace.ISomeInterfaceService"
name="Default"
/>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpsGetEnabled="true"/>
<!-- 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="false"/>
<exceptionShielding/>
</behavior>
</serviceBehaviors>
</behaviors>
I tried 2 types of bindings with two different errors:
1. IIS Error:
'Could not find a base address that matches scheme http for the endpoint with binding BasicHttpBinding. Registered base address schemes are [https].
<bindings>
<basicHttpBinding>
<binding>
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
2. IIS Error:
Security settings for this service require 'Anonymous' Authentication but it is not enabled for the IIS application that hosts this service.
<bindings>
<basicHttpBinding>
<binding>
<security mode="Transport">
<transport clientCredentialType="Basic"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
Does anyone know how to configure this correctly? (if is it possible?)

After some digging and asking some questions to a few colleagues, we finally solved the problem.
Important to understand is there are 2 aspects of security in this case. The IIS security and the WCF security.
IIS security: Enable SSL & enable Basic Authentication. Disable Anonymous Authentication.
(Of course, create a windows account/group and set the permissions on your application in IIS.)
WCF security: Because the binding is only a BasicHttpBinding, the service doesn't require to valid anything. IIS is responsible for this.
The binding configuration of the service:
<bindings>
<basicHttpBinding>
<binding>
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
</binding>
</basicHttpBinding>
And finally, to resolve the first error, we deleted the mex Endpoint. This endpoint requires a HTTP binding.
Deleted:
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>

Related

WCF web.config file settings for IIS hosting and SSL

After hours of searching for examples, most of which contain only snippets of methods but not the 'whole picture' I am asking for guidance. Starting with the out-of-the-box web.config Visual Studio creates with a new WCF Service, I wrote my basic web service. When you run in debug, WCF Test Client shows the functions that you can test. This is great. Now, wanting to move the code to IIS (first on my local machine, then next to the web server using SSL), I added some code I found on the web. I did have my configuration working at one point but managed to change it so much that I lost the original configurations. So, which that, I have this:
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<protocolMapping>
<add scheme="http" binding="webHttpBinding"/>
</protocolMapping>
<services>
<service name="TaskTrackerAppService.Service1" behaviorConfiguration="">
<endpoint address=""
binding="webHttpBinding"
contract="TaskTrackerAppService.IAppWebService"
behaviorConfiguration="WebBehavior"></endpoint>
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange" bindingConfiguration=""></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="WebBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="TaskTrackerAppService.IAppWebService"></binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="" binding="webHttpBinding"
bindingConfiguration="TaskTrackerAppService.IAppWebService"
contract="TaskTrackerAppService.IAppWebService"></endpoint>
</client>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
I configure my client desktop application service reference to point to the local IP http:192.168.0.100:90/AppWebService.svc. Then when I run my client application I get an error:
Could not find default endpoint element that references contract 'ServiceReference.IAppWebService' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element.
So I'd like to get the web.config settings corrected. Then deploy to a hosted IIS service where SSL is ready. As a bonus, is there is way to configure the endpoints such that I can still run debugger and get WCF Test Client. In the once working config WCF test stopped working. Can it support both simple and hosted configurations?
Thanks.
The <client> section in the <system.serviceModel> is used by client application to specify the "ABC" properties (Address, Binding, and Contract) of the service endpoint. You should have that section in your desktop application so you can simply remove it from your server configurations.
The <client> section in the app.config of your desktop application should, however, have the same "ABC" properties as the service endpoint. Since your service binding is webHttpBinding the client should also have webHttpBinding as binding but I can see that the bindingConfiguration it is referring to, TaskTrackerAppService.IAppWebService is actually a basicHttpBinding so that is a misconfiguration.
Further, since your production environment is using SSL so your production web.config should have binding configuration for SSL something similar to this:
<bindings>
<webHttpBinding>
<binding name="webBindingHTTPS">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</webHttpBinding>
</bindings>
with the following endpoint configuration:
<endpoint address=""
binding="webHttpBinding"
contract="TaskTrackerAppService.IAppWebService"
behaviorConfiguration="webBindingHTTPS"></endpoint>
The best way to achieve this is to use web.config transformation syntax. In that case, your Release web.config could have the following elements:
<bindings>
<webHttpBinding>
<binding name="webBindingHTTPS" xdt:Transform="Insert">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</webHttpBinding>
</bindings>
<endpoint address="" xdt:Transform="Replace" xdt:Locator="Match(name)"
binding="webHttpBinding"
contract="TaskTrackerAppService.IAppWebService"
behaviorConfiguration="webBindingHTTPS">
</endpoint>
In this way, whenever you project is built in Debug mode it will be configured withoud SSL and whenever is built in Release mode, it will use SSL.

Anonymous authentication not working for WCF service: "..... The authentication header received from the server was ''"

We use IIS 7.5 to host our intranet applications, which are configured to use Windows Authentication.
Within one of the applications, I have a WCF service I'm trying to host/call into. This must have Anonymous authentication, so I can host it with the following setting:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="myServiceBehaviour">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="basicHttpBindingOverSslAnonymous">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<services>
<service behaviorConfiguration="myServiceBehaviour"
name="xxx.yyy.Web.Mvc.Client.Services.MyService">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttpBindingOverSslAnonymous" name="BasicHttpEndpoint" contract="xxx.yyy.Wcf.IMyService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
But, despite the server being configured to allow Anonymous authentication and disable Windows authentication, all I get is the following exception message:
The HTTP request is unauthorized with client authentication scheme
'Anonymous'. The authentication header received from the server was ''
Note the empty authentication header. Googling for this was futile, as all responses had something in the quotes (despite using the phrasal search operator).
This is based on my client which has the following configuration:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpEndpoint">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://xxx.local/xxx.yyy.Web.Mvc.Client/services/MyService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpEndpoint"
contract="MyService.IMyService" name="BasicHttpEndpoint" />
</client>
</system.serviceModel>
Turning on Windows authentication works fine from a browser, but I don't want to have to send credentials.
It's as if WCF is ignoring my IIS configuration:
Anonymous authentication
Impersonation
Basic authentication
Forms authentication
Windows authentication
Why could this be?
Interestingly, dropping a test.txt file in the same folder works fine with anonymous setting. It's as if this only effects WCF.
The issue was that configuring Anonymous authentication within IIS is not the only step.
The following removes the intranet-style denial rule from the /Services folder that contained my services.
<location path="Services">
<system.web>
<authorization>
<allow users="*" />
</authorization>
<identity impersonate="false" />
</system.web>
</location>
The net effect of this is that .NET assets within the /Services folder are permitted for Anonymous authentication.

WCF Services need to be HTTPS only but only work on HTTP

I have some WCF services that have been working for a while now on HTTP.
I'm moving them to deployment server now and they need to be HTTPS only.
I got the certificate and when I initially set the up they worked over both HTTP and HTTPS.
...at this point I wanted to drop the non-secure access to the services.
So I'm trying to make amendments to my web.config to make this happen:
Service Behaviours:
<serviceBehaviors>
<behavior name="MetaEnabledBahavior">
<serviceMetadata httpsGetEnabled="true"/>
</behavior>
</serviceBehaviors>
Service Endpoints:
<service name="Services.BookingService" behaviorConfiguration="MetaEnabledBahavior">
<!-- Service Endpoints -->
<clear/>
<endpoint address="https://website.com/services/BookingService.svc" binding="wsHttpBinding"
bindingConfiguration="TransportSecurity" contract="Services.IBookingService"/>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
</service>
Bindings:
<bindings>
<wsHttpBinding>
<binding name="TransportSecurity" maxReceivedMessageSize="2000000">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
What I have ended up with at the moment is my HTTP services are still accessible, but the HTTPS access just sends a blank page.
I need HTTP to return an error/page must be viewed by secure channel and HTTPS to be the ones that work only.
How do I fix this?
Smithy try replacing your endpoint with the following:
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="TransportSecurity" contract="Services.IBookingService"></endpoint>
And your binding with a basicHttpBinding
<basicHttpBinding>
<binding name="TransportSecurity" maxReceivedMessageSize="2000000">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</basicHttpBinding>
Hope this helps.
In the <protocolMapping> section of Web.Config, add a <remove scheme="http" /> element.

Custom Domain for Azure Cloud Service with SSL

I'm trying to expose an Azure Cloud Service using https with a custom domain, but I get an error: "The requested service, 'https://mydomain.net/myservice.svc' could not be activated. See the server's diagnostic trace logs for more information."
Regarding the custom domain: I've followed the steps at https://www.windowsazure.com/en-us/develop/net/common-tasks/custom-dns/#header-1 for the second option, "A record": in godaddy's Zone File Manager, I have an A record configured for the "#" host that "Points To" myservice's "Public Virtual IP Address" (as found in the Azure portal). It seems to me that the fact I'm getting "the service could not be activated" means the A record is working, but I'm not certain.
Regarding the https: I've followed the steps at http://www.31a2ba2a-b718-11dc-8314-0800200c9a66.com/2011/06/how-to-get-and-install-ssl-certificate.html. In brief: I purchased a cert from godaddy using a CSR from my dev machine for mydomain.net, completed the CSR on my dev machine using the friendly name mydomain.net, exported it to mydomain.net.pfx, using that file, uploaded the cert to my cloud service in Azure and configured my WebRole in VS with the cert, and published the web role project to Azure.
On the client side (WP7):
<bindings>
<basicHttpBinding>
<binding name="BasicHttpsBinding_IMyInterface"
maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<security mode="Transport" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint name="BasicHttpsBinding_IMyInterface"
address="https://mydomain.net/myservice.svc"
contract="MyService.IMyInterface"
binding="basicHttpBinding"
bindingConfiguration="BasicHttpsBinding_IMyInterface" />
</client>
Note: I didn't use CName because my cert isn't for a subdomain and it isn't a wildcard.
From my searches, I get the impression this is working for other folks and I can't figure out what I'm doing differently.
yep - you need a matching endpoint specified in the server config. The following is a complete example of a web.config file for a WCF service using HTTP transport security (from http://msdn.microsoft.com/en-us/library/hh556232.aspx):
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="MySecureWCFService.Service1">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="secureHttpBinding"
contract="MySecureWCFService.IService1"/>
<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>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpsGetEnabled="true"/>
<!-- 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="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>

Getting an Security setting exception while accessing a WCF service

Following are binding configurations of my WCF service.
Anonymous access: off
Basic authentication: on
Integrated Windows authentication: off !!
support HTTP protocol .
I am getting an following exception while accessing my WCF service:
Security settings for this service require 'Anonymous' Authentication but it is not enabled for the IIS application that hosts this service.
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="MyBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType ="Basic" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="WMWcfWebServiceLib.Service1Behavior"
name="WMWcfWebServiceLib.WMWcfWebService">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="MyBinding"
contract="WMWcfWebServiceLib.IWMWebService">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8731/Design_Time_Addresses/WMWcfWebServiceLib/Service1/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WMWcfWebServiceLib.Service1Behavior">
<!-- To avoid disclosing metadata information,
set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="True"/>
<!-- 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="False" />
</behavior>
</serviceBehaviors>
</behaviors>
Please Help!!
Edit
I am able to access the WCF service through the web browser with the following changes:
Changes the security mode to TransportCredentialOnly and Removed the Mex Endpoint, but now as obvious I am not able to create the proxy on the client side.
Please let me know where I am wrong ?
If you want to support HTTP only your configuration is not used at all because mode="Transport" demands HTTPS. First find why config is not used (probably wrong type name in service element). Next change security mode to TransportCredentialOnly. But be aware that TransportCredentialOnly + Basic authentication means that HTTP requests will contain plain text Windows user name and password. In most cases such implementation will not pass any security audit.
Edit:
You can create proxy without mex endpoint if you still support httpGetEnabled in service metadata behavior.