Expose WCF Web service on the internet configuration - asp.net

I am trying to expose a webservice written in WCF, to the open internet but i am having trouble configuring it to be consumed from the external url.
The web service is hosted internally at https://ourportal.internaldomain.intra:9011/FrontEndWS and works well. We have exposed the webservice on https://www.internetdomain.com.mt/FrontEndWS however when accessing it from the external address, the soap URLs still referer to the internal address.
Our settings are as follows. We do not need to expose the webservice internally, only on the internet so this should simplify configuration.
<bindings>
<basicHttpBinding>
<binding name="LargeMessagingBinding" maxBufferSize="99999900" maxBufferPoolSize="524288000" maxReceivedMessageSize="99999900">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="99999900" maxBytesPerRead="99999900" maxNameTableCharCount="2147483647" />
<security>
<transport clientCredentialType="Basic" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<dataContractSerializer maxItemsInObjectGraph="6553600" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="false" />

In order to expose your web service to the external world, you would have the WCF service in a Virtual directory under a website in IIS.
Now your url "www.internetdomain.com.nt" would be mapped to a specific IP address (externally accessible) and this IP address is the IP addresss of your server on which the WCF service is exposed.
Any request on this IP is received by IIS and determines on how to serve the request.
If the above is fine then the URL for your WCF service would be:
http://www.internetdomain.com.nt/virtualdirectory/FrontEndWS
https://www.internetdomain.com.nt/virtualdirectory/FrontEndWS
For the https case your website would have the 443 https port mapped via Edit Bindings option and specifies the service certificate it needs to use.
Also you need to define your service with an endpoint in the web.config. Example shown below:
<bindings>
<basicHttpBinding>
<binding name="LargeMessagingBinding" maxBufferSize="99999900" maxBufferPoolSize="524288000" maxReceivedMessageSize="99999900">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="99999900" maxBytesPerRead="99999900" maxNameTableCharCount="2147483647" />
<security>
<transport clientCredentialType="Basic" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="SampleWCFService.Service1" behaviorConfiguration="default">
<endpoint address="" behaviorConfiguration="ServiceBehaviour" binding="basicHttpBinding" bindingConfiguration="LargeMessageBinding" contract="SampleWCFService.IService1"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<dataContractSerializer maxItemsInObjectGraph="6553600" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="false" />
Check the services element in the above configuration. Make sure that the namespace of the service is specified correctly.

I had the same problem and now figured out that it was because of the SSL offloader which was infront of the web server. Check with your admin group. We got rid of SSL offloader as we had to make the service up.
You can refer to the links below
http://blogs.msdn.com/b/distributedservices/archive/2010/06/01/ssl-offloader-using-wcf-4-0-routing-service.aspx
http://blogs.msdn.com/b/distributedservices/archive/2010/05/13/wcf-and-intermediate-devices.aspx
Also add host header for https
http://www.sslshopper.com/article-ssl-host-headers-in-iis-7.html

Related

WCF service call returns empty file / page

