Anonymous authentication using generic asp.net handler (*.ashx) - asp.net

I have an asp.net webforms application that has windows authentication enabled. I need to enable anonymous authentication on a folder “Test” in the website which contains images . I did that by adding
<location path="Test">
<system.webServer>
<security>
<authentication>
<anonymousAuthentication enabled="true"/>
</authentication>
</security>
</system.webServer>
Now any requests to images in Test folder is unauthenticated and everything works as expected until I introduced a generic handler for this folder which fetches files from the backend storage if the file is not found in the “Test” folder and boom it broke! Anonymous authentication doesn’t work anymore. Updated web.config file below -
<location path="Test">
<system.webServer>
<handlers>
<add verb="*" path="Test" requireAccess="None" name="Handler1" type="WebApplication1.Test.Handler1, Anonymous" />
</handlers>
<security>
<authentication>
<anonymousAuthentication enabled="true"/>
</authentication>
</security>
</system.webServer>
I inspected the request using fiddler and it returns HTTP/1.1 401 Unauthorized message if I have the handler section in config but if I remove the handler section from config everything just works fine and I can see the valid response in fiddler. Any insight into what could be wrong here?

Finally I was able to resolve it myself by modifying the location configuration as shown below by adding system.web to allow all users
<location path="Test">
<system.webServer>
<handlers>
<add verb="*" path="Test" requireAccess="None" name="Handler1" type="WebApplication1.Test.Handler1, Anonymous" />
</handlers>
<security>
<authentication>
<anonymousAuthentication enabled="true"/>
</authentication>
</security>
</system.webServer>
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>

Related

Custom 401 page in IIS with ASP.NET

I have an internet facing ASP.NET website which I want to secure via Windows Authentication. I set my web.config file as:
<system.web>
<authentication mode="Windows" />
<authorization>
<allow users="*"/>
<deny users="?"/>
</authorization>
I have then disabled Anonymous Access and enabled Windows Authentication in IIS 7.5.
This results in the prompt box being displayed for my Windows credentials, however clicking 'Cancel' gives me a standard 401 error page. I would like to display a static HTML file in place of this message, however I've not been able to get it working and I've tried a combination of various settings such as:
<httpErrors errorMode="Custom" existingResponse="Replace" lockAllAttributesExcept="errorMode"> <error statusCode="401" prefixLanguageFilePath="c:\inetpub\custerr" path="MyCustom401.htm" /> </httpErrors>
and
<customErrors mode="Off" defaultRedirect="ErrorPage.aspx">
<error statusCode="401" redirect="MyCustom401.aspx" />
</customErrors>
What I would like to happen is that anyone entering the correct Windows credentials can carry onto the website as normal, but those with invalid or details to see the custom HTML page.
Can anyone point me in the right direction?
Thanks!
One thing to make sure is that you are allowing anonymous users access to the path where the error files are included otherwise they won't get the error page. For example here is a configuration file that should give you the intended results if your error files are in a directory (errors). First it disables anonymous access for all the site, but then opens it for the "errors" folder:
<configuration>
<system.webServer>
<security>
<authorization>
<add accessType="Deny" users="?" />
</authorization>
</security>
<httpErrors errorMode="Custom">
<error statusCode="401" subStatusCode="2" path="/errors/unauthorized.aspx" responseMode="ExecuteURL" />
</httpErrors>
</system.webServer>
<location path="errors">
<system.webServer>
<security>
<authorization>
<clear />
<add accessType="Allow" users="*" />
</authorization>
</security>
</system.webServer>
</location>
</configuration>

Configuration values for ASP.Net project

