WCF Web Api with HTTPS - wcf

Just to put some context.
ASP.NET MVC2
Web API 5
IIS 7
I am trying to use the WCF Web API and as soon as I enable HTTPS, it stop working.
Things I noticed:
My API call I do through jquery, and I have something like this as the url:
http://www.domain.com/api/serviceApi/SetForeignToken?token=ASDAS-ASDAS-ASDASD-ASDASDAS&foreignToken=AS123ASD
When I use the API test UI I through:
https://www.domain.com/api/serviceApi/Test
I see for the test url:
https://devserver.ad.domain.com/api/serviceapi/SetForeignToken?token=ASDAS-ASDAS-ASDASD-ASDASDAS&foreignToken=AS123ASD
It just seems od the it resolves the DNS to the machine name instead of keeping the normal DNS, as it did before without HTTPS.
Does anyone know how to configure the API to make this work unde HTTPS, or is it even possible?
Thanks,
PS. The Development Enviroment has a self-signed certificate while the production will have a real certificate.

Yes, WCF Web API supports HTTPS. I believe there are a couple of ways to do this (including a code option). I only wanted https enabled on one server so I did this in my web.config:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true">
<baseAddressPrefixFilters>
<add prefix="https://subdomain.example.com"/>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
<bindings>
<webHttpBinding>
<binding>
<security mode="Transport" />
</binding>
</webHttpBinding>
</bindings>
</system.serviceModel>

Thanks guys. spent whole day figuring out this. Just added the code in web.config and it worked.

Related

How do I set the proxy in webhttpbinding configuration to use fiddler

