Training
Certifications
Books
Special Offers
Community




 
Building Secure Microsoft® ASP.NET Applications
Author Microsoft Corporation
Pages 620
Disk N/A
Level Int/Adv
Published 01/22/2003
ISBN 9780735618909
Price $49.99
To see this book's discounted price, select a reseller below.
 

More Information

About the Book
Table of Contents
Sample Chapter
Index
Companion Content
Related Series
Related Books
About the Author

Support: Book & CD

Rate this book
Barnes Noble Amazon Quantum Books

 


Chapter 8: ASP.NET Security



8   ASP.NET Security

This chapter presents guidance and recommendations that will help you build secure ASP.NET Web applications. Much of the guidance and many of the recommendations presented in this chapter also apply to the development of ASP.NET Web services and .NET Remoting objects hosted by ASP.NET.

ASP.NET Security Architecture

ASP.NET works in conjunction with IIS, the .NET Framework, and the underlying security services provided by the operating system, to provide a range of authentication and authorization mechanisms. These are summarized in Figure 8.1 on the next page.

Figure 8.1 illustrates the authentication and authorization mechanisms provided by IIS and ASP.NET. When a client issues a Web request, the following sequence of authentication and authorization events occurs:

  1. The HTTP(S) Web request is received from the network. SSL can be used to ensure the server identity (using server certificates) and, optionally, the client identity.
  2. IIS authenticates the caller by using Basic, Digest, Integrated (NTLM or Kerberos), or Certificate authentication. If all or part of your site does not require authenticated access, IIS can be configured for anonymous authentication. IIS creates a Windows access token for each authenticated user. If anonymous authentication is selected, IIS creates an access token for the anonymous Internet user account (which, by default, is IUSR_MACHINE).
  3. Click to view graphic
    Click to view graphic

    Figure 8.1 ASP.NET security services

  4. IIS authorizes the caller to access the requested resource. NTFS permissions defined by ACLs attached to the requested resource are used to authorize access. IIS can also be configured to accept requests only from client computers with specific IP addresses.
  5. IIS passes the authenticated caller's Windows access token to ASP.NET (this may be the anonymous Internet user's access token, if anonymous authentication is being used).
  6. ASP.NET authenticates the caller.
  7. If ASP.NET is configured for Windows authentication, no additional authentication occurs at this point. ASP.NET will accept any token it receives from IIS.

    If ASP.NET is configured for Forms authentication, the credentials supplied by the caller (using an HTML form) are authenticated against a data store; typically a Microsoft® SQL Server database or Active Directory® directory service. If ASP.NET is configured for Passport authentication, the user is redirected to a Passport site and the Passport authentication service authenticates the user.

  8. ASP.NET authorizes access to the requested resource or operation.
  9. The UrlAuthorizationModule (a system provided HTTP module) uses authorization rules configured in Web.config (specifically, the <authorization> element) to ensure that the caller can access the requested file or folder.

    With Windows authentication, the FileAuthorizationModule (another HTTP module) checks that the caller has the necessary permission to access the requested resource. The caller's access token is compared against the ACL that protects the resource.

    .NET roles can also be used either declaratively or programmatically to ensure that the caller is authorized to access the requested resource or perform the requested operation.

  10. Code within your application accesses local and/or remote resources by using a particular identity. By default, ASP.NET performs no impersonation and as a result, the configured ASP.NET process account provides the identity. Alternate options include the original caller's identity if impersonation is enabled, or a configured service identity.

Gatekeepers

The authorization points or gatekeepers within an ASP.NET Web application are provided by IIS and ASP.NET:

IIS

With anonymous authentication turned off, IIS permits requests only from users that it can authenticate either in its domain or in a trusted domain.

For static file types (for example .jpg, .gif and .htm files — files that are not mapped to an ISAPI extension), IIS uses the NTFS permissions associated with the requested file to perform access control.

ASP.NET

The ASP.NET gatekeepers include the UrlAuthorizationModule, FileAuthorizationModule and principal permission demands and role checks.

UrlAuthorizationModule

You can configure <authorization> elements within your application's Web.config file to control which users and groups of users should have access to the application. Authorization is based on the IPrincipal object stored in HttpContext.User.

FileAuthorizationModule

For file types mapped by IIS to the ASP.NET ISAPI extension (Aspnet_isapi.dll), automatic access checks are performed using the authenticated user's Windows access token (which may be IUSR_MACHINE) against the ACL attached to the requested ASP.NET file.

The FileAuthorizationModule class only performs access checks against the requested file, and not for files accessed by the code in the requested page, although these are access checked by IIS.

For example, if you request Default.aspx and it contains an embedded user control (Usercontrol.ascx), which in turn includes an image tag (pointing to Image.gif), the FileAuthorizationModule performs an access check for Default.aspx and Usercontrol.ascx, because these file types are mapped by IIS to the ASP.NET ISAPI extension.

The FileAuthorizationModule does not perform a check for Image.gif, because this is a static file handled internally by IIS. However, as access checks for static files are performed by IIS, the authenticated user must still be granted read permission to the file with an appropriately configured ACL.

This scenario is shown in Figure 8.2.

Click to view graphic
Click to view graphic

Figure 8.2 IIS and ASP.NET gatekeepers working together

In this scenario you can prevent access at the file gate. If you configure the ACL attached to Default.aspx and deny access to a particular user, the user control or any embedded images will not get a chance to be sent to the client by the code in Default.aspx. If the user requests the images directly, IIS performs the access checks itself.