I am assigned in a new ASP.Net MVC 4.0 project. Traditionally, we used to add configuration values, when testing team raise new new issues (E.g. globalization, maxQueryStringLength, machineKey). For this project, I am planning to take a new route.. All the frequently used configuration values, I am planning to add upfront… I created the following config values.. What are the other most frequently used \ common config values that are needed in an ASP.Net project?
system.web
<system.web>
<!--Culture-->
<globalization culture="en-US" uiCulture="en" />
<!--Remove Custom Errors Mode in Production-->
<customErrors mode="Off"/>
<!--Impersonate-->
<identity impersonate="true"/>
<!--Session Mode and Timeout-->
<sessionState mode="InProc" timeout="60" />
<!--maxQueryStringLength-->
<httpRuntime maxQueryStringLength="6000" />
<!--machineKey-->
<machineKey/>
<!--authentication-->
<authentication mode="Windows">
</authentication>
<!--authorization-->
<authorization>
<allow users="?" />
</authorization>
</system.web>
system.webServer
<system.webServer>
<security>
<requestFiltering>
<!--maxQueryString-->
<requestLimits maxQueryString="6000" />
</requestFiltering>
<!--IIS Setting for Authentication-->
<authentication>
<anonymousAuthentication enabled="false" />
<windowsAuthentication>
<providers>
<clear />
<add value="NTLM" />
</providers>
</windowsAuthentication>
</authentication>
</security>
</system.webServer>
It is a good practice to add connection strings to web.config as well. Not sure whether you require accessing data in this project, but if you do then you need to add the following to the web.config file as well.
<connectionStrings>
<add name="myConnectionString" connectionString="server=localhost;Database=myDb;uid=myUser;password=myPass;" />
</connectionStrings>

Enabling PUT on IIS 7.5 for an ASHX handler using Windows Authentication