The problem:
When I'm calling my deployed WCF service, the browser downloads an empty svc file and does not show me the page with the service xml file.
The context:
I have to move the webapp hosting the WCF service to a new server. This service was working fine on the old server, that was running IIS.
The new server has 2 webservers running. IIS 8.5 and WAMP 2.5, because the server hosts an Php app and Jira.
The setup:
The WAMP server listens to the 80 port and then redirects to IIS, to a specific port, if needed. This is an example for the setup.
Wamp config (https-vhosts.confg):
<VirtualHost *:80>
ServerName site.de
ServerAlias www.site.de
<Proxy *>
Require all granted
</Proxy>
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / http://localhost:9050/
ProxyPassReverse / http://localhost:9050/
The service URL:
https://www.site.de/folder/service.svc
Service config:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="someBinding" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" maxBufferPoolSize="52428899">
<readerQuotas maxDepth="64" maxStringContentLength="81920" maxArrayLength="163840" maxBytesPerRead="40960" maxNameTableCharCount="163840" />
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="LargeServiceBehavior">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
<useRequestHeadersForMetadataAddress />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true" />
<services>
<service name="ExampleServices.ExampleService" behaviorConfiguration="LargeServiceBehavior">
<endpoint address="http://www.site.de/folder/service.svc"
binding="basicHttpBinding"
bindingConfiguration="someBinding"
contract="ExampleServiceModels.IExampleService" />
</service>
</services>
I have never worked with wamp before. And I don't have much experience with WCF settings also. Any ideas or tips would be highly appreciated.
EDIT
Using the wcf test client i get this:
Error: Cannot obtain Metadata from http://www.site.de/folder/ExampleService.svc If this is a Windows (R) Communication Foundation service to which you have access, please check that you have enabled metadata publishing at the specified address. For help enabling metadata publishing, please refer to the MSDN documentation at http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata Exchange Error URI: http://www.site.de/folder/ExampleService.svc Metadata contains a reference that cannot be resolved: 'http://www.site.de/folder/ExampleService.svc'. The requested service, 'http://www.site.de/folder/ExampleService.svc' could not be activated. See the server's diagnostic trace logs for more information.HTTP GET Error URI: http://www.site.de/folder/ExampleService.svc The document at the url http://www.site.de/folder/ExampleService.svc was not recognized as a known document type.The error message from each known type may help you fix the problem:- Report from 'XML Schema' is 'Root element is missing.'.- Report from 'DISCO Document' is 'Root element is missing.'.- Report from 'WSDL Document' is 'There is an error in XML document (0, 0).'. - Root element is missing.
You need to specify a MEX (meta data exchange) binding to expose you WSDL. Example (look at the address "mex"):
<service name="ExampleServices.ExampleService" behaviorConfiguration="LargeServiceBehavior">
<endpoint address="http://www.site.de/folder/service.svc" binding="basicHttpBinding"
bindingConfiguration="someBinding"
contract="ExampleServiceModels.IExampleService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
To get the wsdl type in the browser:
https://www.site.de/folder/service.svc?wsdl
Not sure this answer will help OP after almost 3 years. But it is more intended for #GothamLlianen. But if you want to access a WFC service on a HTTPS connection, you need to specify that binding explicitly.
Add this in the <system.serviceModel> node of the Web.Config
<bindings>
<webHttpBinding>
<binding name="HttpsBinding">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</webHttpBinding>
</bindings>
Then add the name, in this case "HttpsBinding" to the endpoint
<endpoint bindingConfiguration="HttpsBinding"
The complete node below for reference
<system.serviceModel>
<services>
<service behaviorConfiguration="ServiceBehaviour" name="MyProject.Api">
<endpoint bindingConfiguration="HttpsBinding" address="" behaviorConfiguration="web" binding="webHttpBinding" contract="MyProject.IApi" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
<serviceAuthorization principalPermissionMode="UseAspNetRoles" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Bare" />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<bindings>
<webHttpBinding>
<binding name="HttpsBinding">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</webHttpBinding>
</bindings>
</system.serviceModel>

WCF Services - Configuration web service binding exception