Principal Permission Demands and Explicit Role Checks

In addition to the IIS and ASP.NET configurable gatekeepers, you can also use principal permission demands (declaratively or programmatically) as an additional fine-grained access control mechanism. Principal permission checks (performed by the PrincipalPermissionAttribute class) allow you to control access to classes, methods, or individual code blocks based on the identity and group membership of individual users, as defined by the IPrincipal object attached to the current thread.

With Windows authentication, ASP.NET automatically attaches a WindowsPrincipal object that represents the authenticated user to the current Web request (using HttpContext.User). Forms and Passport authentication create a GenericPrincipal object with the appropriate identity and no roles and attaches it to the HttpContext.User.

More Information

  • For more information about configuring security, see "Configuring Security" later in this chapter.
  • For more information about programming security (and IPrincipal objects), see "Programming Security" later in this chapter.

Authentication and Authorization Strategies

ASP.NET provides a number of declarative and programmatic authorization mechanisms that can be used in conjunction with a variety of authentication schemes. This allows you to develop an in depth authorization strategy and one that can be con.figured to provide varying degrees of granularity; for example, per-user or per-user group (role-based).

This section shows you which authorization options (both configurable and programmatic) are available for a set of commonly used authentication options.

The authentication options that follow are summarized here:

  • Windows authentication with impersonation
  • Windows authentication without impersonation
  • Windows authentication using a fixed identity
  • Forms authentication
  • Passport authentication

Available Authorization Options

The following table shows you the set of available authorization options. For each one the table indicates whether or not Windows authentication and/or impersonation are required. If Windows authentication is not required, the particular authorization option is available for all other authentication types. Use the table to help refine your authentication/authorization strategy.

Table 8.1: Windows authentication and impersonation requirements

Authorization OptionRequires Windows AuthenticationRequires Impersonation
FileAuthorizationModuleYesNo
UrlAuthorizationModuleNoNo
Principal Permission DemandsNoNo
.NET RolesNoNo
Enterprise Services RolesYesYes (within the ASP.NET Web application)
NTFS Permissions (for directly requested static files types; not mapped to an ISAPI extension)N/A - These files are not handled by ASP.NET. With any (non-Anonymous) IIS authentication mechanism, permissions should be configured for individual authenticated users. With Anonymous authentication, permissions should be configured for IUSR_MACHINE.No (IIS performs the access check.)
NTFS Permissions (for files accessed by Web application code)NoNo. If impersonating, configure ACLs against the impersonated Windows identity, which is either the original caller or the identity specified on the <identity> element in Web.config*.

Windows Authentication with Impersonation

The following configuration elements show you how to enable Windows (IIS) authentication and impersonation declaratively in Web.config or Machine.config.

<authentication mode="Windows" />
<identity impersonate="true" />

With this configuration, your ASP.NET application code impersonates the IIS-authenticated caller.

Configurable Security

When you use Windows authentication together with impersonation, the following authorization options are available to you:

  • Windows ACLs
    • Client Requested Resources. The ASP.NET FileAuthorizationModule performs access checks for requested file types that are mapped to the ASP.NET ISAPI. It uses the original caller's access token and ACL attached to requested resources in order to perform access checks.
    • For static files types (not mapped to an ISAPI extension), IIS performs access checks using the caller's access token and ACL attached to the file.

    • Resources Accessed by Your Application. You can configure Windows ACLs on resources accessed by your application (files, folders, registry keys, Active Directory objects, and so on) against the original caller.

  • URL Authorization. Configure URL authorization in Web.config. With Windows authentication, user names take the form DomainName\UserName and roles map one-to-one with Windows groups.
  • <authorization>
      <deny user="DomainName\UserName" />
      <allow roles="DomainName\WindowsGroup" />
    </authorization>

  • Enterprise Services (COM+) Roles. Roles are maintained in the COM+ catalog. You can configure roles with the Component Services administration tool or script.

Programmatic Security

