Using Windows Role authentication in the App.config with WCF - 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();
...

Related

Why won't Authorization Rules in IIS restrict access to my WCF service?

I have a standalone WCF service hosted in IIS 10. I would like to restrict access to the web service to a select group of users. I was able to do this for a web application by doing the following in IIS:
Authentication: Windows Authentication only (disabled Anonymous Authentication)
Authorization Rules: Allow a predefined group (i.e., Roles)
However, when I do the above steps for the web service, and changed clientCredentialType="Windows" in its web.config, it still allows any user from the domain to talk to it. Am I missing something obvious? Do web services function differently than web applications in terms of configuring authorization? Given my setup I would expect only users in the MyTestGroup to be able to talk with the web service, and all others getting 401 - Unauthorized.
As an aside, I tried setting up "Deny Everyone" rules but domain users could still talk to the web service, so I feel like the Authorization settings aren't being effectuated somehow. Looking for any insight on this.
Here are the relevant web.config contents:
<system.serviceModel>
<services>
<service name="StudyManagement.StudyManagement">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="secureHttpBinding" name="StudyManagement" contract="StudyManagement.IStudyManagement" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<bindings>
<basicHttpBinding>
<binding maxReceivedMessageSize="1048576" />
<binding name="secureHttpBinding">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" minFreeMemoryPercentageToActivateService="0" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<directoryBrowse enabled="false" />
<security>
<authorization>
<remove users="*" roles="" verbs="" />
<add accessType="Allow" users="" roles="MyAllowGroup" />
</authorization>
</security>
</system.webServer>
You can refer to this website to re-create the authorization rules. In addition, the authorization of wcf services can use ServiceAuthenticationmanager, examples and tutorials.
The following Microsoft documentation helped to answer my question:
WCF services and ASP.NET
Important takeaways:
The ASP.NET HTTP runtime handles ASP.NET requests but does not participate in the processing of requests destined for WCF services, even though these services are hosted in the same AppDomain as is the ASP.NET content. Instead, the WCF Service Model intercepts messages addressed to WCF services and routes them through the WCF transport/channel stack.
Within an AppDomain, features implemented by the HTTP runtime apply to ASP.NET content but not to WCF. Many HTTP-specific features of the ASP.NET application platform do not apply to WCF Services hosted inside of an AppDomain that contains ASP.NET content. Examples of these features include the following:
File-based authorization: The WCF security model does not allow for the access control list (ACL) applied to the .svc file of the service when deciding if a service request is authorized.
Configuration-based URL Authorization: Similarly, the WCF security model does not adhere to any URL-based authorization rules specified in System.Web’s configuration element. These settings are ignored for WCF requests if a service resides in a URL space secured by ASP.NET’s URL authorization rules.
Solution:
Use ASP.NET Compatibility Mode by configuring web.config:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
</system.serviceModel>
Unlike the default side-by-side configuration, where the WCF hosting infrastructure intercepts WCF messages and routes them out of the HTTP pipeline, WCF services running in ASP.NET Compatibility Mode participate fully in the ASP.NET HTTP request lifecycle. In compatibility mode, WCF services use the HTTP pipeline through an IHttpHandler implementation, similar to the way requests for ASPX pages and ASMX Web services are handled. As a result, WCF behaves identically to ASMX with respect to the following ASP.NET features:
File-based authorization: WCF services running in ASP.NET compatibility mode can be secure by attaching file system access control lists (ACLs) to the service’s .svc file.
Configurable URL authorization: ASP.NET’s URL authorization rules are enforced for WCF requests when the WCF service is running in ASP.NET Compatibility Mode.
I recommend reading the entire article for additional information. It's a short and helpful read.
Thanks to #Shiraz Bhaiji for the article reference on WCF Authorization using IIS and ACLs.

AD authentication in REST wcf

I am new to adding security to WCF service. I have developed a REST based WCF service which works fine.
This service is consumed by HTTP POST (outside the domain). I need to incorporate domain (AD) authentication.
How can I incorporate AD authentication in WCF? Additionally, what should I be asking details related to AD to client? Please guide me.
Updated:
Added authenticationScheme="Negotiate" to httpTransport.
Hosted service in IIS & disabled Anonymous authentication. Also tried enabling Forms authentication.
At wcf client, passing domain/id/pwd like: webrequest.Credentials = new NetworkCredential("user", "userpwd", "domain");
I am getting HTTP Error 401.2 - Unauthorized. You are not authorized to view this page due to invalid authentication headers.
Am I missing something?
You need to a biding configuration in your WCF web.config:
<bindings>
<basicHttpBinding>
<binding name="SecurityByTransport">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
You can read more about here:
http://msdn.microsoft.com/en-us/library/ms733089(v=vs.110).aspx
For javascript ajax calls you can follow this recommendation:
Cross domain jQuery ajax call with credentials

WCF security in an internet scenario

I have a WCF service hosted in a Windows Service. Clients from various platforms will access the service. Now I would like to add a basic security mechanism. Ideally, the clients should use username/password for authentication.
Which binding settings do I have to use in this scenario and how can I authenticate the client? Interoperability is more important than a very secure solutions. If possible the client should not be forced to use a certificate or something the like. Additionally, authentication should not be strongly coupled with a SQL Server database. I would like to manually inspect the client credentials.
Thanks for your help
The best for your case can be BasicHttpBinding with security set to TransportWithMessageCredentials and credential type set to UserName. In this case your service will be secured with HTTPS (requires server certificate for SSL which has to be trusted on clients) and authentication will be provided on message level with UserName Token Profile (SOAP header). You can implement your own password validator.
BasicHttpBinding configuration skeleton:
<bindings>
<basicHttpBinding>
<binding name="Secured">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" />
</security>
</binding>
</basicHttpBinding>
</bindings>
If you don't want to use HTTPS you can create custom binding with HttpTransport, TextMessageEncoding and with security mode set to UserNameOverTransport. But you have to set allowInsecureTransport to true (be aware that there is some bug with WSDL generation in this setting).
Custom binding configuration skeleton:
<bindings>
<customBinding>
<binding name="Secured">
<security authenticationMode="UserNameOverTransport" allowInsecureTransport="true" />
<textMessageEncoding messageVersion="Soap11" />
<httpTransport />
</binding>
</cutomBinding>
</bindings>
See the Internet section of the Application Scenarios for guides on how to achieve this:CodePlex Application 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