How to configure WCF REST to work with SSL? - wcf

I have a nice WCF REST-ful JSON service working well as is. The problem arises when I try to put it to work on HTTPS. The Web.config is as follows:
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="StreamedRequestWebBinding" bypassProxyOnLocal="true" useDefaultWebProxy="false" hostNameComparisonMode="WeakWildcard" sendTimeout="10:15:00" openTimeout="10:15:00" receiveTimeout="10:15:00" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" transferMode="StreamedRequest">
<security mode="Transport">
<transport clientCredentialType = "None" />
</security>
<readerQuotas maxArrayLength="2147483647" maxStringContentLength="2147483647" />
</binding>
</webHttpBinding>
</bindings>
<services>
<service name="WcfRESTFullJSON.Service1" behaviorConfiguration="ServiceBehaviour">
<endpoint address="" binding="webHttpBinding" bindingConfiguration="StreamedRequestWebBinding" contract="WcfRESTFullJSON.IService1" />
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<!--Him-->
<webHttp automaticFormatSelectionEnabled="true" />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true" />
</system.serviceModel>
I configured a home-made certificate on IIS.
On the client I have:
WebClient WC;
...
WC.UploadData(URL, "POST", asciiBytes);
What we get:
The remote server returned an error: (500) Internal Server Error.
What may be the problem?

The issue is resolved. It was a missing reference to a endpoint behavior in the following line
...endpoint behaviorConfiguration="web" address="" binding="webHttpBinding" bindingConfiguration="StreamedRequestWebBinding" contract="WcfRESTFullJSON.IService1"...
in the Web.config below. Thank you for your help friends! The solution was finally found in the article Implementing 5 important principles of REST using WCF Services
<services>
<service name="WcfRESTFullJSON.Service1" behaviorConfiguration="ServiceBehaviour">
<endpoint behaviorConfiguration="web" address="" binding="webHttpBinding" bindingConfiguration="StreamedRequestWebBinding" contract="WcfRESTFullJSON.IService1" />
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<!--Him-->
<webHttp automaticFormatSelectionEnabled="true" />
</behavior>
</endpointBehaviors>

As SSL is a protocol under HTTP, there is usually nothing extra to configure in web.config (only a new binding). Another thing that changes if you use SSL is the port... you may need to update the firewall or check that your request is sent to the right port.

See Complete config file
<configuration> <system.web>
<compilation debug="true" targetFramework="4.0" />
<webServices>
<protocols>
<add name="HttpsGet"/>
<add name="HttpsPost"/>
</protocols>
</webServices> </system.web> <system.serviceModel>
<services>
<service name="RESTTEST.RestTestService" behaviorConfiguration="ServiceBehavior">
<endpoint address="" binding="webHttpBinding"
contract="RESTTEST.IRestTestService"
bindingConfiguration="sslBinding"
behaviorConfiguration="web"
></endpoint>
<endpoint address="mex"
binding="mexHttpsBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before
deployment -->
<serviceMetadata httpGetEnabled="true" 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="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<webHttpBinding>
<binding name="sslBinding" crossDomainScriptAccessEnabled="true">
<security mode="Transport">
</security>
</binding>
</webHttpBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="false">
</serviceHostingEnvironment>
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint crossDomainScriptAccessEnabled="true"></standardEndpoint>
</webHttpEndpoint>
<webScriptEndpoint>
<standardEndpoint name="" crossDomainScriptAccessEnabled="true" />
</webScriptEndpoint>
</standardEndpoints> </system.serviceModel> <system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
</customHeaders>
</httpProtocol> </system.webServer> </configuration>

Related

Metadata is currently disabled on my WCF svc page

