Forms Authentication with ACL Authorization
And Showing the Progress of File Generation
By Rob Howard
My inbox has been overflowing with some really great questions. Here are a couple good ones.
On our previous NT 4.0 platform, we used forms authentication with Site Server 3.0 to map personalization and membership logins to NT groups, so we were able to use access control lists (ACL) authorization. On our new platform, we would like to continue to use forms authentication with ACL authorization. We would like to use the form page to authenticate and bind users to Active Directory accounts. We do not want to use URL authorization because we would like to secure other resources besides aspx files (such as asp files and htm files). Is there any way to perform a Windows authentication using forms, or are we restricted only to basic, digest, and integrated authentication? - Joe Alfano
ASP.NET supports a very rich and extensible security architecture. Out of the box, there are three supported modes of authentication: Windows, Forms, and Passport. There is also a custom option, but that is beyond the scope of this answer. The scenario Joe describes is quite common: Resources exist on a server and must have restricted access. There are a couple of ways to solve Joe's problem using ASP.NET, and I'll show you the one I believe is most applicable.
ASP.NET's forms authentication is an authentication model that looks at an incoming request and attempts to determine if the caller has a cookie containing an authentication ticket. If the ticket exists and can be verified, the request is authenticated. However, if the ticket does not exist, the request is redirected to a login page where the credentials can be captured, verified, and authenticated. Finally, the request is rerouted back to the original document requested. Here are the steps:
What It Means
1) GET default.aspx HTTP/1.1
2) 302 Redirect
3) POST login.aspx HTTP/1.1
<form data containing credentials>
4) [verify credentials]
5) 200 OK
Set-Cookie: .ASPXAUTH Auth Ticket
6) GET default.aspx HTTP/1.1
Cookie: .ASPXAUTH Auth Ticket
1) The user requests a resource on the server, default.aspx.
2) The user is not authenticated, so the server redirects the user to login.aspx.
3) The user enters a user name and password (or other credentials) into an HTML form and posts that form back to login.aspx.
4) Code within login.aspx verifies the user name and password against a data store.
5) If the user name and password are valid, an authentication ticket - in the form of an HTTP cookie - is written to the browser's headers.
6) The request is directed back to the page the user originally requested, along with the authentication ticket. The request is authenticated.
In forms authentication, the developer's responsible for writing the code necessary to verify and authenticate the credentials a user provides. It is also the developer's responsibility to call an API on the FormsAuthentication class to inform ASP.NET that the credentials are valid. In Joe's case, when the credentials are provided in login.aspx, he can easily check Active Directory or any other Lightweight Directory Access Protocol directory or data store and verify those credentials. Once the credentials are verified, the user is said to be authenticated. In other words, the user is who he or she claims to be.
After authenticating a resource, you want to control access or authorize the authenticated user to various resources. This is really easy for ASP.NET resources. You simply use the existing authorization features of ASP.NET to control access to resources based upon the URL ID of the resource. However, by default, this excludes any non-ASP.NET resources. By resource, I mean any file with an extension for which ASP.NET is responsible, such as aspx, asmx, and ashx.
Joe said he wishes to authorize access to resources for which ASP.NET is not responsible, such as files with an extension of htm. This is easy to accomplish, by following these steps:
Configure Internet Information Services (IIS)
First, you need to tell IIS that any requests for files with the extension htm are to be handled by ASP.NET. To do this, follow these steps:
1) Open IIS Manager (Start | All Programs | Administrative Tools | Internet Information Services).
2) Select the Properties dialog for the Web site, to apply to the entire site. Or, select it on the specific Web application that contains non-ASP.NET resources you wish to authorize.
3) Select the Home Directory tab.
4) Within the Home Directory tab, press the Configuration button.
5) The dialog Application Configuration that opens should contain three tabs. Select the tab named Mappings.
6) In the extension column, find .aspx and double-click on it.
7) Copy the text value of the Executable field to the clipboard.
8) Return to the Mappings tab and press the Add button.
9) Paste the value copied from the aspx executable setting in the new mapping's Executable field. Type.htm in the Extension field, un-check Check that the file exists, and press OK.
10) Stop and restart IIS.
You need to tell ASP.NET what to do with the new files types you've instructed IIS to send along to ASP.NET:
1) Decide whether you want to configure this globally or only for the local application. If you want this to be a global setting, you'll make changes to the machine.config file. If you want changes to be specific to an ASP.NET application, you'll make changes to the application's web.config file. Open the appropriate file in your editor.
2) Find the <httpHandlers> section within the file and add the following line:
<add verb="GET,HEAD" path=".htm" _
Note that the addition of this line is optional because a path value of * exists already. This is simply more explicit.
Any request for an htm file will be redirected to ASP.NET, and URL authorization can participate in the authentication and authorization for the given resource. You can do the same for just about any file extension.
Joe also asked if he could allow ASP.NET to handle authentication and authorization for asp files from within ASP.NET. Unfortunately, this is not possible because ASP.NET and ASP are completely orthogonal to one another. For ASP authentication and authorization, you would need to follow the existing authentication and authorization strategy or, better yet, migrate those files to ASP.NET!
Generate a File
I'm planning a Web application that generates a file. This file is product data, which I want users to be able to download. I need help with two things:
1) How to start the download of that file automatically.
2) This operation can take hours. I need some way of showing the progress of the operation, but I can't find a way to make fields on my page update based on a timer. I know this has to be possible because the sports pages do it with in-game updates.
- John Woodward
The first part is easy to do. Once the file exists in a known location (and is known to be complete), a page can redirect the user to the known file. The following code should accomplish this:
' If the file exists, let's redirect the user to the file
It's important to call Response.End whenever a Response.Redirect is done. Otherwise, the request will continue to be processed.
The second part of the question is a bit more challenging. Any operation that can take hours is a scary operation on the Web server if it's not implemented correctly. In other words, you don't want to block Web server operations due to file generation. The Web server process uses a thread pool to handle requests. If 100 requests come in for file-generation operations that can take very long to execute, all the threads will be tied up doing the file-generation work, and none will be able to handle new requests. The best solution would be to write a Windows Service - you can do this easily with VS .NET - that accepts requests via .NET and can schedule threads within its process to perform these long-running operations. The service also should support an API that allows applications to check the status of a particular file-generation operation.
The application could be structured as follows:
1) Request for long-running file-generation operation.
2) Based on the identity of the request, the ASP.NET user code creates a unique file-name key and issues a request via .NET remoting to the File Creation Windows service.
3) Then, ASP.NET performs a Response.Redirect to a CheckFileCreationStatus.aspx page, passing the file-name key as a parameter.
4) Whenever CheckFileCreationStatus.aspx?FileName=MyFilename.xls is called, ASP.NET makes a .NET remoting call to the File Creation Windows service and receives back a status of the file creation, such as the percentage completed.
5) The response returned from CheckFileCreationStatus.aspx?FileName=MyFilename.xls contains a meta tag that forces the client to auto-refresh the page every 20 seconds. You can snag the exact syntax for this out of the docs.
6) After five such auto-refreshes, the Windows service returns complete, and CheckFileCreationStatus.aspx performs a Response.Redirect to the location of the generated file.
That's it for now. To submit questions for the "Ask Microsoft" column, send e-mail to [email protected]. In addition to answering questions, we'll send an ASP.NET T-shirt to the person who submits the best question.
Rob Howard is a program manager on the ASP.NET team. He also writes the Microsoft Developer Network's "Nothing but ASP.NET" column and is a co-author of Professional ASP.NET, from Wrox.