I have an ASP.NET (.NET 4) website that uses http PUT for an .ashx generic handler. The PUT call originates from a Silverlight front end. All works in VS 2010 on my local machine (Cassini web server).
Then I deployed to an IIS7.5 Win Server 2008 R2 box.
The silverlight/website is fine, but PUT calls to the .ashx handler are met with a Windows Login Prompt.
This is a local intranet so Windows Authentication (with NTLM & Negotiate providers) is the only enabled authentication.
Then I read this: http://blogs.msdn.com/b/joseph_fultz/archive/2009/07/23/enabling-the-put-verb-with-handlers-and-iis-7-0.aspx
I've followed his suggestion and I can now make PUT calls via my .ashx handler. Problem is only folks in the Administrators Group of the web server can do this. No one else can. They are met with the windows login prompt.
Any idea what this could be?
I can't give Everyone in the company Admin privileges on the webserver. They would no doubt cut off one of my hands, eat said hand in front of me, and then show me the door.
Ok I figured it out.
Here are the key configuration elements in IIS 7.5:
Under Windows Authentication / Providers - NTLM had to be on top of Negotiate
Domain Users needed write access to the directory containing the ashx handler
URL Authorization was not enabled as a role on the web server. I added it and then stuck this in the web.config under system.webServer:
<security>
<authorization>
<remove users="*" roles="" verbs="" />
<add accessType="Allow" users="*" verbs="GET,HEAD,POST,PUT,DELETE,DEBUG" />
</authorization>
</security>
(I'll trim that down a bit, but for now it works)
My entire system.webServer element is as follows:
<system.webServer>
<modules>
<remove name="WebDAVModule" />
</modules>
<defaultDocument>
<files>
<clear />
<add value="default.aspx" />
</files>
</defaultDocument>
<handlers accessPolicy="Read, Write, Execute, Script">
<remove name="WebDAV" />
<remove name="SimpleHandlerFactory-Integrated-4.0" />
<remove name="SimpleHandlerFactory-Integrated" />
<add name="SimpleHandlerFactory-Integrated" path="*.ashx" verb="GET,HEAD,POST,DEBUG,PUT" type="System.Web.UI.SimpleHandlerFactory" resourceType="Unspecified" requireAccess="Write" preCondition="integratedMode" />
<add name="SimpleHandlerFactory-Integrated-4.0" path="*.ashx" verb="GET,HEAD,POST,DEBUG,PUT" type="System.Web.UI.SimpleHandlerFactory" resourceType="Unspecified" requireAccess="Write" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
<security>
<authorization>
<remove users="*" roles="" verbs="" />
<add accessType="Allow" users="*" verbs="GET,HEAD,POST,PUT,DELETE,DEBUG" />
</authorization>
</security>
</system.webServer>
That did it.

My ASP.NET MVC2 application with Forms Authentication is blocking access even to Images, Styles and Scripts

I'm developing a MVC2 application and using Forms Authentication on it.
The scripts, images and styles are all blocked to unlogged users and, consequently, the login page looks awful.
It works well local, the problem is when I publish to the server.
Does anyone has any idea WHY????
PS: The server IIS is version 7.5
My Web.config:
<configuration>
<system.web>
<globalization culture="pt-BR" uiCulture="pt-BR" />
<httpRuntime requestValidationMode="2.0"/>
<customErrors mode="Off" />
<compilation debug="true" targetFramework="4.0">
<assemblies>
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</assemblies>
</compilation>
<pages>
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="Admin.Models" />
</namespaces>
</pages>
<authentication mode="Forms">
<forms name="AGAuth" loginUrl="~/Home/Login" timeout="120" />
</authentication>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<connectionStrings>
<add name="DBContainer" connectionString="metadata=res://*/Database.DB.csdl|res://*/Database.DB.ssdl|res://*/Database.DB.msl;provider=System.Data.SqlClient;provider connection string="Data Source=thewebserver.com,5158;Initial Catalog=thedatabase;Persist Security Info=True;User ID=theuser;Password=thepassword;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" />
</connectionStrings>
</configuration>
Add a web.config to the scripts, images and styles folders telling asp.net to allow access to all users (make sure you you don't have anything in there that you don't want anonymous users to have access to):
<configuration>
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</configuration>
As for the reason, the following is telling IIS to let asp.net process all the requests:
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
I had exactly the same problem.
The cause turned out to be the IIS authentication configuration. By enabling Anonymous Authentication (and enabling Forms Authentication and disabling Windows Authentication) the scripts, styles and images became accessible when logged off.
You can set permission to required folders like this:
<location path="App_Themes">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
<location path="images">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
<system.web>
Take a look at the documentation for the location element. I think the first example will give you what you need.
For convenience, here is the example mentioned:
<configuration>
<location path="Logon.aspx">
<system.web>
<authorization>
<allow users="?"/>
</authorization>
</system.web>
</location>
</configuration>
The group IIS_WPG need read access to the fold. Now it works fine... hope this helps someone else
You can set the permission to required folders like this
<location path="App_Themes">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
This is a complete stab in the dark but what are the rights on the image and css folders? If they are set so that only authorised people can get to them then you have a problem. You might try setting the rights on those folders to everyone, or for the .net default user and see what you get.
Did you accidentally copy or create a Web.config file in your Content folder that has an <authorization> element that may be denying access?
I had the same problem too and I tried what Scott H suggested but it didn't work...
It turns out the user assigned to Anonymous Authentication was set to IUSR (right-click 'Anonymous Authentication' -> Edit), which didn't have access to my code. I had given access to the Application pool identity, so I selected that option, clicked 'OK', and bingo it worked.

How do I protect static files with ASP.NET form authentication on IIS 7.5?

I have a website running on a IIS 7.5 server with ASP.NET 4.0 on a shared host, but in full trust.
The site is a basic "file browser" that allows the visitors to login and have a list of files available to them displayed, and, obviously, download the files. The static files (mostly pdf files) are located in a sub folder on the site called data, e.g. http://example.com/data/...
The site uses ASP.NET form authentication.
My question is: How do I get the ASP.NET engine to handle the requests for the static files in the data folder, so that request for files are authenticated by ASP.NET, and users are not able to deep link to a file and grab files they are not allowed to have?
If you application pool is running in Integrated mode then you can do the following.
Add the following to your top level web.config.
<system.webServer>
<modules>
<add name="FormsAuthenticationModule" type="System.Web.Security.FormsAuthenticationModule" />
<remove name="UrlAuthorization" />
<add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
<remove name="DefaultAuthentication" />
<add name="DefaultAuthentication" type="System.Web.Security.DefaultAuthenticationModule" />
</modules>
</system.webServer>
Now you can use the standard ASP.NET permissions in your web.config to force forms authentication for all files in the directory.
<system.web>
<authorization>
<deny users="?" />
</authorization>
<authentication mode="Forms" />
</system.web>
I had the same problem with getting roles to authenticate. Through trial and error I finally got it to work with a small edit to #Joel Cunningham's code:
<modules runAllManagedModulesForAllRequests="true" >
I used these two sites as references: http://forums.iis.net/t/1177964.aspx and http://learn.iis.net/page.aspx/244/how-to-take-advantage-of-the-iis-integrated-pipeline/
This is an old thread, but I happened on it and ran into the same problem as Egil. Here is the version of Joel's fix that includes roles:
<modules runAllManagedModulesForAllRequests="false">
<remove name="FormsAuthenticationModule" />
<add name="FormsAuthenticationModule" type="System.Web.Security.FormsAuthenticationModule" />
<remove name="UrlAuthorization" />
<add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
<remove name="RoleManager" />
<add name="RoleManager" type="System.Web.Security.RoleManagerModule" />
<remove name="DefaultAuthentication" />
<add name="DefaultAuthentication" type="System.Web.Security.DefaultAuthenticationModule" />
</modules>
Addendum:
As #eych noted the accepted answer also blocks access to the ~/Content folder (or wherever you have your CSS), and ~/Scripts, and so on.
If you want to allow exceptions -- i.e. allow certain files/folders to be accessible by unauthenticated users -- you can do that by means of the location element. Add the following to web.config:
<location path="Content">
<system.web>
<authorization>
<allow users="*" />
</authorization>
</system.web>
</location>
Update:
An alternative solution is to is to leave access on by default -- which will allow access to your CSS / JavaScript / etc. -- and apply the "lock" (only) to the folder where the static content is stored:
<location path="data">
<system.web>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
</location>
Caveat: in our case (an MVC site) we needed to decorate all our controller actions (except login) with [AuthorizeAttribute]. Which is a good idea anyway, but had previously not been necessary (because previously any unauthorized request was redirected to the login page).
I wanted to know why it would be required to re-add modules (with default options) that are added by default for the Integrated Pipeline, so I dug a little deeper.
You need to remove and re-add the modules because, by default, the modules aren't added with the default options. They have a precondition added for backwards compatibility to run only for content handled by a registered ASP.NET handler (e.g., .aspx pages).
The default looks like this:
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule"
preCondition="managedHandler" />
By removing the modules and re-adding them without a precondition, those individual modules run for every request (including your static content). It is more granular than enabling runAllManagedModulesForAllRequests.
You can read about it in a couple articles from when the Integrated Pipeline was introduced with IIS 7:
ASP.NET Integration with IIS 7
How to Take Advantage of the IIS 7.0 Integrated Pipeline
Note that there is a typo or the module name in the second article (and #John's answer) was changed from FormsAuthenticationModule to FormsAuthentication at some point.
The set of working modules in IIS 7.5 thru 8.5 looks like this for me:
<system.webServer>
<modules>
<!-- Re-add auth modules (in their original order) to run for all static and dynamic requests -->
<remove name="FormsAuthentication" />
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />
<remove name="DefaultAuthentication" />
<add name="DefaultAuthentication" type="System.Web.Security.DefaultAuthenticationModule" />
<remove name="RoleManager" />
<add name="RoleManager" type="System.Web.Security.RoleManagerModule" />
<remove name="UrlAuthorization" />
<add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
</modules>
</system.webServer>
If you application pool is running in Classic mode, you can do the following. You will have to repeat these steps for each file extension you'd like to handle, but I'm using .html here.
First, add a page build provider to the Web.config:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<compilation>
<buildProviders>
<add type="System.Web.Compilation.PageBuildProvider" extension=".html"/>
</buildProviders>
</compilation>
</system.web>
</configuration>
Then add a page handler factory:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<httpHandlers>
<add type="System.Web.UI.PageHandlerFactory" path="*.html" verb="*"/>
</httpHandlers>
</system.web>
</configuration>
Then add a page handler:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<handlers>
<add scriptProcessor="C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" requireAccess="Script" preCondition="classicMode,runtimeVersionv2.0,bitness32" path="*.html" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" name="HtmlHandler-Classic-32" />
<add scriptProcessor="C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" requireAccess="Script" preCondition="classicMode,runtimeVersionv2.0,bitness64" path="*.html" verb="GET,HEAD,POST,DEBUG" name="HtmlHandler-Classic-64"/>
</handlers>
</system.webServer>
</configuration>
This worked for me. (Credit: http://www.ifinity.com.au/Blog/EntryId/66/How-To-301-Redirect-htm-or-html-pages-to-DotNetNuke-aspx-pages.)

Resources