I'm trying to setup my Web service client to use fiddler proxy by setting it in the webhttpbinding configuration file as follows:
<bindings>
<webHttpBinding>
<binding name="RestBinding" proxyAddress="http://localhost:8888"
useDefaultWebProxy="false">
</binding>
</webHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:2172/RestServiceImpl.svc"
binding="webHttpBinding" behaviorConfiguration="RestService"
bindingConfiguration="RestBinding"
contract="IWS.IRestServiceImpl" name="Rest"/>
</client>
This doesn't seem to work. I don't see anything logged in fiddler when calling the webservice from the client. I know the call is being made because I get a response back from the service.
I can't seem to figure out what I'm doing wrong.
Any help is appreciated!
Thanks!!
The .NET Framework does not send requests for "localhost" to any proxy, including Fiddler. To workaround this, try to use your machine name instead as the endpoint address (e.g. http://mymachine:2172/RestServiceImpl.svc).
Also, take a look on Using Fiddler with IIS7 Express

File-less WCF activation results in "zero application (non-infrastructure) endpoints..." exception

I've got a WCF service that's using file-less activation:
<bindings>
<basicHttpBinding>
<binding transferMode="Streamed">
<security mode="Transport"/>
</binding>
</basicHttpBinding>
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true">
<serviceActivations>
<add relativeAddress="RulesService.svc"
service="Big.Company.RulesService.Service, RulesService" />
</serviceActivations>
</serviceHostingEnvironment>
On some machines, I see the following exception:
Service
'Big.Company.RulesService.Service' has
zero application (non-infrastructure)
endpoints. This might be because no
configuration file was found for your
application, or because no service
element matching the service name
could be found in the configuration
file, or because no endpoints were
defined in the service element.
As far as I can tell, .svc is correctly mapped to the .NET 4.0 activation module. The application is in the "ASP.NET v4.0" application pool, which is configured for .NET v4.0, using the integrated pipeline.
If I remove the Web.config file, I get a 404 error. If I rename the bin\RulesService.dll file, I get a 'service not found' exception.
What's wrong with it?
Update: It appears to be a problem when turning on SSL. If I connect using HTTPS, it's fine, until I turn on 'Require SSL' in IIS.
An afternoon of using Reflector led me to the ConfigLoader.AddDefaultEndpoints method, which looks at the ProtocolMappingSection of the config file to work out which default endpoints to add.
It appears that HTTPS doesn't set up this section implicitly.
I solved it (with a hint from something I'd seen earlier in the day) by adding the following to my Web.config file:
<protocolMapping>
<add scheme="https" binding="basicHttpBinding"/>
<add scheme="http" binding="basicHttpBinding"/>
</protocolMapping>
I had only an HTTPS binding in IIS for my service and adding an http binding solved my problem. Without any file configuration.
(Sorry for the french screenshot
)
Adding the following to the config file and removing the http binding in IIS also solved my problem.
<protocolMapping>
<add scheme="https" binding="basicHttpBinding"/>
</protocolMapping>
I had the identical problem at work and it was a permissions issue.

Securing WCF hosted inside public MVC2 App

I've got a WCF service that is to be called by an application hosted on the web server (for the short-medium term, we'll only need a single web server so disregard scalability issues)
The web server serves a public website. at example.com
The WCF service exposes calls which amongst other things run jobs and provide certain admin functionality not supported by the web model eg long running database operations.
The WCF service has to be hosted inside the web site as it uses compatibility mode to take advantage of the Asp.Net http(s) pipeline - specifically, the service can generate emails and the emails are templated using MVC. One side-effect of this is that the call has to use the publicly visible hostname eg https://example.com/JobService.svc so that links in emails point to example.com as opposed to localhost or similar.
Obviously, I don't want the general public to be able to kick off jobs/admin tasks so I want to secure the WCF service.
I can only use https as opposed to net.tcp or similar for the binding thanks to relying on the Asp.net http pipeline.
I have to bind to the publicly accessible IP address to be able to use the proper hostname (unless someone knows a way around this?)
I can't use kerberos/NTLM as the server isn't on a domain (and NTLM is weak anyway)
I can't use certificates as it complains:
The SSL settings for the service 'SslRequireCert' does not match those of the IIS 'None'.
NB: I don't quite understand this as the website itself is only served via https. http simply returns a redirect to the same page via https.
(An interesting issue I'm having is that although the mex is served via https, the URLs inside the WSDL use http. I'm assuming this is a side-effect of not being able to set up TLS properly on my service so it thinks it's http even though it also responds on https)
So, I'm running out of ideas for how to secure my service. I could, of course, from within the service itself examine the request and determine if it comes from an IP used by the current server - but this feels very nasty and I'm effectively ignoring the work of experts and trying to put something in its place - Not a very good place to start.
Can anyone suggest a way to limit access to this service to processes on the local machine?
I've attached my current config below. (This is currently giving me the certificate error mentioned above)
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="WebJobServiceHTTPBinding" openTimeout="00:10:00"
sendTimeout="00:10:00">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"
aspNetCompatibilityEnabled="true">
<serviceActivations>
<add relativeAddress="WebJob.svc"
service="MyApp.WebJobService"
factory="MyApp.WCFDIServiceHostFactory" />
</serviceActivations>
</serviceHostingEnvironment>
<services>
<service behaviorConfiguration="WebJobServiceBehavior" name="MyApp.WebJobService">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="WebJobServiceHTTPBinding"
name="HTTPEndpoint" contract="MyApp.JobService.Common.IWebJobService" />
</service>
</services>
<standardEndpoints>
<mexEndpoint>
<standardEndpoint name="WebJobServiceMex" />
</mexEndpoint>
</standardEndpoints>
<behaviors>
<serviceBehaviors>
<behavior name="WebJobServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<serviceCertificate findValue="[Thumbprint of x509 cert used by website for SSL]"
storeName="Root" x509FindType="FindByThumbprint" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
"Can anyone suggest a way to limit access to this service to processes on the local machine?"
Run your service in a different web site in IIS, if you're not already.
You could bind your service in IIS to the internal network IP address which would allow internal LAN clients to access the service but not external clients.
Another binding option is to bind to a port that is not open on your firewall in order to allow access from internal clients only. Even better, bind to a port that is not open on your firewall, and bind to the internal LAN IP.
You could also try binding to IP address 127.0.0.1.
In the end, I was forced to implement my own Authentication system. This was relatively simple as authenticatio implied authorization - ie no permission levels. That said, I'm still unhappy at the solution and will change it if another option presents itself.

WCF call with windows authentication

We have a system where the users access a web server, the web server then calls a WCF service.
We would like the call to the WCF service to be made in the security context of the windows identity of the application pool on the web server.
What is the best way to do this? Can it be done purely through configuration in the web.config file.
Thanks
Shiraz
Yes, you should be able to do this, all in config:
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="WinAuth" mode="Transport">
<transport clientCredentialType="Windows" />
<bindings>
</netTcpBinding>
</bindings>
</system.serviceModel>
Of course, depending on your binding, you'd have to use a different tag under the <bindings> parent node - and of course, not all bindings support all security modes.....
In your endpoint, use the appropriate binding and then just reference this config:
<endpoint name="WCFService" address="......."
binding="netTcpBinding"
bindingConfiguration="WinAuth"
contract="......" />
That should do it! And of course, if you need message security instead of transport security, you can do that, too.
In your WCF service method, you can check to see whether or not the Windows credentials have been sent over, and what they are, by checking:
ServiceSecurityContext.Current.WindowsIdentity
This will be NULL if you don't have a Windows caller, otherwise it will show who called you.
Marc

WCF Security - how to allow all callers to this url?

I have a WCF service self-hosted in a windows service environment that works fine over http; over https I am unable to get to one URL without seeing the windows login prompt when running the silverlight application (or just opening the page in IE). I am using the IPolicyRetriever interface to ensure that the ClientAccessPolicy.xml file is found for the Silverlight app. This is working correctly.
The service in question has two endpoints defined:
<service behaviorConfiguration="defaultBehavior" name="WCFServices.Scheduler">
<endpoint address="WCFServices/Scheduler/" binding="wsHttpBinding" bindingConfiguration="dBinding" contract="WCFServices.IScheduler" />
<endpoint address="" binding="webHttpBinding" contract="WCFServices.IPolicyRetriever" behaviorConfiguration="PolicyBehavior" bindingConfiguration="dBinding" />
<host>
<baseAddresses>
<add baseAddress="https://myservername.org/" />
</baseAddresses>
</host>
</service>
If I go to the https://myservername.org/ I see the test service frontend (with a link to the wsdl). This is exposing the root IPolicyRetriever instance that the Silverlight app uses to pull down the policy file. I can load this and other URLs that expose the WCF service without any login prompts. BUT if I go to https://myservername.org/WCFServices/Scheduler/ in IE 8 I am greeted with a windows login. If I reset the security settings on the service and client to use http, I am able to do go to the latter url without the login prompt, and the silverlight app functions as expected. I suspect it has something to do with this WCF service being the only one with two endpoints defined (this windows service hosts 5 other WCF services, all of which only have 1 endpoint defined). Am I missing some authorization rules? I don't understand how that can be because all the other services load without prompts.
I would appreciate any help. I need the full https://myservername.org/WCFServices/Scheduler/ to serve the WCF service without asking for a login. Thanks for taking the time to read this.
As far as security, I only have this as my binding:
<binding name="dBinding" maxBufferPoolSize="524288" maxReceivedMessageSize="6553600">
<security mode="Transport">
</security>
</binding>
This issue was resolved by adding these lines to my security binding:
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None"/>
</security>
...but that led to a host of other issues, all of which I've been able to handle thanks to WCF logging. If you run into a NOT FOUND (400) error when debugging your WCF service, don't believe it. Turn on server side debugging and pour through the generated log files -- you'll get to the bottom of it.
I should also note that I've found the second endpoint to return a bad request (400) when opening in a web browser, and this is BY DESIGN. The first endpoint will list all additional endpoints in its wsdl, and you can still use any of them in a proxy generating tool. Don't worry if you're getting a bad request error when trying to access them directly in a browser.