When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips
Search

Sections:
Book Reviews
Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
Web Hosts
XML
Information:
Advertise
Feedback
Author an Article

ASP ASP.NET ASP FAQs Message Board Feedback
 
Print this Page!
Published: Wednesday, December 24, 2008

Apply ASP.NET Authentication and Authorization Rules to Static Content with IIS 7.0's Integrated Pipeline Feature

By Scott Mitchell


Introduction


Many ASP.NET applications that support user accounts use forms-based authentication and URL authorization. Forms-based authentication is a mechanism by which users can log into the site by entering their credentials - typically a username and password - into textboxes in a login page. Once validated, the server returns an authentication ticket cookie that identifies the request; this cookie is sent back on subsequent visits to the site, which keeps the user "logged on" for the lifetime of the cookie or until the authentication ticket expires. URL authorization is a mechanism by which authorization rules can be defined on a URL-by-URL or folder-by-folder basis. In short, with URL authorization you can instruct the application to deny access to a particular folder to anonymous users, or prohibit access to a particular URL to all users except those in the Admin role.

Because the forms-based authentication and URL authorization features are part of ASP.NET, the ASP.NET runtime must be consulted in order for these features to be employed. When developing an application using Visual Studio and the ASP.NET Development Server, all requests are handed off to the ASP.NET runtime. Consequently, the authentication and authorization logic applies to both ASP.NET-specific content like ASP.NET pages and Web Services, as well as static content like images, PDFs, and ZIP files. Things are a bit different with IIS, Microsoft's production-grade web server software. By default, IIS handles all static content itself, only invoking the ASP.NET runtime when an ASP.NET resource is requested. As a result, those URL authorization rules you apply to static content are ignored when hosting your site in a production environment!

The good news is that starting with IIS 7.0 Microsoft has introduced the integrated pipeline. In a nutshell, with the integrated pipeline you can instruct IIS to work with the ASP.NET runtime during the processing of all requests, regardless of whether the request is for an ASP.NET-specific resource. This article shows how to use the integrated pipeline feature to apply ASP.NET forms-based authentication and URL authorization rules to static content. Read on to learn more!

- continued -

A Simple Forms-Based Authentication and URL Authorization Example


To demonstrate the differences between the ASP.NET Development Server and IIS when serving static content I created a simple demo web application that is available for download at the end of this article. The demo website is a mock photo album site that supports user accounts and authenticates users via forms authentication. This configuration is specified in the root folder's Web.config file's <authentication> section:

<configuration>
   <system.web>
      <authentication mode="Forms">
         <forms>
            <credentials passwordFormat="Clear">
               <user name="Scott" password="password" />
               <user name="Jisun" password="password" />
               <user name="Alice" password="password" />
            </credentials>
         </forms>
      </authentication>

      ...
   </system.web>
</configuration>

In addition to specifying that the site uses forms-based authentication, I've also included three hard-coded user accounts in the <credentials> section. Typically, the user account information would be stored in a database, but to simplify this demo I just used ASP.NET's facility for storing credentials directly in Web.config. For more information on this technique, as well as a more thorough look at forms-based authentication, be sure to read Darren Neimke's article Using Forms Authentication in ASP.NET.

The image gallery's ASP.NET pages and images are only accessible to authenticated users. I've placed all of these gallery-related files in the ~/Gallery folder, and added a Web.config file to that folder with a URL authorization rule that denies anonymous users (thereby allowing only authenticated users):

<configuration>
   <system.web>
      <authorization>
         <deny users="?" />
      </authorization>
   </system.web>
</configuration>

The ~/Gallery folder contains both ASP.NET pages (such as ~/Gallery/Default.aspx) and image files (such as ~/Gallery/Images/Sam.jpg). The idea is that any file in the ~/Gallery folder - including static image files - should only be accessible to authenticated users. If an anonymous user attempts to visit an ASP.NET page in the ~/Gallery folder or view an image in the ~/Gallery folder then they should be automatically redirected to the login page (~/Login.aspx).

Examining the Behavior of the ASP.NET Development Server When you launch a web application from Visual Studio the ASP.NET Development Server is started and the web application's pages are served through the ASP.NET Development Server, by default. The ASP.NET Development Server is a lightweight web server that only allows testing through localhost. It is oftentimes easier to use than IIS because it requires no setup or configuration.

Unlike IIS, the ASP.NET Development Server routes all incoming requests to the ASP.NET runtime. It doesn't matter whether an ASP.NET resource such as an ASP.NET page is requested, or if a static resource like an image is requested. In either case the ASP.NET Development Server dispatches the request to the ASP.NET runtime which proceeds through its various pipeline stages, which includes authentication and authorization. Consequently, if an anonymous visitor coming through the ASP.NET Development Server attempts to directly visit an image in the ~/Gallery folder they are not shown the image and instead redirected to the login page, as the following screen shot shows:

If an anonymous user requests any file in the ~/Gallery folder they are automatically redirected to the login page.

