WCF Security and what to use in this situation - wcf

I have a client/server application that has many client machines and one service on a server.....
On the server side I will be using a Windows Service to host my WCF service. The service will be passing data across the internet to the client machines. I figure I will be using wsHttpBinding with message level security, which requires a username or a certificate.
Now here's the problem.....
-We don't want to have the user log in to the system
-there is no Windows Authentication on the client machines
-and I would use certificates but, we have tons of client machines going out everyday, so installing certificates manually on each machine is not gonna be an option (unless it can all be done through code... and I mean creation and installing)
anybody have any ideas on how to secure this kind of service? Thanks in advance
Peace

In your scenario, it seems like you're looking for the "basicHttpBinding" with no security whatsoever.
<bindings>
<basicHttpBinding>
<binding name="NoSecurity">
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
and then configure your endpoints to use that binding configuration:
<system.serviceModel>
<services>
<service name="YourNamespace.YourService"
behaviorConfiguration="MyServiceBehavior">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="NoSecurity"
contract="YourNamespace.IMyService">
</endpoint>
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
There's also a really good blog post series that talk about the basics of WCF security in terms of five different, typical scenarios - excellent read! Your scenario would be the "No security at all" scenario.
Another good introductory article is Michele Leroux Bustamante's Fundamentals of WCF Security.
A more thorough (but also more complex) set of guidance for WCF can be found at the WCF Security Guidance on Codeplex.
Marc

Since you will be using an app wirtten by yourself. You can use wshttpbinding with username and password authentication (Client credential type basic) where your app reads the username and password from a config file.
http://msdn.microsoft.com/en-us/library/ms731299.aspx
EDIT
The windows service could run under an account that the user does not have the password for. The service is in a directory that is protected with ACLs, such that the user of the machine does not have access to the config file.

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.

How to disable authentication schemes for WCF Data Services

When I deployed my WCF Data Services to production hosting I started to get the following error (or similar depending on which auth schemes are active):
IIS specified authentication schemes
'Basic, Anonymous', but the binding
only supports specification of exactly
one authentication scheme. Valid
authentication schemes are Digest,
Negotiate, NTLM, Basic, or Anonymous.
Change the IIS settings so that only a
single authentication scheme is used.
Apparently WCF Data Services (WCF in general?) cannot handle having more than once authentication scheme active.
OK so I am aware that I can disable all-but-one authentication scheme on the web application via IIS control panel .... via a support request!!
Is there a way to specify a single authentication scheme on a per-service level in the web.config?
I thought this might be as straight forward as making a change to <system.serviceModel> but... it turns out that WCF Data Services do not configure themselves in the web config. If you look at the DataService<> class it does not implement a [ServiceContract] hence you cannot refer to it in the <service><endpoint>...which I presume would be needed for changing its configuration via XML.
P.S. Our host is using II6, but both solutions for IIS6 & IIS7 appreciated.
Firstly it is possible to configurate Data Services on the web config file. The contract used by the DataService is called System.Data.Services.IRequestHandler.
Here is what you can do in the web config file to configurate it.
On the Service tag of the system.servicemodel element add the
<service name="{you service type name including the namespace i.e. myapplication.myservice}">
<endpoint address="" binding="webHttpBinding" contract="System.Data.Services.IRequestHandler">
</endpoint>
</service>
Once you have that there you can start configuring all manners of thing using the standard WCF configuration elements.
Secondly to enable or disabled authentication methods for a specific service in IIS you can do the following:
On the snap in for IIS right click your service file (i.e. yourservice.svc) and click properties.
Once in properties go to File Security Tab and chose the Edit button on the authentication and access control group box. after that it is just like setting up directory security in IIS.
As a last suggestion as per any trouble shooting goes it is important to enable the wcf disgnostics while you configurate it using the xml configuration, being written in WCF, Data Service logging is as per wcf is rich and very informative.
you can find out more about that on WCF Administration and Diagnostics
I hope i was able to help you with your problem
let me know how things goes.
Regards
Daniel Portella
UPDATE:
Hi Schneider
To specify the authentication scheme in the xml read below
For windows authentication as a example
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="MyBindingName" >
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</webHttpBinding>
</bindings>
<services>
<service name="{you service type name including the namespace i.e. myapplication.myservice}">
<endpoint address="" binding="webHttpBinding" bindingConfiguration="MyBindingName" contract="System.Data.Services.IRequestHandler">
</endpoint>
</service>
</services>
</system.serviceModel>
</configuration>
For other types of authentication please check the MSDN library for examples
Common Scenarios for security

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.

Using Windows Role authentication in the App.config with WCF

I am using a WCF service and a net.tcp endpoint with serviceAuthentication's principal PermissionMode set to UseWindowsGroups.
Currently in the implementation of the service i am using the PrincipalPermission attribute to set the role requirements for each method.
[PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public string method1()
I am trying to do pretty much the same exact thing, except have the configuration for the role set in the app.config. Is there any way to do this and still be using windows groups authentication?
Thanks
If you are hosting your WCF service in IIS, it will run in the ASP.NET worker process, which means you can configure authentication and authorization as you would do with ASMX web services:
<system.Web>
<authentication mode="Windows"/>
<authorization>
<allow roles=".\Administrators"/>
<deny users="*"/>
</authorization>
</system.Web>
Then you will have to disable anonymous access to your endpoint in IIS, and instead enable Windows Integrated Authentication.In the IIS management console you do that by bringing up the 'Properties' dialog for your virtual directory. You will then find the security settings in the 'Directory Security' tab.
Of course, the only communication channel available will be HTTP. Clients will have to provide their Windows identity in the request at the transport-level with these settings:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WindowsSecurity">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://localhost/myservice"
binding="wsHttpBinding"
bindingConfiguration="WindowsSecurity"
contract="IMyService" />
</client>
</system.serviceModel>
Note that if your service endpoint uses wsHttpBinding then you will also have to add SSL to your endpoint since that's a requirement enforced by WCF when you using transport-level security.
If you instead go for the basicHttpBinding, you are then able to use a less secure authentication mode available in WCF called TransportCredentialOnly, where SSL is no longer required.
For more detailed information, here is a good overview of the security infrastructure in WCF.
Lars Wilhelmsen has posted a solution for this problem. Have a look at
http://www.larswilhelmsen.com/2008/12/17/configurable-principalpermission-attribute/
If I understood well you want to select the role at runtime. This can be done with a permission demand within the WCF operation. E.g.
public string method1()
{
PrincipalPermission p = new PrincipalPermission(null, "Administrators");
p.Demand();
...