Programmatic security refers to security checks located within your Web application code. The following programmatic security options are available when you use Windows authentication and impersonation:

  • PrincipalPermission Demands
    • Imperative (in-line within a method's code)
    •     PrincipalPermission permCheck = new PrincipalPermission(
                                             null, @"DomainName\WindowsGroup");
          permCheck.Demand();

    • Declarative (attributes preceding interfaces, classes and methods)
    • [PrincipalPermission(SecurityAction.Demand, 
                        Role=@"DomainName\WindowsGroup)]

  • Explicit Role Checks. You can perform role checking using the IPrincipal Sinterface.
  • IPrincipal.IsInRole(@"DomainName\WindowsGroup");

  • Enterprise Services (COM+) Roles. You can perform role checking programmatically using the ContextUtil class.
  • ContextUtil.IsCallerInRole("Manager")

When to Use

Use Windows authentication and impersonation when:

  • Your application's users have Windows accounts that can be authenticated by the server.
  • You need to flow the original caller's security context to the middle tier and/or data tier of your Web application to support fine-grained (per-user) authorization.
  • You need to flow the original caller's security context to the downstream tiers to support operating system level auditing.

Before using impersonation within your application, make sure you understand the relative trade-offs of this approach in comparison to using the trusted subsystem model. These were elaborated upon in "Choosing a Resource Access Model" in Chapter 3, "Authentication and Authorization Design."

The disadvantages of impersonation include:

  • Reduced application scalability due to the inability to effectively pool database connections.
  • Increased administration effort as ACLs on back-end resources need to be configured for individual users.
  • Delegation requires Kerberos authentication and a suitably configured environment.

More Information

  • For more information about Windows authentication, see "Windows Authentication" later in this chapter.
  • For more information about impersonation, see "Impersonation" later in this chapter.
  • For more information about URL authorization, see "URL Authorization Notes" later in this chapter.
  • For more information about Enterprise Services (COM+) roles, see Chapter 9, "Enterprise Services Security."
  • For more information about PrincipalPermission demands, see "Identities and Principals" in Chapter 2, "Security Model for ASP.NET Application."

Windows Authentication without Impersonation

The following configuration elements show how you enable Windows (IIS) authentication with no impersonation declaratively in Web.config.

<authentication mode="Windows" />
<!-- The following setting is equivalent to having no identity element -->
<identity impersonate="false" />

Configurable Security

When you use Windows authentication without impersonation, the following authorization options are available to you:

  • Windows ACLs
    • Client Requested Resources. The ASP.NET FileAuthorizationModule performs access checks for requested file types that are mapped to the ASP.NET ISAPI. It uses the original caller's access token and ACL attached to requested resources in order to perform access checks. Impersonation is not required.
    • For static files types (not mapped to an ISAPI extension) IIS performs access checks using the caller's access token and ACL attached to the file.

    • Resources accessed by your application. Configure Windows ACLs on resources accessed by your application (files, folders, registry keys, Active Directory objects) against the ASP.NET process identity.

  • URL Authorization. Configure URL Authorization in Web.config. With Windows authentication, user names take the form DomainName\UserName and roles map one-to-one with Windows groups.
  • <authorization>
      <deny user="DomainName\UserName" />
      <allow roles="DomainName\WindowsGroup" />
    </authorization>

Programmatic Security

The following programmatic security options are available:

  • Principal Permission Demands
    • Imperative
    •     PrincipalPermission permCheck = new PrincipalPermission(
                                               null,
      @"DomainName\WindowsGroup");
          permCheck.Demand();

    • Declarative
    • [PrincipalPermission(SecurityAction.Demand, 
                        Role=@"DomainName\WindowsGroup")]

  • Explicit Role Checks. You can perform role checking using the IPrincipal interface.
  • IPrincipal.IsInRole(@"DomainName\WindowsGroup");

When to Use

Use Windows authentication without impersonation when:

  • Your application's users have Windows accounts that can be authenticated by the server.
  • You want to use a fixed identity to access downstream resources (for example, databases) in order to support connection pooling.

More Information

  • For more information about Windows authentication, see "Windows Authentication" later in this chapter.
  • For more information about URL authorization, see "URL Authorization Notes", later in this chapter.
  • For more information about PrincipalPermission demands, see "Principals" within the "Getting Started" section of this book.

Windows Authentication Using a Fixed Identity

The <identity> element in Web.config supports optional user name and password attributes, which allows you to configure a specific fixed identity for your application to impersonate. This is shown in the following configuration file fragment.

<identity impersonate="true"
          userName="registry:HKLM\SOFTWARE\YourSecureApp\
                    identity\ASPNET_SETREG,userName"
          password="registry:HKLM\SOFTWARE\YourSecureApp\
                    identity\ASPNET_SETREG,password" />

This example shows the <identity> element where the credentials are encrypted in the registry using the aspnet_setreg.exe utility. The clear text userName and password attribute values have been replaced with pointers to the secured registry key and named values that contain the encrypted credentials. For details about this utility and to download it, see article Q329290, "HOWTO: Use the ASP.NET Utility to Encrypt Credentials and Session State Connection Strings" in the Microsoft Knowledge Base.

When to Use

Using a fixed impersonated identity is not recommended when using the .NET Framework 1.0 on Windows 2000 servers. This is because you would need to give the ASP.NET process account the powerful "Act as part of the operating system" privilege. This privilege is required by the ASP.NET process because it performs a LogonUser call using the credentials that you have provided.

Forms Authentication

The following configuration elements show how you enable Forms authentication declaratively in Web.config.

<authentication mode="Forms">
  <forms loginUrl="logon.aspx" name="AuthCookie" timeout="60" path="/">
  </forms>
</authentication>

Configurable Security

When you use Forms authentication, the following authorization options are available to you:

  • Windows ACLs
    • Client Requested Resources. Requested resources require ACLs that allow read access to the anonymous Internet user account. (IIS should be configured to allow anonymous access when you use Forms authentication).
    • ASP.NET File authorization is not available because it requires Windows authentication.

    • Resources Accessed by Your Application. Configure Windows ACLs on resources accessed by your application (files, folders, registry keys, and Active Directory objects) against the ASP.NET process identity.

  • URL Authorization  
  • Configure URL Authorization in Web.config. With Forms authentication, the format of user names is determined by your custom data store; a SQL Server database, or Active Directory.

    • If you are using a SQL Server data store:
    • <authorization>
      <deny users="?" />
        <allow users="Mary,Bob,Joe" roles="Manager,Sales" />
      </authorization>

    • If you are using Active Directory as your data store, user names, and group names appear in X.500 format:
    • <authorization>
        <deny users="someAccount@domain.corp.yourCompany.com" />
        <allow roles ="CN=Smith James,CN=FTE_northamerica,CN=Users,
                      DC=domain,DC=corp,DC=yourCompany,DC=com" />
      </authorization>

Programmatic Security

The following programmatic security options are available:

  • Principal Permission Demands
    • Imperative
    •     PrincipalPermission permCheck = new PrincipalPermission(
                                               null, "Manager");
          permCheck.Demand();

    • Declarative
    • [PrincipalPermission(SecurityAction.Demand, 
                        Role="Manager")]

  • Explicit Role Checks. You can perform role checking using the IPrincipal interface.
  • IPrincipal.IsInRole("Manager");

When to Use

Forms authentication is most ideally suited to Internet applications. Use Forms authentication when:

  • Your application's users do not have Windows accounts.
  • You want users to log on to your application by entering credentials using an HTML form.

More Information

  • For more information about Forms authentication, see "Forms Authentication" later in this chapter.
  • For more information about URL authorization, see "URL Authorization Notes" later in this chapter.

Passport Authentication

The following configuration elements show how you enable Passport authentication declaratively in Web.config.

<authentication mode="Passport" />

When to Use

Passport authentication is used on the Internet when application users do not have Windows accounts and you want to implement a single-sign-on solution. Users who have previously logged on with a Passport account at a participating Passport site will not have to log on to your site configured with Passport authentication.

Configuring Security

This section shows you the practical steps required to configure security for an ASP.NET Web application. These are summarized in Figure 8.3 on the next page.

Click to view graphic
Click to view graphic

Figure 8.3 Configuring ASP.NET application security

Configure IIS Settings

To configure IIS security, you must perform the following steps:

  1. Optionally install a Web server certificate (if you need SSL).
  2. For more information, see "How To: Set Up SSL on a Web Server" in the Reference section of this book.

  3. Configure IIS authentication.
  4. Optionally configure client certificate mapping (if using certificate authentication).
  5. For more information about client certificate mapping, see article Q313070, "How to Configure Client Certificate Mappings in Internet Information Services (IIS) 5.0" in the Microsoft Knowledge Base.

  6. Set NTFS permissions on files and folders. Between them, IIS and the ASP.NET FileAuthorizationModule check that the authenticated user (or the anonymous Internet user account) has the necessary access rights (based on ACL settings) to access the requested file.

Configure ASP.NET Settings

Application level configuration settings are maintained in Web.config files, which are located in your application's virtual root directory and optionally within additional subfolders (these settings can sometimes override the parent folder settings).

  1. Configure authentication. This should be set on a per-application basis (not in Machine.config) in the Web.config file located in the application's virtual root directory.
  2. <authentication mode="Windows|Forms|Passport|None" />

  3. Configure Impersonation. By default, ASP.NET applications do not impersonate. The applications runs using the configured ASP.NET process identity (usually ASPNET) and all resource access performed by your application uses this identity. You only need impersonation in the following circumstances:
    • You are using Enterprise Services and you want to use Enterprise Services (COM+) roles to authorize access to functionality provided by serviced components.
    • IIS is configured for Anonymous authentication and you want to use the anonymous Internet user account for resource access. For details about this approach, see "Accessing Network Resources" later in this chapter.
    • You need to flow the authenticated user's security context to the next tier (for example, the database).
    • You have ported a classic ASP application to ASP.NET and want the same impersonation behavior. Classic ASP impersonates the caller by default.

    To configure ASP.NET impersonation use the following <identity> element in your application's Web.config.

    <identity impersonate="true" />

  4. Configure Authorization. URL authorization determines whether a user or role can issue specific HTTP verbs (for example, GET, HEAD, and POST) to a specific file. To implement URL authorization, you perform the following tasks.
    1. Add an <authorization> element to the Web.config file located in your application's virtual root directory.
    2. Restrict access to users and roles by using allow and deny attributes. The following example from Web.config uses Windows authentication and allows Bob and Mary access but denies everyone else.
    3. <authorization>
        <allow users="DomainName\Bob, DomainName\Mary" />
        <deny users="*" />
      </authorization>

URL Authorization Notes

Take note of the following when you configure URL authorization:

  • "*" refers to all identities.
  • "?" refers to unauthenticated identities (that is, the anonymous identity).
  • You don't need to impersonate for URL authorization to work.
  • Authorization settings in Web.config usually refer to all of the files in the current directory and all subdirectories (unless a subdirectory contains its own Web.config with an <authorization> element. In this case the settings in the subdirectory override the parent directory settings).
  • You can use the <location> tag to apply authorization settings to an individual file or directory. The following example shows how you can apply authorization to a specific file (Page.aspx).

    <location path="page.aspx" />
      <authorization>
        <allow users="DomainName\Bob, DomainName\Mary" />
        <deny users="*" />
      </authorization>
    </location>

  • Users and roles for URL authorization are determined by your authentication settings:
    • When you have <authentication mode="Windows" /> you are authorizing access to Windows user and group accounts.
    • User names take the form "DomainName\WindowsUserName"

      Role names take the form "DomainName\WindowsGroupName"

    • When you have <authentication mode="Forms" /> you are authorizing against the user and roles for the IPrincipal object that was stored in the current HTTP context. For example, if you used Forms to authenticate users against a database, you will be authorizing against the roles retrieved from the database.
    • When you have <authentication mode="Passport" /> you authorize against the Passport User ID (PUID) or roles retrieved from a store. For example, you can map a PUID to a particular account and set of roles stored in a SQL Server database or Active Directory.
    • When you have <authentication mode="None" /> you may not be performing authorization. "None" specifies that you don't want to perform any authentication or that you don't want to use any of the .NET authentication modules and want to use your own custom mechanism.
    • However, if you use custom authentication, you should create an IPrincipal object with roles and store it into the HttpContext.User. When you subsequently perform URL authorization, it is performed against the user and roles (no matter how they were retrieved) maintained in the IPrincipal object.

URL Authorization Examples

The following list shows the syntax for some typical URL authorization examples:

  • Deny access to the anonymous account
  •  <deny users="?" />

  • Deny access to all users
  • <deny users="*"/>

  • Deny access to Manager role
  • <deny roles="Manager"/>

  • Forms authentication example
  • <configuration>
      <system.web>
          <authentication mode="Forms">
            <forms name=".ASPXUSERDEMO"
                   loginUrl="login.aspx"
                   protection="All" timeout="60" />
          </authentication>
          <authorization>
            <deny users="jdoe@somewhere.com" />
            <deny users="?" />
          </authorization>
      </system.web>
    </configuration>

Secure Resources

  1. Use Windows ACLs to secure resources that include files, folders, and registry keys.
  2. If you are not impersonating, any resource your application is required to access must have an ACL that grants at least read access to the ASP.NET process account.

    If you are impersonating, files and registry keys must have an ACL that grants at least read access to the authenticated user (or the anonymous Internet user account, if anonymous authentication is in effect).

  3. Secure Web.config and Machine.config:
    • Use the Correct ACLs. If ASP.NET is impersonating, the impersonated identity requires read access. Otherwise, the ASP.NET process identity requires read access. Use the following ACL on Web.config and Machine.config.
    • System: Full Control

      Administrators: Full Control

      Process Identity or Impersonated Identity : Read

      If you are not impersonating the anonymous Internet user account (IUSR_MACHINE), you should deny access to this account.

    • Remove Unwanted HTTP Modules. Machine.config contains a set of default HTTP modules (within the <httpModules> element. These include:
      • WindowsAuthenticationModule
      • FormsAuthenticationModule
      • PassportAuthenticationModule
      • UrlAuthorizationModule
      • FileAuthorizationModule
      • OutputCacheModule
      • SessionStateModule
      If your application doesn't use a specific module, remove it to prevent any potential future security issues associated with a particular module from being exploited within your application.

  4. Optionally, lock configuration settings by using the <location> element together with the allowOverride="false" attribute as described below.

Locking Configuration Settings

Configuration settings are hierarchical. Web.config file settings in subdirectories override Web.config settings in parent directories. Also, Web.config settings override Machine.config settings.

You can lock configuration settings to prevent them being overridden at lower levels, by using the <location> element coupled with the allowOverride attribute. For example:

<location path="somepath" allowOverride="false" />
. . . arbitrary configuration settings . . .
</location>

Note that the path may refer to a Web site or virtual directory and it applies to the nominated directory and all subdirectories. If you set allowOverride to false, you prevent any lower level configuration file from overriding the settings specified in the <location> element. The ability to lock down configuration settings applies to all types of setting and not just security settings such as authentication modes.

In the context of machine.config, the path must be fully qualified and include the Web site, virtual directory name and optionally a sub directory and filename. For example:

<location path="Web Site Name/VDirName/SubDirName/PageName.aspx" >
. . .
</location>

In the context of web.config, the path is relative from the application's virtual directory. For example:

<location path="SubDirName/PageName.aspx" >
. . .
</location>

Preventing Files from Being Downloaded

You can use the HttpForbiddenHandler class to prevent certain file types from being downloaded over the Web. This class is used internally by ASP.NET to prevent the download of certain system level files (for example, configuration files including web.config). For a complete list of file types restricted in this way, see the <httpHandlers> section in machine.config.

You should consider using the HttpForbiddenHandler for files that your application uses internally, but are not intended for download.

To use the HttpForbiddenHandler to prevent a particular file type from being downloaded

  1. Create an application mapping in IIS for the specified file type to map it to Aspnet_isapi.dll.
    1. On the taskbar, click the Start button, click Programs, click Administrative Tools, and then select Internet Information Services.
    2. Select your application's virtual directory, right-click, and then click Properties.
    3. Select Application Settings, click Configuration.
    4. Click Add to create a new application mapping.
    5. Click Browse, and select c:\winnt\Microsoft.NET\Framework\v1.0.3705\aspnet_isapi.dll.
    6. Enter the file extension for the file type you want to prevent being downloaded (for example, .abc) in the Extension field.
    7. Ensure All Verbs and Script engine is selected and Check that file exists is not selected.
    8. Click OK to close the Add/Edit Application Extension Mapping dialog box.
    9. Click OK to close the Application Configuration dialog box, and then click OK again to close the Properties dialog box.

  2. Add an <HttpHandler> mapping in Web.config for the specified file type.
  3. An example for the .abc file type is shown below.

    <httpHandlers>
      <add verb="*" path="*.abc"
        type="System.Web.HttpForbiddenHandler"/>
    </httpHandlers>

Secure Communication

Use a combination of SSL and Internet Protocol Security (IPSec) to secure communication links.

More information

  • For information about using SSL to secure the link to the database server, see "How To: Use SSL to Secure Communication with SQL Server 2000."
  • For information about using IPSec between two computers, see "How To: Use IPSec to Provide Secure Communication Between Two Servers."

Programming Security

After you establish your Web application's configurable security settings, you need to further enhance and fine-tune your application's authorization policy programmatically. This includes using declarative .NET attributes within your assemblies and performing imperative authorizing checks within code.

This section highlights the key programming steps required to perform authorization within an ASP.NET Web application.

An Authorization Pattern

The following summarizes the basic pattern for authorizing users within your Web application:

  1. Retrieve credentials
  2. Validate credentials
  3. Put users in roles
  4. Create an IPrincipal object
  5. Put the IPrincipal object into the current HTTP context
  6. Authorize based on the user identity / role membership

Retrieve Credentials

You must start by retrieving a set of credentials (user name and password) from the user. If your application does not use Windows authentication, you need to ensure that clear text credentials are properly secured on the network by using SSL.

Validate Credentials

If you have configured Windows authentication, credentials are validated automatically using the underlying services of the operating system.

If you use an alternate authentication mechanism, you must write code to validate credentials against a data store such as a SQL Server database or Active Directory.

For more information about how to securely store user credentials in a SQL Server database, see "Authenticating Users Against a Database" within Chapter 12, "Data Access Security."

Put Users in Roles

Your user data store should also contain a list of roles for each user. You must write code to retrieve the role list for the validated user.

Create an IPrincipal Object

Authorization occurs against the authenticated user, whose identity and role list is maintained within an IPrincipal object (which flows in the context of the current Web request).

If you have configured Windows authentication, ASP.NET automatically constructs a WindowsPrincipal object. This contains the authenticated user's identity together with a role list, which equates to the list of Windows groups to which the user belongs.

If you are using Forms, Passport, or custom authentication, you must write code within the Application_AuthenticateRequest event handler in Global.asax to create an IPrincipal object. The GenericPrincipal class is provided by the .NET Framework, and should be used in most scenarios.

Put the IPrincipal Object into the Current HTTP Context

Attach the IPrincipal object to the current HTTP context (using the HttpContext.User variable). ASP.NET does this automatically when you use Windows authentication. Otherwise, you must attach the object manually.

Authorize Based on the User Identity and/or Role Membership

Use .NET roles either declaratively (to obtain class or method level authorization), or imperatively within code if your application requires more fine-grained authorization logic.

You can use declarative or imperative principal permission demands (using the PrincipalPermission class), or you can perform explicit role checks by calling the IPrincipal.IsInRole() method.

The following example assumes Windows authentication and shows a declarative principal permission demand. The method that follows the attribute will only be executed if the authenticated user is a member of the Manager Windows group. If the caller is not a member of this group, a SecurityException is thrown.

[PrincipalPermission(SecurityAction.Demand, 
                     Role=@"DomainName\Manager")]
public void SomeMethod()
{
}

The following example shows an explicit role check within code. This example assumes Windows authentication. If a non-Windows authentication mechanism is used, the code remains very similar. Instead of casting the User object to a WindowsPrincipal object, it should be cast to a GenericPrincipal object.

// Extract the authenticated user from the current HTTP context. 
// The User variable is equivalent to HttpContext.Current.User if you are
// using an .aspx or .asmx page
WindowsPrincipal authenticatedUser = User as WindowsPrincipal;
if (null != authenticatedUser)
{
  // Note: To retrieve the authenticated user's username, use the
  // following line of code
  // string username = authenticatedUser.Identity.Name;

  // Perform a role check
  if (authenticatedUser.IsInRole(@"DomainName\Manager") )
  {
    // User is authorized to perform manager functionality
  }
}
else
{
  // User is not authorized to perform manager functionality
}

More Information

For a practical implementation of the above pattern for Forms authentication, see the "Forms Authentication" section later in this chapter.

Creating a Custom IPrincipal class

The GenericPrincipal class provided by the .NET Framework should be used in most circumstances when you are using a non-Windows authentication mechanism. This provides role checks using the IPrincipal.IsInRole method.

On occasion, you may need to implement your own IPrincipal class. Reasons for implementing your own IPrincipal class include:

  • You want extended role checking functionality. You might want methods that allow you to check whether a particular user is a member of multiple roles. For example:
  • CustomPrincipal.IsInAllRoles( "Role", "Role2", "Role3" ) 
    CustomPrincipal.IsInAnyRole( "Role1", "Role2", "Role3" )

  • You may want to implement an extra method or property that returns a list of roles in an array. For example:
  • string[] roles = CustomPrincipal.Roles;

  • You want your application to enforce role hierarchy logic. For example, a Senior Manager may be considered higher up in the hierarchy than a Manager. This could be tested using methods like the ones shown below.
  • CustomPrincipal.IsInHigherRole("Manager");
    CustomPrincipal.IsInLowerRole("Manager");

  • You may want to implement lazy initialization of the role lists. For example, you could dynamically load the role list only when a role check is requested.
  • You may want to implement the IIdentity interface to have the user identified by an X509ClientCertificate. For example:
  • CustomIdentity id = CustomPrincipal.Identity; 
    X509ClientCertificate cert = id.ClientCertificate;

More Information

For more information about creating your own IPrincipal class, see "How To: Implement IPrincipal" in the Reference section of this book.

Windows Authentication

Use Windows authentication when the users of your application have Windows accounts that can be authenticated by the server (for example, in intranet scenarios).

If you configure ASP.NET for Windows authentication, IIS performs user authentication by using the configured IIS authentication mechanism. This is shown in Figure 8.4.

Click to view graphic
Click to view graphic

Figure 8.4 ASP.NET Windows authentication uses IIS to authenticate callers

The access token of the authenticated caller (which may be the Anonymous Internet user account if IIS is configured for Anonymous authentication) is made available to the ASP.NET application. Note the following:

  • This allows the ASP.NET FileAuthorizationModule to perform access checks against requested ASP.NET files using the original caller's access token.
  • File authorization does not require impersonation. With impersonation enabled any resource access performed by your application uses the impersonated caller's identity. In this event, ensure that the ACLs attached to resources contain an Access Control Entry (ACE) that grants at least read access to the original caller's identity.

Identifying the Authenticated User

ASP.NET associates a WindowsPrincipal object with the current Web request. This contains the identity of the authenticated Windows user together with a list of roles that the user belongs to. With Windows authentication, the role list consists of the set of Windows groups to which the user belongs.

The following code shows how to obtain the identity of the authenticated Windows user and to perform a simple role test for authorization.

WindowsPrincipal user = User as WindowsPrincipal; 
if (null != user)
{
  string username = user.Identity.Name;
  // Perform a role check
  if ( user.IsInRole(@"DomainName\Manager") )
  {
    // User is authorized to perform manager functionality
  }
}
else
{
  // Throw security exception as we don't have a WindowsPrincipal
}  

Forms Authentication

When you are using Forms authentication, the sequence of events triggered by an unauthenticated user who attempts to access a secured file or resource (where URL authorization denies the user access), is shown in Figure 8.5.

Click to view graphic
Click to view graphic

Figure 8.5 Forms authentication sequence of events

The following describes the sequence of events shown in Figure 8.5:

  1. The user issues a Web request for Default.aspx.
  2. IIS allows the request because Anonymous access is enabled. ASP.NET checks the <authorization> elements and finds a <deny users=?" /> element.

  3. The user is redirected to the login page (Login.aspx) as specified by the loginUrl attribute of the <forms> element.
  4. The user supplies credentials and submits the login form.
  5. The credentials are validated against a store (SQL Server or Active Directory) and roles are optionally retrieved. You must retrieve a role list if you want to use role-based authorization.
  6. A cookie is created with a FormsAuthenticationTicket and sent back to the client. Roles are optionally stored in the ticket. By storing the role list in the ticket, you avoid having to access the database to re-retrieve the list for each successive Web request from the same user.
  7. The user is redirected with client-side redirection to the originally requested page (Default.aspx).
  8. In the Application_AuthenticateRequest event handler (in Global.asax), the ticket is used to create an IPrincipal object and it is stored in HttpContext.User.
  9. ASP.NET checks the <authorization> elements and finds a <deny users=?" /> element. However, this time the user is authenticated.

    ASP.NET checks the <authorization> elements to ensure the user is in the <allow> element.

    The user is granted access to Default.aspx.

Development Steps for Forms Authentication

The following list highlights the key steps that you must perform to implement Forms authentication:

  1. Configure IIS for anonymous access.
  2. Configure ASP.NET for Forms authentication.
  3. Create a logon Web form and validate the supplied credentials.
  4. Retrieve a role list from the custom data store.
  5. Create a Forms authentication ticket (store roles in the ticket).
  6. Create an IPrincipal object.
  7. Put the IPrincipal object into the current HTTP context.
  8. Authorize the user based on user name/role membership.

Configure IIS for Anonymous Access

Your application's virtual directory must be configured in IIS for anonymous access.

To configure IIS for anonymous access

  1. Start the Internet Information Services administration tool.
  2. Select your application's virtual directory, right-click, and then click Properties.
  3. Click Directory Security.
  4. In the Anonymous access and authentication control group, click Edit.
  5. Select Anonymous access.

Configure ASP.NET for Forms Authentication

A sample configuration is shown below.

<authentication mode="Forms">
  <forms name="MyAppFormsAuth"
       loginUrl="login.aspx"
       protection="Encryption"
       timeout="20"
       path="/" >
  </forms>
</authentication>

Create a Logon Web Form and Validate the Supplied Credentials

Validate credentials against a SQL Server database, or Active Directory.

More Information

  • See "How To: Use Forms Authentication with SQL Server 2000" in the Reference section of this book.
  • See "How To: Use Forms Authentication with Active Directory" in the Reference section of this book.

Retrieve a Role List from the Custom Data Store

Obtain roles from a table within a SQL Server database, or groups/distribution lists configured within Active Directory. Refer to the preceding resources for details.

Create a Forms Authentication Ticket

Store the retrieved roles in the ticket. This is illustrated in the following code.

// This event handler executes when the user clicks the Logon button
// having supplied a set of credentials
private void Logon_Click(object sender, System.EventArgs e)
{
  // Validate credentials against either a SQL Server database
  // or Active Directory
  bool isAuthenticated = IsAuthenticated( txtUserName.Text,
                                          txtPassword.Text );
  if (isAuthenticated == true )
  {
    // Retrieve the set of roles for this user from the SQL Server
    // database or Active Directory. The roles are returned as a
    // string that contains pipe separated role names
    // for example "Manager|Employee|Sales|"
    // This makes it easy to store them in the authentication ticket

    string roles = RetrieveRoles( txtUserName.Text, txtPassword.Text );

    // Create the authentication ticket and store the roles in the
    // custom UserData property of the authentication ticket
    FormsAuthenticationTicket authTicket = new
       FormsAuthenticationTicket(
                    1,                          // version
                    txtUserName.Text,           // user name
                    DateTime.Now,               // creation
                    DateTime.Now.AddMinutes(20),// Expiration
                    false,                      // Persistent
                    roles );                    // User data
     // Encrypt the ticket.
     string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
     // Create a cookie and add the encrypted ticket to the
     // cookie as data.
     HttpCookie authCookie =
               new HttpCookie(FormsAuthentication.FormsCookieName,
                              encryptedTicket);

     // Add the cookie to the outgoing cookies collection.
     Response.Cookies.Add(authCookie);
     // Redirect the user to the originally requested page
     Response.Redirect( FormsAuthentication.GetRedirectUrl(
                        txtUserName.Text,
                        false ));
  }
}

Create an IPrincipal Object

Create the IPrincipal object in the Application_AuthenticationRequest event handler in Global.asax. Use the GenericPrincipal class, unless you need extended role-based functionality. In this case create a custom class that implements IPrincipal.

Put the IPrincipal Object into the Current HTTP Context

The creation of a GenericPrincipal object is shown below.

protected void Application_AuthenticateRequest(Object sender, EventArgs e) 
{
  // Extract the forms authentication cookie
  string cookieName = FormsAuthentication.FormsCookieName;
  HttpCookie authCookie = Context.Request.Cookies[cookieName];
  if(null == authCookie)
  {
    // There is no authentication cookie.
    return;
  }
  FormsAuthenticationTicket authTicket = null;
  try
  {
    authTicket = FormsAuthentication.Decrypt(authCookie.Value);
  }
  catch(Exception ex)
  {
    // Log exception details (omitted for simplicity)
    return;
  }
  if (null == authTicket)
  {
    // Cookie failed to decrypt.
    return;
  }
  // When the ticket was created, the UserData property was assigned a
  // pipe delimited string of role names.
  string[] roles = authTicket.UserData.Split(new char[]{'|'});

  // Create an Identity object
  FormsIdentity id = new FormsIdentity( authTicket );
  // This principal will flow throughout the request.
  GenericPrincipal principal = new GenericPrincipal(id, roles);
  // Attach the new principal object to the current HttpContext object
  Context.User = principal;
}

Authorize the User Based on User Name or Role Membership

Use declarative principal permission demands to restrict access to methods. Use imperative principal permission demands and/or explicit role checks (IPrincipal.IsInRole) to perform fine-grained authorization within methods.

Forms Implementation Guidelines

  • Use SSL when capturing credentials using an HTML form.
  • In addition to using SSL for the login page, you should also use SSL for other pages, whenever the credentials or the authentication cookie is sent across the network. This is to mitigate the threat associated with cookie replay attacks.

  • Authenticate users against a custom data store. Use SQL Server or Active Directory.
  • Retrieve a role list from the custom data store and store a delimited list of roles within the UserData property of the FormsAuthenticationTicket class. This improves performance by eliminating repeated access to the data store for each Web request and also saves you from storing the user's credentials in the authentication cookie.
  • If the list of roles is extensive and there is a danger of exceeding the cookie size limit, store the role details in the ASP.NET cache object or database and retrieve them on each subsequent request.
  • For each request after initial authentication:
    • Retrieve the roles from the ticket in the Application_AuthenticateRequest event handler.
    • Create an IPrincipal object and store it in the HTTP context (HttpContext.User). The .NET Framework also associates it with the current .NET thread (Thread.CurrentPrincipal).
    • Use the GenericPrincipal class unless you have a specific need to create a custom IPrincipal implementation; for example, to support enhanced role-based operations.

  • Use two cookies; one for personalization and one for secure authentication and authorization. Make the personalization cookie persistent (make sure it does not contain information that would permit a request to perform a restricted operation; for example, placing an order within a secure part of a site).
  • Use a separate cookie name (using the Forms attribute of the <forms> element) and path for each Web application. This will ensure that users who are authenticated against one application are not treated as authenticated when using a second application hosted by the same Web server.
  • Ensure cookies are enabled within client browsers. For a Forms authentication approach that does not require cookies, see "Cookieless Forms Authentication" later in this chapter.

More Information

  • See "How To: Use Forms Authentication with SQL Server 2000" in the Reference section of this book.
  • See "How To: Use Forms Authentication with Active Directory" in the Reference section of this book.
  • See "How To: Use Forms Authentication with GenericPrincipal Objects" in the Reference section of this book.

Hosting Multiple Applications Using Forms Authentication

If you are hosting multiple Web applications that use Forms authentication on the same Web server, it is possible for a user who is authenticated in one application to make a request to another application without being redirected to that application's logon page. The URL authorization rules within the second application may deny access to the user, without providing the opportunity to supply logon credentials using the logon form.

This only happens if the name and path attributes on the <forms> element are the same across multiple applications and each application uses a common <machineKey> element in Web.config.

More Information

For more information about this issue, and for resolution techniques, see the following Knowledge Base articles:

  • Q313116, "PRB: Forms Authentication Requests Are Not Directed to loginUrl Page"
  • Q310415, "PRB: Mobile Forms Authentication and Different Web Applications"

Cookieless Forms Authentication

If you need a cookieless Forms authentication solution, consider using the approach used by the Microsoft Mobile Internet Toolkit. Mobile Forms Authentication builds upon Forms Authentication but uses the query string to convey the authentication ticket instead of a cookie.

More Information

For more information about Mobile Forms Authentication, see article Q311568, "INFO: How To Use Mobile Forms Authentication with Microsoft Mobile Internet Toolkit," in the Microsoft Knowledge Base.


Next



Last Updated: January 6, 2003
Top of Page