It’s impossible to be a consultant these days without being aware of basic security concepts. Take Web applications, for example. When you’re installing a new ASP.NET application for a client, they’re very likely to want to limit who can use all or part of the application.
To handle the client's needs, you need to understand both authentication (obtaining credentials from the user and using those credentials to verify the user’s identity) and authorization (allowing an authenticated user access to resources). ASP.NET provides flexible ways to configure authentication, but you need to know which settings to make in ASP.NET, which settings to make in IIS, and how they all interact.
ASP.NET configuration files
Most ASP.NET settings are stored in an XML file named Web.config. Each Web application has its own configuration file stored in the root of the application that dictates the master settings for that app. Any subdirectory can contain its own Web.config file that overrides settings in the master configuration file for that subdirectory only. This can be handy if just some of the pages in your application are sensitive; you can put those pages in their own subdirectory with a higher-security Web.config file.
There’s also a master configuration file named Machine.config installed in the .NET Framework configuration directory (under your Windows directory). Generally, you shouldn’t make settings in this file, because such settings apply to all Web applications on the computer.
Sometimes it’s easy
In some cases, you won’t need to authenticate users at all. For example, you might be delivering a Web application that allows users to browse through literature about a company’s products. In that case, you probably want to set ASP.NET to not require any authentication. You can do that by making this setting in the configuration file:
<authentication mode="None" />
The result of this setting is that the application will be available to anonymous users—at least, if IIS lets anonymous users through. To show you how the two systems interact, I need to dig into the actual authentication process.
IIS and ASP.NET authentication
You can think of ASP.NET authentication as having two distinct gateways. The first gateway is maintained by IIS, which gets first crack at any HTTP request arriving at your server. Only if IIS decides to let the request through the gateway does ASP.NET get to apply its own authentication rules. If IIS denies a request, ASP.NET will never even know that the request was made.
Here’s an overview of the whole process, showing the various ways in which a request for an ASP.NET page can be denied or allowed:
- IIS first checks to make sure that the incoming request comes from an IP address that is allowed access to the domain. If not, the request is denied.
- Next, IIS performs its own user authentication, if it's configured to do so. By default, IIS allows anonymous access, so requests are automatically authenticated, but you can change this default on a per-application basis within IIS.
- If the request is passed to ASP.NET with an authenticated user, ASP.NET checks to see whether impersonation is enabled. If it is, ASP.NET acts as though it were the authenticated user. If not, ASP.NET acts with its own configured account.
- Finally, the identity from the previous step is used to authorize resources from the operating system. If all the necessary resources can be obtained, the user's request is granted; otherwise, it is denied. Resources can include much more than just the ASP.NET page itself. You can also use .NET’s code-access security features to extend this authorization step to disk files, Registry keys, and other resources.
ASP.NET includes the concept of pluggable authentication providers. Out of the box, three authentication providers are available (and in theory, at least, you can write your own if none of them is suitable). Odds are, you’ll find that one of the stock three providers is right for an ASP.NET application that needs to limit access:
- The Windows authentication provider allows you to authenticate users based on their Windows accounts. This provider uses IIS to perform the actual authentication and then passes the authenticated identity to your code. This is the default provider for ASP.NET.
- The Passport authentication provider uses Microsoft's Passport service to authenticate users.
- The Forms authentication provider uses custom HTML forms to collect authentication information and allows you to use your own logic to authenticate users. The user’s credentials are then stored in a cookie for use during the session.
To select an authentication provider, you just need to make the appropriate entry in the application’s Web.config file:
<authentication mode="Windows" />
<authentication mode="Passport" />
<authentication mode="Forms" />
Windows authentication and IIS
If you select Windows authentication for your ASP.NET application, you also need to configure authentication within IIS. That’s because Windows authentication is delegated back to IIS. IIS gives you a choice of four authentication methods:
- If you select anonymous authentication, IIS does not perform any authentication. Anyone is allowed access to the ASP.NET application.
- If you select basic authentication, users must provide a Windows username and password to connect. This information is sent across the network in clear text, making basic authentication dangerously insecure on the Internet.
- If you select digest authentication, users must still provide a Windows username and password to connect. However, the password is hashed before being sent across the network. Digest authentication requires that all users be running Internet Explorer 5 or later and that Windows accounts be stored in Active Directory.
- If you select Windows integrated authentication, passwords never cross the network. Users must still have a Windows username and password, but either the Kerberos or challenge/response protocols are used to authenticate the user. Windows-integrated authentication requires that all users be running Internet Explorer 3.01 or later.
Passport authentication lets you use Microsoft's Passport service to authenticate users of your application. If your users have signed up with Passport, and you configure the authentication mode of the application to be Passport authentication, all authentication duties are offloaded to the Passport servers. To use Passport authentication, you'll need to download Microsoft’s Passport Software Development Kit (SDK).
You will probably find Passport to be an unattractive choice for most applications because it’s an expensive choice. Currently, using Passport in a production application requires you to pay $10,000 per year, plus a periodic $1,500 testing fee for each protected URL.
Forms authentication lets you handle authentication by using custom logic within an ASP.NET Web form. When a user requests any page from the application, ASP.NET checks for a special session cookie. If the cookie is present, the request succeeds. If the cookie isn’t present, your custom form is loaded instead. You can ask for a password, check for a username in a database, or perform any other form of authentication you like.
When you’re satisfied, you tell ASP.NET that the user is authenticated and it creates the special cookie for future requests during the same session.
There’s one more question to answer after a user is authenticated: What identity does the user have within your application? The answer to this question depends on whether you’ve implemented impersonation within your ASP.NET application. Your choices are to disable impersonation, to enable impersonation of the authenticated user, or to enable impersonation of a specific named user.
The default setting is to disable impersonation. You can make this setting explicit by including this line in the application’s configuration file:
With this setting, ASP.NET won’t impersonate the authenticated user. Instead, it will present its own credentials when asking for resources. By default, ASP.NET runs as an unprivileged account named ASPNET. You can change this by making a setting in the processModel section of the Machine.config file. This setting can be changed only in Machine.config, so any change automatically applies to every site on the server (and no site can have a setting different from that of the server). To use a high-privilege system account instead of a low-privilege account, set the userName attribute of the processModel element to SYSTEM. This will allow ASP.NET access to more resources—and make it correspondingly easier to shoot yourself in the foot.
When impersonation is disabled, all requests will run in the context of the account running ASP.NET: either the ASPNET account or the system account. This is true whether you're using anonymous access or authenticating users in some fashion. After the user has been authenticated, ASP.NET uses its own identity (rather than that of the user) to request access to resources.
The second possible setting is to turn on impersonation:
In this case, ASP.NET takes on the identity passed to it by IIS. If you're allowing anonymous access in IIS, this means that ASP.NET will impersonate the IUSR_ComputerName account that IIS itself uses. If you're not allowing anonymous access, ASP.NET will take on the credentials of the authenticated user and make requests for resources as if it were that user. Thus, by turning impersonation on and using a nonanonymous method of authentication in IIS, you can let users log on and use their identities within your ASP.NET application. That is, if user Joe uses Windows authentication to identify himself, and you have impersonation turned on, ASP.NET will pretend to be Joe when it asks for access to resources.
The third possibility is to specify a particular identity to use for all authenticated requests:
If you make this setting, all requests are made as the specified user no matter who logs on to the application or what means of authentication they use. This is an easy way to use an application-specific account for all security requests, but it also means storing a password in the configuration file. ASP.NET won’t allow this file to be downloaded, but any administrator on your LAN can get to it.
What to do?
What’s best for your application? Only you can answer that question, but here are some rules of thumb to go by:
- If there’s nothing sensitive about the application, stick with no authentication in ASP.NET and anonymous authentication in IIS. That lets anyone who can reach the host computer via TCP/IP use the application.
- If you need to limit access, but all authenticated users have the same privileges, turn on Windows authentication and then use impersonation of an application-specific account.
- If you need to limit access and distinguish between users, turn on Windows authentication or forms authentication and impersonate the authenticated user.
And remember, whatever you do: Understand what you’re choosing and test your code. Security is never something to be taken lightly.