The following is my web.config file:
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
</system.web>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true" />
<bindings>
<webHttpBinding>
<binding name="Binding" crossDomainScriptAccessEnabled="true">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</webHttpBinding>
</bindings>
<client />
<services>
<service name="Service1" behaviorConfiguration="ServiceBehaviour">
<endpoint address="" binding="webHttpBinding" contract="Service1"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="ServiceBehaviourJSON">
<webHttp helpEnabled="true" defaultOutgoingResponseFormat="Json" />
</behavior>
</endpointBehaviors>
</behaviors>
</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>
</configuration>
And I viewed a few examples of this error on here and changed what was asked but I still seem to get the same Metadata publishing for this service is currently disabled.??
My two files for the web service are called IService1.vb and Service1.svc.
Maybe someone can see the error that I can't and let me know :)
Updated web.config file
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
</system.web>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true" />
<bindings>
<webHttpBinding>
<binding name="Binding" crossDomainScriptAccessEnabled="true">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</webHttpBinding>
</bindings>
<client />
<services>
<service name="Service1" behaviorConfiguration="metadataBehavior">
<endpoint address="" binding="webHttpBinding" contract="Service1"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<endpoint address="" binding="basicHttpBinding" contract="Service1"
/>
<host>
<baseAddresses>
<add baseAddress="http://localhost:65234/Service1.svc"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
<behavior name="metadataBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="ServiceBehaviourJSON">
<webHttp helpEnabled="true" defaultOutgoingResponseFormat="Json" />
</behavior>
</endpointBehaviors>
</behaviors>
</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>
</configuration>
You expose metadata using HTTP protocol (httpGetEnabled), then WCF seeks for address to expose but there is no HTTP base address defined, alas.

WCF rest hosting on IIS

I have an wcf rest service. I hosted it in IIS with following service configuration
<system.serviceModel>
<services>
<service behaviorConfiguration="Default" name="CRM_Service.CRM_Service">
<endpoint address="" behaviorConfiguration="webBehavior"
binding="webHttpBinding" bindingConfiguration="webHttpBinding_ICRM_Service" contract="CRM_Service.ICRM_Service" />
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
<host>
<baseAddresses>
<add baseAddress="*********" />
</baseAddresses>
</host>
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="webHttpBinding_ICRM_Service" closeTimeout="00:04:00" maxReceivedMessageSize="2147483647"
maxBufferPoolSize="2147483647">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="webBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="Default">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceThrottling maxConcurrentCalls="500" maxConcurrentSessions="500"
maxConcurrentInstances="500" />
</behavior>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<diagnostics>
<messageLogging logEntireMessage="true"
logMessagesAtServiceLevel="false"
logMessagesAtTransportLevel="false"
logMalformedMessages="true"
maxMessagesToLog="5000"
maxSizeOfMessageToLog="2000">
</messageLogging>
</diagnostics>
</system.serviceModel>
I used separate application pool for this project. After hosting it worked fine for some duration,but after that service was not responding for any method call. Please help me to come out this issue. Thanks in advance...

WCF application Endpoint not found

So the problem I could guess I'm facing is the configuration of web config. Let me tell what I'm doing,
Created WCF library
created on WCF application and refer the library DLL.
After that when I run the WCF application it gives me the error endpoint not found.
<system.serviceModel>
<services>
<service name="Boost.Web.CARD.services.CardServiceLibrary.CardService"
behaviorConfiguration="HostBehavior">
<endpoint
address=""
binding="webHttpBinding" bindingConfiguration="CardCustomBinding"
contract="Boost.Web.CARD.services.CardServiceLibrary.ICardService"/>
</service>
</services>
<diagnostics wmiProviderEnabled="true">
<messageLogging logMalformedMessages="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true"/>
</diagnostics>
<bindings>
<webHttpBinding>
<binding name="CardCustomBinding" allowCookies="true"
maxBufferSize="20000000" maxBufferPoolSize="20000000"
maxReceivedMessageSize="20000000">
<readerQuotas maxDepth="32" maxStringContentLength="20000000"
maxArrayLength="20000000"/>
<security mode="None"/>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="HostBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
I just want to test it on my local machine not on the server. I am adding my WCF library config part as well that might also help in sorting out the issue.
<system.serviceModel>
<services>
<service behaviorConfiguration="Boost.Web.CARD.services.CardServiceLibrary.Service1Behavior" name="Boost.Web.CARD.services.CardServiceLibrary.CardService">
<endpoint address="" behaviorConfiguration="Web" binding="webHttpBinding" contract="Boost.Web.CARD.services.CardServiceLibrary.ICardService" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/service/1.0/rest" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="Web">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="Boost.Web.CARD.services.CardServiceLibrary.Service1Behavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>

