Allow access to WCF based on a group set in web.config - wcf

I have created a WCF service that uses windows authentication and would like to set it so it can only be accessed if the user is in a Windows group. I Currently use the following attribute in code to make this happen
[PrincipalPermission(SecurityAction.Demand, Role = "Domain\MyGroup")]
Problem with this is I have to do it on each method and compile if I want to change the group. Is there a way so I can set the group that has access in the config file and for the services as an whole?
I have tried the following in my config file but this does not appear to work
<security>
<authentication>
<windowsAuthentication authPersistSingleRequest="true" enabled="true"/>
</authentication>
<authorization>
<add accessType="Allow" roles="Domain\MyGroup" />
</authorization>
</security>

Ok I figured it out. I have the config file set like the following
<security>
<authentication>
<windowsAuthentication enabled="true" />
</authentication>
<authorization>
<remove users="*" roles="" verbs="" />
<remove users="?" roles="" verbs="" />
<add accessType="Deny" users="?" />
<add accessType="Allow" roles="Domain\MyGroup" />
</authorization>
</security>
Also had to set
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
And on my class that implements the WCF contract
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
I guess this means Im using ASP authentication rather than WCF but I works for me

The PrincipalPermission attribute is from the .NET code access security functionality and isn't related to WCF. A more flexible way to do this if the service is hosted in IIS is shown in this MSDN post. WCF also supports different custom authentication mechanisms as described here.

Related

IIS Windows Authentication - Unable to Deny Specific Users

Recently I have developed a very simple .net core API and then deployed the same on IIS and want to enable Windows Authentication for some users. To be able to implement it, my web.config looks like
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<authentication mode="Windows" />
<authorization>
<allow users="Tow\USER1"/>
<deny users="*"/>
</authorization>
</system.web>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\Oculus.WebApi.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="InProcess" />
</system.webServer>
</location>
</configuration>
As it can be seen only User1 should be allowed access but everyone is able to access. My IIS authentication looks like this:
Can some one help please?
From this thread, ASP.NET Core does not support nor use web.config. The published web.config is there only for IIS hosting, since IIS requires this.
A wrokaround is that you could try to place inside system.webServer, which is directly for configuration of IIS.
<configuration>
<system.webServer>
<security>
<authorization>
<remove users = "*" roles="" verbs="" />
<add accessType = "Allow" users="Tow\USER1"/>
</authorization>
</security>
</system.webServer>
</configuration>
But the recommend way is that you'd better write you own custom authorization policy in asp.net core
https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api
https://learn.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-2.2

Aspnet Core - web.config Authorization

I am trying to add "authorization" elements to web.config, like it used to work in classic asp.net:
global configuration - should limit access "globally":
<configuration>
<system.web>
<authentication mode="Windows" />
<authorization>
<allow roles="AD\some.user" />
<deny users="*" />
</authorization>
...
"location" based configuration:
<configuration>
<location path="RelativePath" >
<system.web>
<authorization>
<allow roles="AD\some.user" />
<deny users="*" />
</authorization>
</system.web>
</location>
both versions appear to be not working at all for aspnet.core hosted in IIS
What does work is this:
"global":
<configuration>
<system.webServer>
<security>
<authorization>
<remove users="*" roles="" verbs="" />
<add accessType="Allow" roles="AD\johannes.colmsee" />
</authorization>
</configuration>
"location" based:
<configuration>
<location path="RelativePath" >
<system.webServer>
<security>
<authorization>
<remove users="*" roles="" verbs="" />
<add accessType="Allow" roles="AD\denis.kopic" />
</authorization>
</security>
</system.webServer>
</location>
This works fine.
Now to my question:
does aspnet core not support the "first version" at all? Or is it something I do wrong?
ASP.NET Core does not support nor use web.config. The published web.config is there only for IIS hosting, since IIS requires this. If you happened to publish to a different web server, you could discard web.config entirely.
It should be apparent from looking at the contents of the published web.config, that it is extremely bare. Pretty much the only thing that exists is the AspNetCoreHosting module config, which of course is necessary for hosting ASP.NET Core inside IIS.
Now, as for why the second version actually did work, that's because it was placed inside system.webServer, which is directly for configuration of IIS, so IIS is doing the authorization at a very high-level before anything is handed off to your ASP.NET Core app. That may work for your needs, but it's an extremely rough-shod approach, as you'll have to likely end up defining many such sections for different paths, users, and authorization levels, and then keep that in sync with anything you end up changing in the ASP.NET Core app. Because IIS is looking at this as just static paths, if you move or rename anything, you can end up accidentally opening a hole in your security, since IIS will not yet have been configured to authorize that new location.
Long and short, you should remove all this and handle authorization via your ASP.NET Core app. Windows Auth is still supported.

