Security Exception calling Reporting Services from a Windows Service - wcf

I am trying to call the web service for SQL Server Reporting Services from a Windows Service. I can successfully make the call from an Asp.Net MVC website, but when I try to use exactly the same code from a Windows service (with seemingly the same WCF configuration), I get the following error...
Inner Exception: System.ServiceModel.Security.MessageSecurityException
- The HTTP request is unauthorized with client authentication scheme 'Ntlm'. The authentication header received from the server was 'NTLM'.
Inner Exception: System.Net.WebException - The remote server returned
an error: (401) Unauthorized.
BOTH the application pool for my Asp.Net MVC site AND the Windows Service are set up to use the "Network Service" user.
Here is my WCF configuration in the config file...
<system.serviceModel>
<serviceHostingEnvironment
aspNetCompatibilityEnabled="true"/>
<bindings>
<basicHttpBinding>
<binding name="ReportExecutionServiceSoap" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
<readerQuotas maxArrayLength="2147483647"
maxStringContentLength="2147483647"
maxBytesPerRead="2147483647"
maxDepth="2147483647"
maxNameTableCharCount="2147483647"
/>
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm" proxyCredentialType="None" realm=""/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://myserver/ReportServer_MSSQL2008/ReportExecution2005.asmx"
binding="basicHttpBinding" bindingConfiguration="ReportExecutionServiceSoap"
contract="ReportService.ReportExecutionServiceSoap" name="ReportExecutionServiceSoap" behaviorConfiguration="ImpersonationBehaviour" />
</client>
<behaviors>
<endpointBehaviors>
<behavior name="ImpersonationBehaviour">
<clientCredentials>
<windows allowedImpersonationLevel="None" allowNtlm="true"/>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
I have tried all the different "allowedImpersonationLevel" and have tried it without this behaviour defined at all.

Make you have referenced all codes need to run the windows app at som point.

Related

WCF metadata shows incorrect service URI on HTTPS