WCF CustomBinding for CustomTextMessageEncoder using HTTPS

I am working on a WCF REST-type service that will accept text/xml type documents via a POST over HTTPS (ASP.NET 4.0 on IIS). Can someone help me with the web.config? I'm testing with the sample code for the CustomTextMessageEncoder to parse the document. I'm getting an error:
"Manual addressing is not supported with message level security. Configure the binding ('CustomBinding', 'http://tempuri.org/') to use transport security or to not do manual addressing."
Unfortunately, if I turn off ManualAddressing, I get a different error. I'm not sure how to turn on TransportSecurity since it's a custom binding.
The main portions of the web.config for what I"m doing are:
<system.serviceModel>
<services>
<service name="MyApp.MyApp" behaviorConfiguration="MyAppBehavior" >
<endpoint address="https://myURL/MyApp/" binding="customBinding" bindingConfiguration="newBinding" behaviorConfiguration="webEndpoint" contract="MyApp.IMyApp" />
<host>
<baseAddresses>
<add baseAddress="https://myURL/MyApp/" />
</baseAddresses>
</host>
</service>
</services>
<serviceHostingEnvironment multipleSiteBindingsEnabled="false" aspNetCompatibilityEnabled="true">
<baseAddressPrefixFilters>
<add prefix="https://myURL/MyApp/" />
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
<behaviors>
<serviceBehaviors>
<behavior name="MyAppBehavior" >
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="True" httpsGetUrl="https://myURL/MyApp/MyApp.svc/" />
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webEndpoint" >
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<bindingElementExtensions>
<add name="customTextMessageEncoding" type="Microsoft.Samples.CustomTextMessageEncoder.CustomTextMessageEncodingElement, CustomTextMessageEncoder" />
</bindingElementExtensions>
</extensions>
<bindings>
<webHttpBinding>
<binding name="webHttpBinding">
<security mode="Transport" />
</binding>
</webHttpBinding>
<customBinding>
<binding name="newBinding" >
<security authenticationMode="AnonymousForCertificate" />
<customTextMessageEncoding messageVersion="Soap12WSAddressing10">
</customTextMessageEncoding>
<httpsTransport manualAddressing="true" requireClientCertificate="true" />
</binding>
</customBinding>
</bindings>
</system.serviceModel>

WCF routing + SSL

