How to enable Windows Authentication and NetTCPBinding WCF webservice on IIS7? - wcf

I am attempting to set up a web service that uses windows authentication and NetTCPBinding on IIS 7. currently I am getting this error when I attempt to access the wysdl
"Security settings for this service require 'Anonymous' Authentication but it is not enabled for the IIS application that hosts this service. "
The relevant sections of my Config file look like this...
<behaviors>
...
<serviceBehaviors>
<behavior name="WCFHostService.MyServiceBehavior">
<serviceMetadata httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="UPMC.ISD.EADIS.ACO.ACOServiceConcept">
<endpoint name ="TCP_Binding"
address=""
binding="netTcpBinding"
contract="UPMC.ISD.EADIS.ACO.ACOServiceConcept.IACOService"/>
<endpoint name="mexHttpbinding"
contract="IMetadataExchange"
binding="mexTcpBinding"
address="mex" />
</service>
</services>
How do I get the "security settings" for my service to align to allow me to access this service? I also just read that you can get rid of the error by getting rid of your mex binding endpoints or by enabling anonymous authentication. But how do you get your wsdl if you don't have mex binding? Well I guess I will give that a go, but if you have any other advice I will most certainly take it.
Thanks.

According to WCF NetTcpBinding Security - how does it work?, the default security setting for NetTCP is Windows Authentication. It sounds like one or two things might be the issue:
Ensure Windows Authentication is enabled (in the IIS Management Console under Authentication - same place where you find the switch for Anonymous Authentication as in #Joel C's answer).
You might want to try specifying the windows account credentials when you create the client proxy, in case the account running the client is unable to authenticate.
Are the client and the server in the same domain?

Have you verified that Anonymous Authentication is enabled in the IIS application where you're hosting your service? In the IIS management console, browse to the site and application where your service is being hosted. Then make sure you have the "Features View" selected, and select the "Authentication" option. You should see various forms of authentication (anonymous, Windows, ASP.NET Impersonation, etc.) and each should say either enabled or disabled next to it.

Related

WCF net.tcp SSL, certificate and username + password authentication

I want to build a client-server, WPF-WCF application that should fulfill the following requirements:
Fast
Secured communication between clients and server
If an user wants to use the client application, he should have a certain certificate installed on his machine and also provide a valid username/password pair
Everything should happen over the internet
So I started working on it two days ago and, after going through almost every example/tutorial I could find that got close to my scenario, I managed to build a WCF service with net.tcp binding that is hosted in IIS (8 I think) and exposes its metadata through a mex endpoint and a tiny little client console application that can connect to the service and call its one and only HelloWorld method.
All was well until I started trying to add certificate based security. I tried countless configuration combinations and techniques but still couldn't get anything working.
At first, I got some specific error messages telling me various things about the server or client certificates not being valid, trusted, or good for anything in any way.
Then I followed these articles, since I need self-signed certificates while developing.
http://msdn.microsoft.com/en-us/library/ff647171.aspx
http://msdn.microsoft.com/en-us/library/ms733813(v=vs.110).aspx
http://msdn.microsoft.com/en-us/library/ff648498.aspx
Then, I started getting more and more vague error messages until I gave up.
It might very well be that I misunderstood how WCF works since I don't have that much experience with it.
The configuration that worked is this:
Service configuration
<configuration>
<system.web>
<httpRuntime targetFramework="4.5.1"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="TcpServiceBehaviour">
<serviceMetadata />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="TcpServiceBehaviour" name="WcfTcpServer.TcpService">
<endpoint address="net.tcp://serverName/wcftcpserver/TcpService.svc" binding="netTcpBinding" name="TcpServiceEndpoint" contract="WcfTcpServer.ITcpService" />
<endpoint address="SME" binding="mexTcpBinding" bindingConfiguration="" name="ServiceMetadataEndpoint" contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
</configuration>
Client configuration
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1" />
</startup>
<system.serviceModel>
<client>
<endpoint address="net.tcp://serverName/wcftcpserver/TcpService.svc" binding="netTcpBinding" contract="WcfTcpServer.ITcpService" name="TcpServiceEndpoint">
<identity>
<servicePrincipalName value="host/serverName.smth.smthElse.ro" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>
That's, as you can see, the certificate-less configuration.
Any step that I take towards using my self-signed certificates within this configuration, breaks the applications.
I use .NetFramework 4.5.1 for everything.
I would very much appreciate help with this problem. I can provide additional configurations I tried, if needed.
Is this even possible or am I trying in vain?
Thank you!
In short, yes, you can support multiple client credentials using what are known as Supporting Tokens.
From the linked article:
The example adds an X.509 binary security token in addition to a
username security token. The token is passed in a WS-Security message
header from the client to the service and part of the message is
signed with the private key associated with the X.509 security token
to prove the possession of the X.509 certificate to the receiver. This
is useful in the case when there is a requirement to have multiple
claims associated with a message to authenticate or authorize the
sender.
On the topic of using NetTcpBinding over the internet:
NetTcpBinding is generally recommended for intranet scenarios. It is advised by much of what I have read to either use WsHttpBinding and BasicHttpBinding for internet scenarios depending on your requirements. If security is a top concern of yours - the recommended choice is WsHttpBinding with Message level security.
Guidelines on choosing a binding for an internet scenario: Internet Binding Scenarios.

Consuming a WCF hosted as Windows Service

I have a WCF Service (with installer) that I have built and installed in Windows Services. Opened up Admin Tools, Services, and started the service without a problem.
So now I'm beginning a new project (a simple Windows forms app). I want to consume my new WCF, but have no idea how. I can't seem to add a reference / add a service reference to it.
Any help would be greatly appreciated.
Thanks,
Jason
When the Windows service hosting your WCF service is up and running and properly configured, you should be able to use either Visual Studio's Add Service Reference or the command-line svcutil tool to connect to that service.
Just type in the address where the service lives.
This requires that your service has metadata exchange enabled (as a service behavior) as well as provides at least one MEX (Metadata Exchange) endpoint in its config. Do you have those available??
Service behavior:
<behaviors>
<serviceBehaviors>
<behavior name="mex">
<serviceMetadata />
</behavior>
</serviceBehaviors>
</behaviors>
and then your service must reference this configuration.
Service config:
<services>
<service name="YourService"
behaviorConfiguration="mex"> <!-- reference the service behavior with the serviceMetadata element ->
<endpoint .... (your regular endpoint here) />
<endpoint name="mex"
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>

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.

Azure WCF Service Consume Azure WCF Service

I current have a solution with an Azure WCF service and a Windows Phone 7 project. I can run the development fabric locally and browse to the url (http://127.0.0.1:81/API/V1.svc) of my service fine. When I do Add Service Reference from the Windows Phone application it will discover the service fine, but when I try to view the methods on the service I get the error "Unable to launch the ASP.NET Development Server because port '50149' is in use." If I click OK I get "There was an error downloading metadata from the address. Please verify that you have entered a valid address."
I don't quite understand why it is discovering it on port 50149 since I browse to it on port 81 but I tried using port 81 when adding the service and I got
There was an error downloading 'http://localhost:81/API/V1.svc'.
Unable to connect to the remote server
No connection could be made because the target machine actively refused it 127.0.0.1:81
Metadata contains a reference that cannot be resolved: 'http://localhost:81/API/V1.svc'.
There was no endpoint listening at http://localhost:81/API/V1.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
Unable to connect to the remote server
No connection could be made because the target machine actively refused it 127.0.0.1:81
If the service is defined in the current solution, try building the solution and adding the service reference again.
Here is my service model section
<system.serviceModel>
<services>
<service name="DocDemon.API.V1">
<endpoint name="basicHttpBinding" binding="basicHttpBinding" contract="DocDemon.API.IV1" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<bindings>
</bindings>
</system.serviceModel>
Do I need to defined and end point in here?
Does it have something to do with the WP7 project and the Azure WCF being in the same solution? (Do I have to have the WCF running when I trying to add service reference from the WP7 app?)
I moved the WP7 Application into its own solution and then it was able to detect the web service fine when that application was running in the local DevFabric. The WP7 application was just unable to find it when they were in the same solution.
Have you looked at the WCF Azure Samples known issues on the MSDN Code Gallery? There's a subtlety around metadata and a behavior tweak needed. Hopefully this helps.
In my WCF running in Azure I configure endpoints in two places (my example defines a secure ssl endpoint on port 443):
1st time in web.config to define endpoints contracts:
<system.serviceModel>
<services>
<service
behaviorConfiguration="CustomValidationBehavior"
name="ServiceName">
<endpoint
binding="wsHttpBinding"
bindingConfiguration="MembershipBinding"
name="bindingName contract="InterfaceName" />
Afterwards, you also must make sure that Azure exposes your service thru its own endpoints in ServiceDefinition.csdef:
<InputEndpoints>
<InputEndpoint name="HttpsIn" protocol="https" port="443" certificate="CertName" />
</InputEndpoints>
You cannot use a reference to that port if it is not running, no metadata will be found.
I would say move your server project to IIS instead of Casini since that's where it'll run while on the Azure platform.
I did have some issues playing with Azure and Casini that did not happen on IIS.

WCF Deployment to IIS 6 Results in 403 Permission Error

I've never deployed a WCF service to IIS 6 before. I've got a service that I'm deploying to IIS 6 by using the default configuration as part of the WCF project. I since simplified the configuration thinking that might have been the issue. Here is the error I'm getting if I browse to the service in a browser:
HTTP Error 403.1 - Forbidden: Execute
access is denied.
My configuration now looks like this:
<system.serviceModel>
<services>
<service name="MyCompany.WebServices.MyService">
<endpoint address="" binding="basicHttpBinding" contract="MyCompany.WebServices.IMyService" />
</service>
</services>
</system.serviceModel>
If I try adding it as a reference in ASP.NET MVC, I get the following:
There was an error downloading
'http://ws.mycompany.com/MyService.svc'.
The request failed with HTTP status
403: Forbidden. Metadata contains a
reference that cannot be resolved:
'http://ws.mycompany.com/MyService.svc'.
The HTTP request was forbidden with
client authentication scheme
'Anonymous'. The remote server
returned an error: (403) Forbidden. If
the service is defined in the current
solution, try building the solution
and adding the service reference
again.
Any ideas what might be going on?
UPDATED:
It appears to be a configuration issue on my IIS 6 box. I'd assume this because I've created a brand new ASP.NET 3.5 WCF Application and deployed it to a new URL at http://ws.unitedoneresources.com/Service1.svc. If I try to call that service, I get the same HTTP Error listed above. The entire service configuration is the following:
<system.serviceModel>
<services>
<service name="WcfService1.Service1" behaviorConfiguration="WcfService1.Service1Behavior">
<!-- Service Endpoints -->
<endpoint address="" binding="wsHttpBinding" contract="WcfService1.IService1">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WcfService1.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>
</system.serviceModel>
Again, this is a brand new ASP.NET 3.5 WCF Application so I haven't modified anything on the project itself.
I wacked the I wacked the website, installed WCF on IIS 6 (using ServiceModelReg.exe /i /x at a command prompt), and redeployed. It worked!
Thanks!
Found this question searching for a solution to the same problem. I had forgotten to changes permissions to 'Scripts and Executables' on the services directory. I was on II7
You don't really give us a lot to go on here - what's missing are the server side configuration bits that show us how you set up security - can you please update your question and show us everything inside the <system.serviceModel> tag on your server side config and on your client calling the server??
Just guessing from the system defaults, using the basicHttpBinding would result in a default security setting of nothing - and it would appear as if your server-side config requires some form of security. It almost seems as if your security settings are out of sync, thus resulting in this error.
Another point is: how did you set up the IIS side? Did you create a virtual directory for your service? Basically, when hosting in IIS, your service URL is determined by server name (plus possibly the port), the virtual directory your *.svc file lives in, and the name and extension of the svc file itself.
We had similar symptoms, but only with PUT and DELETE verbs under IIS 6.0.
By default, the .svc extension within our IIS application was only allowing GET, POST verbs.
Adding the verbs (or allowing all verbs) for the .svc extension for the application fixed the issue.