View the full size image and check out the URL in the browser's Address bar in the screen shot above. Note that the Address is the login page (Login.aspx) but the querystring includes a ReturnUrl parameter that points back to the file the user initially requested (Sam.jpg). Once the user successfully authenticates on the login page they will automatically be redirected to the picture of Sam, which is visible now because they are no longer an anonymous user.

The ASP.NET Development Server implements the behavior we want - enforcement of the URL authorization rules specified for the ~/Gallery folder for dynamic and static content alike.

Examining IIS's Default Behavior By default, the IIS web server dispatches requests for ASP.NET resources to the ASP.NET runtime, but handles requests for static content itself. As a result, requests for static content are served without regard to the URL authorization rules spelled out in the ASP.NET application's configuration. I have IIS 7.0 installed on my computer and have added a new IIS Application that points to the directory where the demo application resides. If I visit this website through IIS rather than through the ASP.NET Development Server I can view "protected" static content such as Sam.jpg. The following screen shot was taken after visiting the site through IIS as an anonymous user and typing in the URL to Sam.jpg. Unlike the example above, I am shown the picture rather than taken to the login page.

Because IIS handles the request for static content, the picture of Sam is visible to anonymous users.

This is not the behavior we want, as it allows anonymous users to potentially see private content (if they know the direct URL). All it would take it one of the users on the site to unwittingly publish a direct link to the image on his blog or website and the search engines would pick it up and the picture would be revealed to the world at large. The good news is that we can configure IIS 7.0 to use the integrated pipeline feature, which causes IIS to involve the ASP.NET runtime when handling requests for static content.

Using IIS 7.0's Integrated Pipeline


IIS applications are serviced by Application Pools, sometimes called AppPools. In IIS 7.0 these Application Pools can be configured to use either the classic pipeline or the integrated pipeline. The classic pipeline does not work with the ASP.NET runtime; if this option is set then IIS will continue to server static requests on its own without ASP.NET integration. Therefore, the first step in protecting static content in our demo application is to ensure that the AppPool used by our IIS application is configured to use the integrated pipeline.

If you use a web hosting company and are on an IIS 7.0 web server then you likely have an option in your Control Panel where you can specify what pipeline is used. Contact your web host provider for more information. If you have direct control over your web server, launch the IIS Manager and select the Application Pools option from the list on the left. Double-click the Application Pool used by your IIS application and ensure that the Integrated Pipeline option is enabled.

Configure the Application Pool to use the Integrated Pipeline.

Now that we have instructed IIS to use the integrated pipeline the last step is to plug in the ASP.NET modules into the pipeline. Namely, we need to instruct IIS 7.0 to use ASP.NET's FormsAuthenticationModule and UrlAuthorizationModule while processing requests. Add the <sytem.webServer> element to the web application's root Web.config file, remove the existing definitions for the FormsAuthenticationModule and UrlAuthorization modules and add them back in using ASP.NET's versions (namely, System.Web.Security.FormsAuthenticationModule and System.Web.Security.UrlAuthorizationModule).

<configuration>
   <system.web>
      ...
   </system.web>

   <system.webServer>
      <modules>
         <remove name="FormsAuthenticationModule" />
         <add name="FormsAuthenticationModule" type="System.Web.Security.FormsAuthenticationModule" />
         
         <remove name="UrlAuthorization" />
         <add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
      </modules>
   </system.webServer>
</configuration>

Once this configuration information has been specified in Web.config revisit the Sam.jpg image file hosted via IIS from your browser. This time while processing the request for the image file IIS allows for the ASP.NET runtime to perform authentication and authorization logic. The ASP.NET runtime notes that the request is coming from an anonymous user and is for a URL that denies anonymous users. Therefore, the anonymous user is redirected to the login page, just like when visiting the image file served by the ASP.NET Development Server.

Now that the integrated pipeline is enabled when an anonymous user requests any file in the ~/Gallery folder they are automatically redirected to the login page.

Conclusion


The IIS and ASP.NET Development Server web servers handle requests differently. The ASP.NET Development Server dispatches all incoming requests to the ASP.NET runtime; however, by default IIS does not work with the ASP.NET runtime when static content like images, ZIP files, and PDFs are requested. By bypassing the ASP.NET runtime for static content, any URL authorization rules specified in ASP.NET are ignored. As a result, it is possible for unauthorized users to view static content that resides in folders that are protected via ASP.NET's URL authorization.

In IIS 7.0 you can remedy this by using the integrated pipeline feature and instructing the IIS pipeline to work in tandem with the ASP.NET modules that handle authentication and authorization logic. This article shows how to enable the integrated pipeline in IIS 7.0 and how to configure the web application to use the ASP.NET-related modules in the pipeline. For more information on IIS 7.0's integrated pipeline refer to the articles in the Further Reading section below.

Happy Programming!

  • By Scott Mitchell


    Attachments


  • Download the demo application discussed in this article
  • Further Reading


  • Website Security Tutorials
  • Using Forms Authentication in ASP.NET
  • How to Take Advantage of the IIS 7.0 Integrated Pipeline
  • Enhance Your Apps with the Integrated ASP.NET Pipeline


  • ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article