I need to create a "routing" service.
I'm trying to used the System.ServiceModel.Routing.IRequestReplyRouter of .Net
I can make it work only in HTTP mode, not in HTTPS.
The error is "Cannot establish secure SSL/TLS connection"... I also tried a custom certificate validator but it is not called! (it is created, but the validate method is not called)
I post my configuration here:
<?xml version="1.0"?>
<bindings>
<customBinding>
<!-- Security Off version-->
<binding name="customBindingNotSecure">
<textMessageEncoding messageVersion="Soap12WSAddressing10"/>
<httpTransport />
</binding>
<!-- Security On -->
<binding name="customBindingSecure">
<textMessageEncoding messageVersion="Soap12WSAddressing10">
</textMessageEncoding>
<security authenticationMode="UserNameOverTransport" />
<httpsTransport />
</binding>
<binding name="platoneBinding">
<textMessageEncoding messageVersion="Soap12WSAddressing10" />
<httpsTransport maxReceivedMessageSize="1000000" maxBufferPoolSize="1000000" maxBufferSize="1000000" />
</binding>
</customBinding>
</bindings>
<services>
<service behaviorConfiguration="routingService" name="System.ServiceModel.Routing.RoutingService">
<endpoint address=""
binding="customBinding"
name="reqReplyEndpoint"
contract="System.ServiceModel.Routing.IRequestReplyRouter" bindingConfiguration="customBindingSecure"/>
<endpoint address=""
binding="customBinding"
name="reqReplyEndpointHttp"
contract="System.ServiceModel.Routing.IRequestReplyRouter"
bindingConfiguration="customBindingNotSecure"/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="CustomClientBehavior">
<clientCredentials>
<serviceCertificate>
<defaultCertificate findValue="serverx509v1" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName"/>
<authentication customCertificateValidatorType="com.abodata.plat1.WCFProxy.PlatoneCertificateValidator, PlatoneWSRelay"
certificateValidationMode="Custom" revocationMode="NoCheck" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="routingService">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<routing routeOnHeadersOnly="true" filterTableName="routingTable1" />
<serviceCredentials>
<clientCertificate>
<authentication customCertificateValidatorType="com.abodata.plat1.WCFProxy.PlatoneCertificateValidator, PlatoneWSRelay"
certificateValidationMode="Custom" revocationMode="NoCheck" />
</clientCertificate>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="com.abodata.plat1.WCFProxy.UsernameValidator, PlatoneWSRelay" />
</serviceCredentials>
</behavior>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<routing>
<filters>
<filter name="MatchAllFilter1" filterType="MatchAll" />
</filters>
<filterTables>
<filterTable name="routingTable1">
<add filterName="MatchAllFilter1" endpointName="PlatoneWSService" />
</filterTable>
</filterTables>
</routing>
<client>
<endpoint address="https://10.0.2.243:9006/Persistence"
binding="customBinding" bindingConfiguration="platoneBinding"
contract="*" name="PlatoneWSService">
<identity>
<dns value="serverx509v1" />
</identity>
</endpoint>
</client>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
EDIT: I managed to establish the TLS connection by adding to my configuration
<system.net>
<settings>
<servicePointManager checkCertificateName="false" checkCertificateRevocationList="false"/>
</settings>
</system.net>
But... now I have problems with the security header of my soap envelop. The client sends the message correctly to my router, but it removes the security header, so I get an exception...
Ok... I solved also the second problem.
My router binding must not specify the security tag, otherwise it process the envelop.
This is my working configuration
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<bindings>
<!-- Must use custom binding: silverlight only support basicHttpBinding that is not
SOAP 1.2. So.. I create a custom binding-->
<customBinding>
<!-- Security Off version-->
<binding name="customBindingNotSecure">
<textMessageEncoding messageVersion="Soap12WSAddressing10"/>
<httpTransport />
</binding>
<!-- Security On -->
<binding name="customBindingSecure">
<textMessageEncoding messageVersion="Soap12WSAddressing10">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
</textMessageEncoding>
<httpsTransport maxBufferPoolSize="2000000" maxBufferSize="2000000" maxReceivedMessageSize="2000000" />
</binding>
<binding name="platoneBinding">
<textMessageEncoding messageVersion="Soap12WSAddressing10" />
<httpsTransport maxReceivedMessageSize="1000000000" maxBufferPoolSize="1000000000" maxBufferSize="1000000000" />
</binding>
</customBinding>
</bindings>
<services>
<service behaviorConfiguration="routingService" name="System.ServiceModel.Routing.RoutingService">
<endpoint address=""
binding="customBinding"
name="reqReplyEndpoint"
contract="System.ServiceModel.Routing.IRequestReplyRouter" bindingConfiguration="customBindingSecure"/>
<endpoint address=""
binding="customBinding"
name="reqReplyEndpointHttp"
contract="System.ServiceModel.Routing.IRequestReplyRouter"
bindingConfiguration="customBindingNotSecure"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="routingService">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<routing routeOnHeadersOnly="true" filterTableName="routingTable1" />
</behavior>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<routing>
<filters>
<filter name="MatchAllFilter1" filterType="MatchAll" />
</filters>
<filterTables>
<filterTable name="routingTable1">
<add filterName="MatchAllFilter1" endpointName="PlatoneWSService" />
</filterTable>
</filterTables>
</routing>
<client>
<!-- https://10.0.2.243:9006/Persistence -->
<endpoint address="https://10.0.2.243:9006/Persistence"
binding="customBinding" bindingConfiguration="platoneBinding"
contract="*" name="PlatoneWSService">
</endpoint>
</client>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
<system.net>
<settings>
<servicePointManager checkCertificateName="false" checkCertificateRevocationList="false"/>
</settings>
</system.net>
</configuration>
Dimensions for the buffer and message have to be "tested" (that is.. I chose a big number to make it works...)