All,
Env:
Asp.net 4.0
IIS 7 (or greater)
WCF service consumed by SL component
Authentication:
Anonymous/Forms
When I attempt to browse to my WCF web service (using browser) I get the following exception on my web service, I need to get rid of this error:
The authentication schemes configured on the host ('IntegratedWindowsAuthentication') do not allow those configured on the binding 'BasicHttpBinding' ('Anonymous'). Please ensure that the SecurityMode is set to Transport or TransportCredentialOnly. Additionally, this may be resolved by changing the authentication schemes for this application through the IIS management tool, through the ServiceHost.Authentication.AuthenticationSchemes property, in the application configuration file at the element, by updating the ClientCredentialType property on the binding, or by adjusting the AuthenticationScheme property on the HttpTransportBindingElement.
I looked at ALL related posts and none of them help me.
I am not using any authentication or user/pwd transmission for my service.
The service I need to get working is consumed by Silverlight component and has this name in web.config file:
Htmls.WebStore.Services.WebStoreServices (ignore the other service).
Here's my web.config:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="WebStoreServices_InsecureTransport" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="4096" />
<security mode="None" />
</binding>
<binding name="basicHttpBinding" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647">
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="SitefinityWebApp.Sitefinity.Services.Content.EventsAspNetAjaxBehavior">
<enableWebScript />
</behavior>
<behavior name="EndpBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
<behavior name="Telerik.Sitefinity.Web.Services.LocalizationBehavior" />
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="Htmls.WebStore.Services.WebStoreServices">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="WebStoreServices_InsecureTransport" contract="Htmls.WebStore.Services.IWebStoreServices" />
</service>
<service name="SitefinityWebApp.Sitefinity.Services.Content.Events">
<endpoint address="" behaviorConfiguration="SitefinityWebApp.Sitefinity.Services.Content.EventsAspNetAjaxBehavior" binding="webHttpBinding" contract="SitefinityWebApp.Sitefinity.Services.Content.Events" />
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
The exception was caused by having incorrect permission on the folder where the xxxxx.svc file was. The folder was locked down using security permissions.

Problems with WCF Webservice and SSL

I've read lots of threads the last hours but I did not find a solution which is working for me :-(
So as already multiple other users I have problems calling a SVC-Webservice via SSL from my Windows Phone 7 application. On localhost it works fine. I've deployed the Webservice within my Webapplication. The service "MyService.svc" is in the root of the webapplication. On IIS I've only added HTTPS (from Startcom, using default Port 443) for this IP and made SSL required. I could open my web application and I could open the Webservice using any browser at http://mydomain.com/MyService.svc, from both server and local development machine. The page says I could call svcutil.exe https://mydomain.com/MyService.svc?wsdl. When I click on the link the data is display correct.
Now when I try to access it via WP7 app I always get the following error:
"There was no endpoint listening at https://mydomain.com/MyService.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details."
And inner details say: "The remote server returned an error: NotFound."
Here is the important part of my web.config. I don't know whether this is all required, as said I've copied it from multiple threads but at least in IE it works fine:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyBehavior">
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true" />
<dataContractSerializer maxItemsInObjectGraph="1073741824" />
<useRequestHeadersForMetadataAddress>
<defaultPorts>
<add scheme="https" port="443" />
</defaultPorts>
</useRequestHeadersForMetadataAddress>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MyBehavior" name="MyNamespace.MyService">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="HttpsBinding"
contract="MyNamespace.IMyService">
</endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="HttpsBinding">
<readerQuotas maxStringContentLength="2147483647" />
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<!-- <serviceHostingEnvironment multipleSiteBindingsEnabled="true" /> -->
Many thanks!

Is there a way to pass domain credentials from the originating browser in webHttpBinding wcf service?