Windows Authentication allow users not working

I am trying to use windows authentication for my application, for the testing I have tried allowing to only myself and deny all rest
<authentication mode="Windows" />
<authorization>
<allow users="DomainName\nogariyap" />
<deny users="*"/>
</authorization>
But it gives me "Access Denied" error even I am logged in to my machine with the same user "DomainName\nogariyap"
When I change it to this
<allow users="*" />
it works
I don't know why it is not working for particular windows user?
Edit
It strangly worked when I added this in system.webServer
<security>
<authentication>
<windowsAuthentication enabled="true" />
<anonymousAuthentication enabled="false" />
</authentication>
<authorization>
<remove users="*" roles="" verbs="" />
<add users="DomainName\nogariyap" accessType="Allow"/>
<add users="?" accessType="Deny"/>
</authorization>
</security>
But I don't know why it is not working with the settings in system.web and what are the difference in these two settings?
<system.web> is the projects configuration and <system.webserver> is the server configuration. Both should be compatible but the recommendation seems to be to use the server configuration over the other. It was introduce on IIS7. Some of the differences between both are:
In system.webserver the order:
Deny rules get evaluated first starting at the parent
Allow rules starting at the parent.
Order of appearance in rule collection
In system.web the order:
Lower level first going up to the parent
Order of appearance in rule collection
In webserver you can apply rules to any element meaning: images, documents without further configuration(adding mapping between every extension you want to a handler)
in the first attempt you had deny users="*" meaning deny everyone. in the second attempt, you had deny users="?" meaning unknown users (not signed in).

Webservice does not seem to be doing any authentication despite config in IIS7.5

