In "Get Ready for .NET," May 2002, InstantDoc ID 24479—the first article in my series about integrating IIS and ASP.NET—I introduced you to the Microsoft .NET Framework and showed you how to get your hands on it. I also explained the .NET Framework's two major components: the Common Language Runtime (CLR) and the .NET Framework class library. You must have a good understanding of the .NET Framework before you even consider installing it in your production environment. This month, I dig a little deeper into the inner workings of ASP.NET in relation to designing, configuring, and implementing ASP.NET's security architecture.
ASP.NET's Security Architecture
Browser-based clients communicate with ASP.NET through IIS, which translates and optionally authenticates the request. (I say "optionally" because no authentication occurs if you enable Anonymous access.) In addition, IIS finds the requested resource (i.e., the ASP.NET application's home page, default.aspx) and, if the client is authenticated and authorized, returns the resource to the client's browser. Figure 1, page 2, shows this communications process.
In addition to using built-in ASP.NET security features such as role-based security, an ASP.NET application can use low-level security features (e.g., code-access security) of the .NET Framework. Role-based security and code-access security can help software developers and IIS administrators design and deploy applications with robust security features such as principals, authentication, authorization, permissions, type safety and security, and security policies.
Principals. A principal characterizes the identity and role of a user. The principal acts by proxy on an authenticated user's behalf. Role-based security in the .NET Framework supports three kinds of principals:
- Generic principals represent users and roles that exist independent of Windows .NET Server (Win.NET Server), Windows 2000, or Windows NT server users and roles.
- Windows principals represent Windows users and their roles. Windows principals also represent Win.NET Server, Win2K, and NT server groups. A Windows principal can impersonate another user, which means that the principal can access a resource by proxy on a user's behalf.
- Custom principals are defined by software architects to meet the unique needs that applications with role-based security have beyond what the .NET Framework provides.
Authentication. Authentication is the process of discovering and verifying a principal's identity by examining the user's credentials and validating those credentials against an authority. An authority can be one of several authentication mechanisms, including Basic authentication, Digest authentication, OS schemes (e.g., Kerberos, NT LAN Manager—NTLM), or application-defined mechanisms. Most of these authentication mechanisms work seamlessly with .NET Framework's role-based security.
Authorization. Authorization is the process of determining whether a principal can perform a requested action. Authorization occurs after authentication and uses information about the principal's identity and roles to determine what resources the principal can access. Authorization is implemented in the .NET Framework by a robust role-based security system.
Permissions. The .NET Framework offers three kinds of permissions, each with a specific purpose:
- Code-access permissions provide access to a protected resource or provide the ability to perform a protected operation.
- Identity permissions provide code with credentials that support a particular kind of identity (e.g., PublisherIdentityPermission, which is a software publisher's digital signature).
- Role-based security permissions provide a mechanism for discovering whether a user (or the agent or piece of code acting on the user's behalf) has a particular identity or is a member of a specified role.
Type safety and security. Type-safe ASP.NET code accesses only the memory locations it's authorized to access. When ASP.NET code is type safe, the CLR can completely isolate assemblies (i.e., groups of programming constructs contained in files that are built, versioned, and deployed as one implementation unit) from one another. Type-safe components can execute safely in the same process. When code isn't type safe, you have large security risks such as those you see exploited by today's viruses. For example, the CLR can't prevent code that isn't type safe from calling native (i.e., unmanaged) code and performing malicious operations. When code is type safe, the CLR's security mechanisms ensure that the code doesn't access native code unless the software developer has specifically given it permission to do so.
Security policies. A security policy is a configurable set of rules by which the CLR abides when the code has calculated the roles to determine the security policy. You set the security policy in the Microsoft Management Console (MMC) Code Access Security Policy snap-in, and the CLR enforces the policy.
Authentication: The Connection Between ASP.NET and IIS
The relationship between ASP.NET authentication and the IIS authentication services is important. IIS always assumes that a set of credentials will map to a Windows account, and IIS uses those credentials to authenticate a user. You configure the type of authentication mechanism in the MMC Internet Information Services snap-in by right-clicking the Web server or virtual directory, then selecting Properties. Click the Directory Security tab, then click Edit in the Anonymous access and authentication section to access the Authentication Methods dialog box, which Figure 2 shows.
IIS 5.0 offers three authentication schemes: Basic, Digest, and Integrated Windows authentication with either NTLM or Kerberos. (For an explanation of how Integrated Windows authentication works with NTLM and Kerberos, see Leon Braginski, "Kerberos vs. NTLM," May 2002, InstantDoc ID 24473.) In addition to these three methods, IIS 6.0 offers Passport authentication. However, because the Win.NET Server family of servers (of which IIS 6.0 is a part) hasn't shipped yet, Passport authentication services are available only as a centralized authentication service that Microsoft provides. ASP.NET offers this modified form of Passport authentication. (Licensing costs are involved in using Passport as an authentication mechanism, so consult the .NET Passport Web site at http://www.microsoft.com/passport for details.)
Beyond IIS's mechanisms, ASP.NET provides Forms authentication, in which developers use HTTP client-side redirection to send authentication requirements for a protected resource to an HTML form. By using an HTML form, the software developer can easily custom-brand the logon page because it's in HTML. Microsoft Site Server 3.0 has a similar authentication mechanism for its Membership Directory Service. With Forms authentication, a user provides credentials (in the form of a username and password) and submits the form. If the ASP.NET application successfully authenticates the user, the system issues a form that contains the credentials (i.e., the key). Subsequent requests for protected resources contain the form information in the request headers, so users don't need to authenticate again.
Configuring ASP.NET Security
Configuration details for ASP.NET reside in two files: web.config and machine.config. Web.config can reside in the same directories as the ASP.NET application files. The .NET Framework or Win.NET Server OS installation process installs machine.config in the installation program root's Config directory, which is why machine.config is often called the root configuration file. If no web.config file exists in an ASP.NET application directory, the application uses the machine.config file for its configuration settings.
Subdirectories inherit a parent directory's configuration settings from web.config unless you override this inheritance by placing a unique web.config file in the subdirectory. Web.config contains sections for each major category of ASP.NET functionality, including security. Web.config and machine.config files have three major security subsections: Authentication, Authorization, and Identity Impersonate. Listing 1 shows sample XML code to configure Forms authentication in the Authentication section of a web.config or machine.config file. The <authentication mode> tag identifies which authentication method you want to use—in this case, Forms. You use parameters within the <authentication mode> tag to identify the form name and URL.
Listing 2 shows the sample XML code for the Authorization section of a web.config or machine.config file. In this section, the <allow users> tag specifies that all users are allowed. The commented lines show the format for defining which specific users and roles are allowed.
Listing 3, page 4, shows sample code for the Identity Impersonate section of a web.config or machine.config file. This code facilitates impersonation.
Table 1, page 4, which I adapted from the Microsoft .NET Framework Developer's Guide, summarizes the configuration settings available in the security sections of web.config and machine.config files. Be aware that ASP.NET configuration settings in web.config and machine.config files apply only to ASP.NET resources such as *.aspx and *.asmx (in other words, those resources that aspnet_isapi.dll is registered to handle). Unfortunately, ASP.NET configuration settings in web.config and machine.config files can't provide authorization for files that aspnet_isapi.dll doesn't handle. Files with extensions such as *.txt, *.htm, *.gif, *.jpg, and *.asp are still accessible to all users (subject to IIS permissions). Even if you secure resources in the web.config file of an ASP.NET application, all users can still view the files in that directory if you've enabled directory browsing and no other restrictions (e.g., ACLs) are in place. Fortunately, you can work around this security hole. You can explicitly map those files that, by default, aspnet_isapi.dll doesn't handle. However, configuring ASP.NET in this way incurs performance penalties, which could be dramatic depending on your situation.
At runtime, ASP.NET processes the configuration information in the web.config and machine.config files in the hierarchical virtual directory structure of IIS to calculate a group of configuration settings for each unique requested resource. IIS then caches the group of configuration settings for all subsequent resource requests.
ASP.NET automatically detects changes to configuration files and applies new configuration settings to resources that those changes affect. You don't need to restart IIS or reboot the Web server for web.config and machine.config changes to take effect. IIS automatically recalculates and caches hierarchical configuration settings whenever you change a web.config or machine.config file. However, exceptions to this automatic processing exist. For example, ASP.NET can't automatically configure the <processModel> tag while IIS is running. (The <processModel> tag specifies the process model, such as whether an ASP.NET application runs in process or out of process to IIS.)
Because the ASP.NET configuration files are XML-based, they're extensible. You can define new configuration parameters within the configuration files, and software developers can write configuration section handlers to process those custom configuration parameters. ASP.NET protects configuration files by configuring IIS to prevent direct browser access to them. IIS returns HTTP access error 403 Forbidden to any browser attempting to access a configuration file directly.
You should now have a basic understanding of ASP.NET's security architecture, its relation to IIS, and how to configure ASP.NET security. Next time, I'll continue this ASP.NET series by showing you how to optimize performance in IIS for ASP.NET applications. I'll also cover some advanced ASP.NET configuration topics.