Using .NET 4.7.1 and minimal WCF configuration, the WSDL, when accessed from HTTPS, shows a HTTP address, and shows the incorrect host unless port 80 is enabled in the configuration.
This service should only be available on HTTPS, which will be enforced by a firewall rule further along.
My configuration looks like this
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpsGetEnabled="True"/>
<useRequestHeadersForMetadataAddress/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
And the result looks like this in a browser (demonstrating incorrect scheme and incorrect host. Sorry that I must block out most of this, but you should be able to get what I'm saying...)
resulting wsdl
I understand that "useRequestHeadersForMetadataAddress" tells WCF that I indeed want the WSDL right next to the service. I assumed it also should be able to handle the same intentions for scheme.
Any thoughts?
My issue was assuming I didn't need to specify binding configuration. Without binding configuration, I don't think WCF can figure out you want HTTPS bindings, and all problems flowed from there.
So, unfortunately, my web.config grows to twice its size!
<basicHttpBinding>
<binding name="SecureServiceBinding" closeTimeout="00:02:00" openTimeout="00:02:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="20480000" maxBufferSize="10240000" maxReceivedMessageSize="10240000" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true" messageEncoding="Text">
<readerQuotas maxDepth="100" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="2147483647"/>
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
<message clientCredentialType="UserName" algorithmSuite="Default"/>
</security>
</binding>
</basicHttpBinding>

WCF returns 404 for large request, maxReceivedMessageSize="2147483647"

Our WCF service on large request returns following error:
"System.ServiceModel.EndpointNotFoundException: There was no endpoint listening at http://xxx.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details. ---> System.Net.WebException: The remote server returned an error: (404) Not Found.
For small requests everything works fine and I am getting correct response from WCF service, the issue is only with large requests.
Settings on the client are as follow:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_ITestService" openTimeout="00:05:00" sendTimeout="00:05:00" maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647" >
<readerQuotas maxDepth="2147483647" maxBytesPerRead="2147483647" maxArrayLength="2147483647" maxStringContentLength="2147483647"
maxNameTableCharCount="2147483647"/>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:33333/TestService.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ITestService" contract="TestService.ITestService" name="BasicHttpBinding_ITestService" />
</client>
</system.serviceModel>
The settings of the WCF service:
<bindings>
<basicHttpBinding>
<binding maxReceivedMessageSize="2147483647" receiveTimeout="00:10:00" sendTimeout="00:10:00" maxBufferSize="2147483647" maxBufferPoolSize="2147483647">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483646" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
What can be the issue?
In this case, the error was not with WCF but with the IIS settings.
The Message was to large for IIS, I have added "maxAllowedContentLength" to the web.config on the server.
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="2200000000"/>
</requestFiltering>
</security>
The error message was misleading.
In my case, it was not working even after trying all solutions and setting all limits to max. In last I found out that a Microsoft IIS filtering module Url Scan 3.1 was installed on IIS/website, which have it's own limit to reject incoming requests based on content size and return "404 Not found page".
It's limit can be updated in %windir%\System32\inetsrv\urlscan\UrlScan.ini file by setting MaxAllowedContentLength to the required value.
For eg. following will allow upto 300 mb requests
MaxAllowedContentLength=314572800

How to enable HTTPS in WCF service

I have hosted my service on IIS.
Hosted service has applied SSL certificate and on browse of URL, it appears with HTTPS.
But, when i do consume this URL into client application (ASP.NET WEB Application) then, it allows to add https//domain/service.svc but, on client configuration, it appears the URL as http and not https. when do manual change then, it gives error as follow: The provided URI scheme 'https' is invalid; expected 'http'.
Below is the WCF service configuration (hosted on IIS):
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="customBehavior">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="basicBindingConfiguration" closeTimeout="00:05:00"
openTimeout="00:05:00" receiveTimeout="00:10:00" sendTimeout="00:05:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
</security>
</binding>
</basicHttpBinding>
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" minFreeMemoryPercentageToActivateService="0" />
<services>
<service name="Administrator.OAP.CRMServices.CRMServices"
behaviorConfiguration="customBehavior">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="basicBindingConfiguration"
contract="Administrator.OAP.CRMServices.Contracts.ICRMServices" />
</service>
</services>
can any one please guide me what is the problem or changes require here to consume this service with HTTPS only ?
Your binding has this:
<security mode="None">
Which means your service is not expecting to use security of any kind. HTTPS is transport authentication, so you need to set:
<security mode="Transport">
The following link includes useful information about setting up transport security in WCF: http://msdn.microsoft.com/en-us/library/ms733043(v=vs.110).aspx

Calling a webservice from a C# dll from within CLASSIC ASP

I'm a windows dev with very little knowledge of web applications and ASP. I'm trying to create a C# dll (which is making a webservice call) for someone, that is being called from a CLASSIC ASP app.
It all started from a WinForms test app that successfully loaded a WSDL and called that web service. Now the requirement is to take the test app functionality, move it to a dll and call that dll from the ASP app. I naively left the appconfig file there, and when that dll was called, he got this well known error:
Could not find default endpoint element that references contract Service1.MyService 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.
I understand that classic asp doesn't have config files - I read a lot of posts about it, and most of the relevant ones mention to use BasicHTTPBinding and provide an endpoint address on the fly. How do I do that? Any examples?
I saw this answer:
All I needed to do is to create a BasicHTTPBinding and provide an endpoint address on the fly.Then create a new instance of the web service using the created binding and endpoint address.
But i'm not sure how to do it.
This is the appconfig that worked for the winforms app:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IMyService">
<security mode="Transport">
<transport clientCredentialType="Certificate" proxyCredentialType="None"
realm="" />
</security>
</binding>
<binding name="BasicHttpBinding_ICustomerService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://MyService.svc"
behaviorConfiguration="custom" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IMyService" contract="MyService.IMyService"
name="BasicHttpBinding_IMyService" />
</client>
<behaviors>
<endpointBehaviors>
<behavior name="custom">
<customInspector />
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="customInspector" type="CustomBehaviors.CustomBehaviorExtensionElement, CompeteDataServiceTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
</system.serviceModel>
You will need to configure the service through code, as there is no config file in this case. See Configuring WCF Services in Code.

WCF configuration with https

I'm not having any success setting up HTTPS in my development environment on an existing WCF service. The service has been fine with http. I'm using the hosts file to redirect to localhost, which has been working for http.
My web service configuration
<services>
<service name="EnfieldWebService">
<endpoint address="https://enfieldwebservice.devserver.int/EnfieldWebService.svc"
binding="basicHttpBinding" bindingConfiguration="transportSecurity" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="transportSecurity">
<security mode="Transport">
</security>
</binding>
</basicHttpBinding>
</bindings>
Client configuration
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IEnfieldWebService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://enfieldwebservice.devserver.int/EnfieldWebService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IEnfieldWebService"
contract="HttpsEnfieldService.IEnfieldWebService" name="BasicHttpBinding_IEnfieldWebService" />
</client>
And Unit Test Results:
System.ServiceModel.EndpointNotFoundException: There was no endpoint listening at
https://enfieldwebservice.devserver.int/EnfieldWebService.svc that
could accept the message. This is often caused by an incorrect address
or SOAP action. See InnerException, if present, for more details. --->
System.Net.WebException: The remote server returned an error: (404)
Not Found.
Used WCF Configuration Editor to rewrite essentially the same configuration. All that it removed was
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
Turns out this feature is only compatible with http, and breaks https.