The Problem
I have a WCF webservice that I am hosting as a webservice in IIS7.5. I want this service to only be accessible by two groups. The webservice is running successfully, although there does not seem to be any authentication being done.
I was under the impression ( having read gobs of MSDN pages attesting to this) that all one really had to do was enable Windows Authentication on the Application site, disable Anonymous Authentication, set the mode to windows in the web.config and add Allow/Deny rules to the authorization section as diaplayed below:
<system.web>
<authentication mode="Windows" />
<compilation debug="false" strict="false" explicit="true" targetFramework="4.0" />
<pages /> <!-- Omitted -->
<authorization>
<allow roles="Managers" />
<allow roles="Operations" />
<deny users="*" />
<deny users="?" />
</authorization>
</system.web>
With the above steps and web.config changes done, and after going to the Authorization page in IIS and reloading the Auth rules, calling the service through the WCFTestclient shows it working flawlessly. Except I am not part of either of those two groups...
The Questions
It looks like it is just letting anyone in. My questions are these:
Is there a way to see passed and failed authentication checks on the webservice? (If so, I can see if any kind of authentication is going on).
Does the above look correct? It seems a bit simple, but given the Microsoft Method, it is not far fetched that something so standard would be fairly simple to set up.
Bottom-line
I have a service with the above web.config file, and an IIS7.5 instance with Windows Authentication installed and enabled. Anonymous Authentication is disabled. Auth rules are defined for two groups to have access, and all others to be denied and yet despite the fact that I am in those groups, I can access the service.
EDIT:
So I appear to have authentication working. If I only have the Allow All Users rule in place, I have access to the webservice. If I enact a Deny All Users rule, I no longer have access. However, if I add my account ("domain\MyAccount" as an allow (regardless of position in the web.config) I still don't have access.
What I have changed to get here,
Added the following to the service definition:
<AspNetCompatibilityRequirements(RequirementsMode:=AspNetCompatibilityRequirementsMode.Required)> _
Added the following to the web.config:
<system.web>
<authentication mode="Windows"/>
<authorization>
<deny users="*"/>
<allow users="sierra\cblissittekeps"/>
</authorization>
</system.web>
and
<system.servicemodel>
<bindings>
<basicHttpBinding>
<binding name="ADServiceBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<system.servicemodel>
Alright! So apparently the steps I took in the original post are not in fact enough. You have to add that aspnetcompatabilityrequirements attribute to the service class (which implements your service iterface), you have to add to the serviceHostingEnvironment tag an aspNetCompatibility attribute:
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"
aspNetCompatibilityEnabled="true" />
And, something that no-one seems to mention, the order of your Allow/Deny rules makes a difference. Adding an allow AFTER a Deny All Users means that all users are still denied. Putting it before means that all users are denied except the ones in the allow.

WCF Rest with basicHttpBinding on IIS 7.5 500 error

yet another failed attempted to get a WCF Rest (no svc file) service using basicHttpBinding deployed to IIS 7.5. I believe I have the website configured properly along with IIS. I'm sure the problem resides in my config. The response I'm receiving is a 500 Error. I have a MVC 3 web running fine on this box.
The WCF Rest service is using basicHttpBinding with security mode of Transportcredentialonly. Here is my config;
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</modules>
<handlers>
<add name="UrlRoutingHandler" preCondition="integratedMode" verb="*" path="UrlRouting.axd" type="System.Web.HttpForbiddenHandler, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</handlers>
</system.webServer>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="AuthBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic"></transport>
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="NamedService">
<endpoint contract="Namespace.IService" binding="basicHttpBinding" bindingConfiguration="AuthBinding"></endpoint>
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true" />
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
Current web and IIS config based on other posts;
I have a v4.0 app pool created for the web
I have a website created associated with the above app pool
I have both 32bit and 64bit .NET v4 ISAPI filters enabled
I register v4 again with Aspnet_regiis.exe -i
I have HTTP Redirect installed
I have basic authentication enabled
Any help would be greatly appreciated. I've been at this for a day now. BTW... I'm not seeing any event messages. I know DNS is configured properly because I can strip away the WCF stuff and put a temp html page in the web and it works.
---------------- UPDATE ---------------------
Still having issues even after using this stripped down config. The couple things I left out is this is a x64 OS and I'm using castle as an IoC. I did run the Frameword64/aspnet_regiis.exe.
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="castle" type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor"/>
</configSections>
<connectionStrings>
<add name="Main.ConnectionString" connectionString="data source=blah;initial catalog=newdatabase;User ID=web;Password=testing;persist security info=False;packet size=4096;" providerName="System.Data.SqlClient" />
</connectionStrings>
<system.web>
<compilation targetFramework="4.0" />
<httpModules>
<add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor" />
</httpModules>
</system.web>
<castle>
<properties>
<myConnStr>data source=blah;initial catalog=newdatabase;User ID=web;Password=testing;persist security info=False;packet size=4096;" providerName="System.Data.SqlClient</myConnStr>
</properties>
<components>
<component id="RestService" service="Namespace.Rest.IRestService, Namespace.Rest" type="Namespace.Rest.RestService, Namespace.Rest" lifestyle="PerWebRequest"/>
<component id="Repository" service="Namespace.Domain.Interfaces.IRepository, Namespace.Domain" type="Namespace.Domain.Repository, Thumbfound.Domain" lifestyle="PerWebRequest">
<parameters>
<connectionString>#{myConnStr}</connectionString>
</parameters>
</component>
</components>
</castle>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</modules>
</system.webServer>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<standardEndpoints>
<webHttpEndpoint>
<!--
Configure the WCF REST service base address via the global.asax.cs file and the default endpoint
via the attributes on the <standardEndpoint> element below
-->
<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"/>
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
</configuration>
yet another failed attempted to get a
WCF Rest (no svc file) service using
basicHttpBinding deployed to IIS 7.5.
There's your problem right there - WCF REST must use the webHttpBinding - not basicHttpBinding (that's a SOAP binding).
Turns out this was a Castle Windsor configuration issue.
The resolution to my problem was removing the <httpmodules> section within <system.web> and placing my PerRequestLifestyleModule config in the <modules> section of <system.webServer>. I guess IIS 7 doesn't like httpmodules in integrated mode.