Is there a way to pass domain credentials from the originating browser in webHttpBinding WCF service?
I'm thinking this should be possible as when I log into any aspx page with Windows Authentication enabled in IIS, I can get the calling user's domain credentials. How would I setup my WCF service in such a manner? Currently the user identity I get in the WCF service are those of the app pool the svc is running under?
EDIT
I don't have .NET 4 -- My configuration file is below, but I still get an error:
Security settings for this service require 'Anonymous' Authentication
but it is not enabled for the IIS application that hosts this service.
Should I explicitly enable Anonymous for that path in IIS? I think this would undo my efforts to get the domain name.
<behaviors>
<endpointBehaviors>
<behavior name="Awesome.Project.OperationsBehavior">
<enableWebScript />
</behavior>
</endpointBehaviors>
</serviceBehaviors>
<behavior name="Awesome.Project.OperationsServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="Awesome.Project.OperationsServiceBehavior"
name="Awesome.Project.Operations">
<endpoint address="" binding="webHttpBinding"
contract="Awesome.Project.Operations"
behaviorConfiguration="Awesome.Project.OperationsBehavior"
bindingName="windowsSecurityWebHttpBinding">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<!--<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange" />-->
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="windowsSecurityWebHttpBinding">
<security mode="Transport">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</webHttpBinding>
</bindings>
You need to turn on authentication in the service - assuming .NET 4 add the following to your config
<bindings>
<webHttpBinding>
<binding>
<security mode="Transport">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</webHttpBinding>
</bindings>
for .NET 3.5 or 3.0 you need
<bindings>
<webHttpBinding>
<binding name="webBindingConfig">
<security mode="Transport">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</webHttpBinding>
</bindings>
<services>
<service ...>
<endpoint bindingConfiguration = "webBindingConfig" binding="webHttpBinding" .../>
</service>
</services>
Edit for additional questions:
WCF will generally not pass credentials over non secured transports - that's why mode="Transport" is important. If you got rid of it its the same as Mode="None" for WebHttpBinding
If the site is considered to be in the intranet zone then IE will pass the user's credentials automatically. However, non-IE browsers will not and so will hit the site anonymously before getting a 401 and then sending the credentials. The intial request requires anonymous access to be supported in IIS as WCF handles the authentication mechanism
If you need to get hold of HttpContext you can use Asp.NET Compatibility. However in WCF you can use ServiceSecurityContext.Current.PrimaryIdentity.Name to get the authenticated user
How to: Impersonate the Original Caller in WCF Calling from a Web Application gives a walkthrough on how to do this.

Set up wcf service for http and https and also add username/password to its access

I am kinda new to WCF and the setting up of service and have 2 questions. My first question I have a service that will be accessed via https on a web server. However locally on my local IIS7, it will be accessed via http as https is not available. How can I set up a service to be accessed by both?
My second question is regarding how I can set up a service that requires a username and password to be accessed. The service that I have in place I dont want methods within it to be accessed unless the calling application has the rights to do so?
Here is an example of the relevant area of my web.config file.
<system.serviceModel>
<bindings>
<webHttpBinding>
<!-- standard AJAX binding that supports SSL -->
<binding name="TransportSecurity">
<security mode="Transport" />
</binding>
<!-- standard AJAX binding for HTTP only -->
<binding name="NoSecurity">
<security mode="None" />
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="EndPointBehavior">
<enableWebScript />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceDebug httpHelpPageEnabled="false" httpsHelpPageEnabled="false" includeExceptionDetailInFaults="true" />
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<services>
<service behaviorConfiguration="ServiceBehavior" name="ServiceName">
<endpoint address=""
behaviorConfiguration="EndPointBehavior"
binding="webHttpBinding"
bindingConfiguration="NoSecurity"
contract="App.Service.ServiceName" />
</service>
</services>
<diagnostics>
<messageLogging logMessagesAtTransportLevel="true" logMessagesAtServiceLevel="false" logMalformedMessages="true" logEntireMessage="false" maxSizeOfMessageToLog="65535000" maxMessagesToLog="500" />
</diagnostics>
</system.serviceModel>
In this config, the service is set up for http only and not username/password applied to it.
You can add the username password configuration to your bindings:
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
and
<security mode="TransportCredentialOnly"> <!-- This means http + credential -->
<transport clientCredentialType="Basic" />
</security>
As for authorization, there are a bunch of options. The very simplest is to apply a custom username password validator (artibtrary example taken from Link):
<serviceBehaviors>
<behavior name="CustomValidator">
<serviceCredentials>
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType=
</behavior>
</serviceBehaviors>
At a more sophisticated level, read up on the ServiceAuthorizationManager:
http://msdn.microsoft.com/en-us/library/system.servicemodel.serviceauthorizationmanager.aspx

Resources