Building Secure ASP.NET Applications: Authentication, Authorization, and Secure Communication

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

 

patterns & practices Developer Center

Authentication and Authorization

J.D. Meier, Alex Mackman, Michael Dunner, and Srinath Vasireddy
Microsoft Corporation

Published: November 2002

Last Revised: January 2006

See the "patterns & practices Security Guidance for Applications Index" for links to additional security resources.

See the Landing Page for the starting point and a complete overview of Building Secure ASP.NET Applications.

Summary: This chapter provides guidance to help you develop an appropriate authentication and authorization strategy for your particular application scenario. It will help you choose the most appropriate authentication and authorization technique and apply them at the correct places in your application. (22 printed pages)

Contents

Designing an Authentication and Authorization Strategy
Authorization Approaches
Flowing Identity
Role-Based Authorization
Choosing an Authentication Mechanism
Summary

Designing an authentication and authorization strategy for distributed Web applications is a challenging task. The good news is that proper authentication and authorization design during the early phases of your application development helps to mitigate many top security risks.

This chapter will help you design an appropriate authorization strategy for your application and will also help answer the following key questions:

  • Where should I perform authorization and what mechanisms should I use?
  • What authentication mechanism should I use?
  • Should I use Active Directory® directory service for authentication or should I validate credentials against a custom data store?
  • How should I represent users who do not use the Microsoft® Windows® operating system within my application?
  • How should I flow user identity throughout the tiers of my application? When should I use operating system level impersonation/delegation?

When you consider authorization, you must also consider authentication. The two processes go hand in hand for two reasons:

  • First, any meaningful authorization policy requires authenticated users.

  • Second, the way in which you authenticate users (and specifically the way in which the authenticated user identity is represented within your application) determines the available gatekeepers at your disposal.

    Some gatekeepers such as ASP.NET file authorization, Enterprise Services (COM+) roles and Windows ACLs, require an authenticated Windows identity (in the form of a WindowsIdentity object that encapsulates a Windows access token, which defines the caller's security context). Other gatekeepers, such as ASP.NET URL authorization and .NET roles, do not. They simply require an authenticated identity; one that is not necessarily represented by a Windows access token.

Designing an Authentication and Authorization Strategy

The following steps identify a process that will help you develop an authentication and authorization strategy for your application:

  1. Identify resources
  2. Choose an authorization strategy
  3. Choose the identities used for resource access
  4. Consider identity flow
  5. Choose an authentication approach
  6. Decide how to flow identity

Identify Resources

Identify resources that your application needs to expose to clients. Typical resources include:

  • Web Server resources such as Web pages, Web services, static resources (HTML pages and images).
  • Database resources such as per-user data or application-wide data.
  • Network resources such as remote file system resources and data from directory stores such as Active Directory.

You must also identify the system resources that your application needs to access. This is in contrast to resources that are exposed to clients. Examples of system resources include the registry, event logs and configuration files.

Choose an Authorization Strategy

The two basic authorization strategies are:

  • Role based. Access to operations (typically methods) is secured based on the role membership of the caller. Roles are used to partition your application's user base into sets of users that share the same security privileges within the application; for example, Senior Managers, Managers and Employees .Users are mapped to roles and if the user is authorized to perform the requested operation, the application uses fixed identities with which to access resources. These identities are trusted by the respective resource managers (for example, databases, the file system and so on).
  • Resource based. Individual resources are secured using Windows ACLs. The application impersonates the caller prior to accessing resources, which allows the operating system to perform standard access checks. All resource access is performed using the original caller's security context. This impersonation approach severely impacts application scalability, because it means that connection pooling cannot be used effectively within the application's middle tier.

In the vast majority of .NET Web applications where scalability is essential, a role-based approach to authorization represents the best choice. For certain smaller scale intranet applications that serve per-user content from resources (such as files) that can be secured with Windows ACLs against individual users, a resource-based approach may be appropriate.

The recommended and common pattern for role-based authorization is:

  • Authenticate users within your front-end Web application.

  • Map users to roles.

  • Authorize access to operations (not directly to resources) based on role membership.

  • Access the necessary back-end resources (required to support the requested and authorized operations) by using fixed service identities. The back-end resource managers (for example, databases) trust the application to authorize callers and are willing to grant permissions to the trusted service identity or identities.

    For example, a database administrator may grant access permissions exclusively to a specific HR application (but not to individual users).

More information

  • For more information about the two contrasting authorization approaches, see Authorization Approaches later in this chapter.
  • For more information about role-based authorization and the various types of roles that can be used, see Role-Based Authorization later in this chapter.

Choose the Identities Used for Resource Access

Answer the question, "who will access resources?"

Choose the identity or identities that should be used to access resources across the layers of your application. This includes resources accessed from Web-based applications, and optionally Web services, Enterprise Services and .NET Remoting components. In all cases, the identity used for resource access can be:

  • Original caller's identity. This assumes an impersonation/delegation model in which the original caller identity can be obtained and then flowed through each layer of your system. The delegation factor is a key criteria used to determine your authentication mechanism.

  • Process identity. This is the default case (without specific impersonation). Local resource access and downstream calls are made using the current process identity. The feasibility of this approach depends on the boundary being crossed, because the process identity must be recognized by the target system.

    This implies that calls are made in one of the following ways:

    • Within the same Windows security domain
    • Across Windows security domains (using trust and domain accounts, or duplicated user names and passwords where no trust relationship exists)
  • Service account. This approach uses a (fixed) service account. For example:

    • For database access this might be a fixed SQL user name and password presented by the component connecting to the database.
    • When a fixed Windows identity is required, use an Enterprise Services server application.
  • Custom identity. When you don't have Windows accounts to work with, you can construct your own identities (using IPrincipal and IIdentity implementations) that can contain details that relate to your own specific security context. For example, these could include role lists, unique identifiers, or any other type of custom information.

    By implementing your custom identity with IPrincipal and IIdentity types and placing them in the current Web context (using HttpContext.User), you immediately benefit from built-in gatekeepers such as .NET roles and PrincipalPermission demands.

Consider Identity Flow

To support per-user authorization, auditing, and per-user data retrieval you may need to flow the original caller's identity through various application tiers and across multiple computer boundaries. For example, if a back-end resource manager needs to perform per-caller authorization, the caller's identity must be passed to that resource manager.

Based on resource manager authorization requirements and the auditing requirements of your system, identify which identities need to be passed through your application.

Choose an Authentication Approach

Two key factors that influence the choice of authentication approach are first and foremost the nature of your application's user base (what types of browsers are they using and do they have Windows accounts), and secondly your application's impersonation/delegation and auditing requirements.

More information

For more detailed considerations that help you to choose an authentication mechanism for your application, see Choosing an Authentication Mechanism later in this chapter.

Decide How to Flow Identity

You can flow identity (to provide security context) at the application level or you can flow identity and security context at the operating system level.

To flow identity at the application level, use method and stored procedure parameters. Application identity flow supports:

  • Per-user data retrieval using trusted query parameters

        SELECT x,y FROM SomeTable WHERE username="bob"
    
  • Custom auditing within any application tier

Operating system identity flow supports:

  • Platform level auditing (for example, Windows auditing and SQL Server auditing)
  • Per-user authorization based on Windows identities

To flow identity at the operating system level, you can use the impersonation/delegation model. In some circumstances you can use Kerberos delegation, while in others (where perhaps the environment does not support Kerberos) you may need to use other approaches such as, using Basic authentication. With Basic authentication, the user's credentials are available to the server application and can be used to access downstream network resources.

More information

For more information about flowing identity and how to obtain an impersonation token with network credentials (that is, supports delegation), see Flowing Identity later in this chapter.

Authorization Approaches

There are two basic approaches to authorization:

  • Role based. Users are partitioned into application-defined, logical roles. Members of a particular role share the same privileges within the application. Access to operations (typically expressed by method calls) is authorized based on the role-membership of the caller.

    Resources are accessed using fixed identities (such as a Web application's or Web service's process identity). The resource managers trust the application to correctly authorize users and they authorize the trusted identity.

  • Resource based. Individual resources are secured using Windows ACLs. The ACL determines which users are allowed to access the resource and also the types of operation that each user is allowed to perform (read, write, delete and so on).

    Resources are accessed using the original caller's identity (using impersonation).

Role Based

With a role-based (or operations-based) approach to security, access to operations (not back-end resources) is authorized based on the role membership of the caller. Roles (analyzed and defined at application design time) are used as logical containers that group together users who share the same security privileges (or capabilities) within the application. Users are mapped to roles within the application and role membership is used to control access to specific operations (methods) exposed by the application.

Where within your application this role mapping occurs is a key design criterion; for example:

  • On one extreme, role mapping might be performed within a back-end resource manager such as a database. This requires the original caller's security context to flow through your application's tiers to the back-end database.
  • On the other extreme, role mapping might be performed within your front-end Web application. With this approach, downstream resource managers are accessed using fixed identities that each resource manager authorizes and is willing to trust.
  • A third option is to perform role mapping somewhere in between the front-end and back-end tiers; for example, within a middle tier Enterprise Services application.

In multi-tiered Web applications, the use of trusted identities to access back-end resource managers provides greater opportunities for application scalability (thanks to connection pooling). Also, the use of trusted identities alleviates the need to flow the original caller's security context at the operating system level, something that can be difficult (if not impossible in certain scenarios) to achieve.

Resource Based

The resource-based approach to authorization relies on Windows ACLs and the underlying access control mechanics of the operating system. The application impersonates the caller and leaves it to the operating system in conjunction with specific resource managers (the file system, databases, and so on) to perform access checks.

This approach tends to work best for applications that provide access to resources that can be individually secured with Windows ACLs, such as files. An example would be an FTP application or a simple data driven Web application. The approach starts to break down where the requested resource consists of data that needs to be obtained and consolidated from a number of different sources; for example, multiple databases, database tables, external applications or Web services.

The resource-based approach also relies on the original caller's security context flowing through the application to the back-end resource managers. This can require complex configuration and significantly reduces the ability of a multi-tiered application to scale to large numbers of users, because it prevents the efficient use of pooling (for example, database connection pooling) within the application's middle tier.

Resource Access Models

The two contrasting approaches to authorization can be seen within the two most commonly used resource-access security models used by .NET Web applications (and distributed multi-tier applications in general). These are:

  • The trusted subsystem model
  • The impersonation/delegation model

Each model offers advantages and disadvantages both from a security and scalability perspective. The next sections describe these models.

The Trusted Subsystem Model

With this model, the middle tier service uses a fixed identity to access downstream services and resources. The security context of the original caller does not flow through the service at the operating system level, although the application may choose to flow the original caller's identity at the application level. It may need to do so to support back-end auditing requirements, or to support per-user data access and authorization.

The model name stems from the fact that the downstream service (perhaps a database) trusts the upstream service to authorize callers. Figure 3.1 shows this model. Pay particular attention to the trust boundary. In this example, the database trusts the middle tier to authorize callers and allow only authorized callers to access the database using the trusted identity.

Ff649350.f03sn01(en-us,PandP.10).gif

Figure 3.1. The Trusted Subsystem model

The pattern for resource access in the trusted subsystem model is the following:

  • Authenticate users
  • Map users to roles
  • Authorize based on role membership
  • Access downstream resource manager using a fixed trusted identity

Fixed identities

The fixed identity used to access downstream systems and resource managers is often provided by a preconfigured Windows account, referred to as a service account. With a Microsoft SQL Server™ resource manager, this implies Windows authentication to SQL Server.

Alternatively, some applications use a nominated SQL account (specified by a user name and password in a connection string) to access SQL Server. In this scenario, the database must be configured for SQL authentication.

For more information about the relative merits of Windows and SQL authentication when communicating with SQL Server, see Chapter 12, Data Access Security.

Using multiple trusted identities

Some resource managers may need to be able to perform slightly more fine-grained authorization, based on the role membership of the caller. For example, you may have two groups of users, one who should be authorized to perform read/write operations and the other read-only operations.

Consider the following approach with SQL Server:

  • Create two Windows accounts, one for read operations and one for read/write operations.

    More generally, you have separate accounts to mirror application-specific roles. For example, you might want to use one account for Internet users and another for internal operators and/or administrators.

  • Map each account to a SQL Server user-defined database role, and establish the necessary database permissions for each role.

  • Map users to roles within your application and use role membership to determine which account to impersonate before connecting to the database.

This approach is shown in Figure 3.2.

Ff649350.f03sn02(en-us,PandP.10).gif

Figure 3.2. Using multiple identities to access a database to support more fine-grained authorization

The Impersonation / Delegation Model

With this model, a service or component (usually somewhere within the logical business services layer) impersonates the client's identity (using operating system-level impersonation) before it accesses the next downstream service. If the next service in line is on the same computer, impersonation is sufficient. Delegation is required if the downstream service is located on a remote computer.

As a result of the delegation, the security context used for the downstream resource access is that of the client. This model is typically used for a couple of reasons:

  • It allows the downstream service to perform per-caller authorization using the original caller's identity.
  • It allows the downstream service to use operating system-level auditing features.

As a concrete example of this technique, a middle-tier Enterprise Services component might impersonate the caller prior to accessing a database. The database is accessed using a database connection tied to the security context of the original caller. With this model, the database authenticates each and every caller and makes authorization decisions based on permissions assigned to the individual caller's identity (or the Windows group membership of the caller). The impersonation/delegation model is shown in Figure 3.3.

Ff649350.f03sn03(en-us,PandP.10).gif

Figure 3.3. The impersonation/delegation model

Choosing a Resource Access Model

The trusted subsystem model is used in the vast majority of Internet applications and large-scale intranet applications, primarily for scalability reasons. The impersonation model tends to be used in smaller-scale applications where scalability is not the primary concern and those applications where auditing (for reasons of non-repudiation) is a critical concern.

Advantage of the impersonation / delegation model

The primary advantage of the impersonation / delegation model is auditing (close to the data). Auditing allows administrators to track which users have attempted to access specific resources. Generally auditing is considered most authoritative if the audits are generated at the precise time of resource access and by the same routines that access the resource.

The impersonation / delegation model supports this by maintaining the user's security context for downstream resource access. This allows the back-end system to authoritatively log the user and the requested access.

Disadvantages of the impersonation / delegation model

The disadvantages associated with the impersonation / delegation model include:

  • Technology challenges. Most security service providers don't support delegation, Kerberos is the notable exception.

    Processes that perform impersonation require higher privileges (specifically the Actas part of the operating system privilege). This restriction applies to Windows 2000 and does not apply to Windows Server 2003.

  • Scalability. The impersonation / delegation model means that you cannot effectively use database connection pooling, because database access is performed by using connections that are tied to the individual security contexts of the original callers. This significantly limits the application's ability to scale to large numbers of users.

  • Increased administration effort. ACLs on back-end resources need to be maintained in such a way that each user is granted the appropriate level of access. When the number of back-end resources increases (and the number of users increases), a significant administration effort is required to manage ACLs.

Advantages of the trusted subsystem model

The trusted subsystem model offers the following advantages:

  • Scalability. The trusted subsystem model supports connection pooling, an essential requirement for application scalability. Connection pooling allows multiple clients to reuse available, pooled connections. It works with this model because all back-end resource access uses the security context of the service account, regardless of the caller's identity.
  • Minimizes back-end ACL management. Only the service account accesses back-end resources (for example, databases). ACLs are configured against this single identity.
  • Users can't access data directly. In the trusted-subsystem model, only the middle-tier service account is granted access to the back-end resources. As a result, users cannot directly access back-end data without going through the application (and being subjected to application authorization).

Disadvantages of the trusted subsystem model

The trusted-subsystem model suffers from a couple of drawbacks:

  • Auditing. To perform auditing at the back end, you can explicitly pass (at the application level) the identity of the original caller to the back end, and have the auditing performed there. You have to trust the middle-tier and you do have a potential repudiation risk. Alternatively, you can generate an audit trail in the middle tier and then correlate it with back-end audit trails (for this you must ensure that the server clocks are synchronized).
  • Increased risk from server compromise. In the trusted-subsystem model, the middle-tier service is granted broad access to back-end resources. As a result, a compromised middle-tier service potentially makes it easier for an attacker to gain broad access to back-end resources.

Flowing Identity

Distributed applications can be divided into multiple secure subsystems. For example, a front-end Web application, a middle-tier Web service, a remote component, and a database represent four different security subsystems. Each performs authentication and authorization.

You must identify those subsystems that must flow the caller's identity (and associated security context) to the next downstream subsystem in order to support authorization against the original caller.

Application vs. Operating System Identity Flow

Strategies for flowing identities include using the delegation features of the operating system or passing tickets and/or credentials at the application level. For example:

  • To flow identity at the application level, you typically pass credentials (or tickets) using method arguments or stored procedure parameters.

    Note   GenericPrincipal objects that carry the authenticated caller's identity do not automatically flow across processes. This requires custom code.

    You can pass parameters to stored procedures that allow you to retrieve and process user-specific data. For example:

    SELECT CreditLimit From Table Where UserName="Bob"
    

    This approach is sometimes referred to as a trusted query parameter approach.

  • Operating system identity flow requires an extended form of impersonation called delegation.

Impersonation and Delegation

Under typical circumstances, threads within a server application run using the security context of the server process. The attributes that comprise the process' security context are maintained by the process' logon session and are exposed by the process level Windows access token. All local and remote resource access is performed using the process level security context that is determined by the Windows account used to run the server process.

Impersonation

When a server application is configured for impersonation or uses programmatic impersonation, an impersonation token is attached to the thread used to process a request. The impersonation token represents the security context of the authenticated caller (or anonymous user). Any local resource access is performed using the thread impersonation token that results in the use of the caller's security context.

Delegation

If the server application thread attempts to access a remote resource, delegation is required. Specifically, the impersonated caller's token must have network credentials. If it doesn't, all remote resource access is performed as the anonymous user (AUTHORITY\ANONYMOUS LOGON).

There are a number of factors that determine whether or not a security context can be delegated. Table 3.1 shows the various IIS authentication types and for each one indicates whether or not the security context of the authenticated caller can be delegated.

Table 3.1. IIS Authentication types

Authentication Type Can Delegate Notes
Anonymous Depends If the anonymous account (by default IUSR_MACHINE) is configured in IIS as a local account, it cannot be delegated unless the local (Web server) and remote computer have identical local accounts (with matching usernames and passwords).
If the anonymous account is a domain account it can be delegated.
Basic Yes If Basic authentication is used with local accounts, it can be delegated if the local accounts on the local and remote computers are identical. Domain accounts can also be delegated.
Digest No  
Integrated Windows Depends Integrated Windows authentication either results in NTLM or Kerberos (depending upon the version of operating system on client and server computer).
NTLM does not support delegation.
Kerberos supports delegation with a suitably configured environment.
For more information, see How To: Implement Kerberos Delegation for Windows 2000 in the References section of this guide.
Client Certificates Depends Can be delegated if used with IIS certificate mapping and the certificate is mapped to a local account that is duplicated on the remote computer or is mapped to a domain account.
This works because the credentials for the mapped account are stored on the local server and are used to create an Interactive logon session (which has network credentials).
Active Directory certificate mapping does not support delegation.

Important   Kerberos delegation under Windows 2000 is unconstrained. In other words, a user may be able to make multiple network hops across multiple remote computers. To close this potential security risk, you should limit the scope of the domain account's reach by removing the account from the Domain Users group and allow the account to be used only to log on to specific computers.

Note   Windows Server 2003 introduces constrained delegation, which can be used to restrict the delegation to a particular service on a particular server. For more information see "How To: Use Protocol Transition and Constrained Delegation in ASP.NET 2.0."

Role-Based Authorization

Most .NET Web applications will use a role-based approach for authorization. You need to consider the various role types and choose the one(s) most appropriate for your application scenario. You have the following options:

  • .NET roles
  • Enterprise Services (COM+) roles
  • SQL Server User Defined Database roles
  • SQL Server Application roles

.NET Roles

.NET roles are extremely flexible and can be used within Web applications, Web services, or remote components hosted within ASP.NET (and accessed using the HttpChannel).

You can perform authorization using .NET roles either declaratively by using PrincipalPermission demands, or programmatically in code by using imperative PrincipalPermission demands or the IPrincipal.IsInRole method.

Note   Additionally, if you are using the Role Manager feature of ASP.NET 2.0, you can use Role Manager APIs for role checks. For more information see, "How To: Use Role Manager in ASP.NET 2.0."

.NET roles with Windows authentication

If your application uses a non-Windows authentication mechanism such as Forms or Passport, you must write code to create a GenericPrincipal object (or a custom IPrincipal object) and populate it with a set of roles obtained from a custom authentication data store such as a SQL Server database.

Note   When using the Role Manager feature of ASP.NET 2.0, you do not need to populate the GenericPrincipal class with the role set. The Role Manager feature automatically obtains the role information for the user. For more information see, "How To: Use Role Manager in ASP.NET 2.0."

.NET roles with non-Windows authentication

If your application uses a non-Windows authentication mechanism such as Forms or Passport, you must write code to create a GenericPrincipal object (or a custom IPrincipal object) and populate it with a set of roles obtained from a custom authentication data store such as a SQL Server database.

Custom IPrincipal objects

The .NET Role-based security mechanism is extensible. You can develop your own classes that implement IPrincipal and IIdentity and provide your own extended role-based authorization functionality.

As long as the custom IPrincipal object (containing roles obtained from a custom data store) is attached to the current request context (using HttpContext.User), basic role-checking functionality is ensured.

By implementing the IPrincipal interface, you ensure that both the declarative and imperative forms of PrincipalPermission demands work with your custom identity. Furthermore, you can implement extended role semantics; for example, by providing an additional method such as IsInMultipleRoles( string [] roles ) which would allow you to test and assert for membership of multiple roles.

More information

Enterprise Services (COM+) Roles

Using Enterprise Services (COM+) roles pushes access checks to the middle tier and allows you to use database connection pooling when connecting to back-end databases. However, for meaningful Enterprise Services (COM+) role-based authorization, your front-end Web application must impersonate and flow the original caller's identity (using a Windows access token) to the Enterprise Services application. To achieve this, the following entries must be placed in the Web application's Web.config file.

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

If it is sufficient to use declarative checks at the method level (to determine which users can call which methods), you can deploy your application and update role membership using the Component Services administration tool.

If you require programmatic checks in method code, you lose some of the administrative and deployment advantages of Enterprise Services (COM+) roles, because role logic is hard-coded.

SQL Server User Defined Database Roles

With this approach, you create roles in the database, assign permissions based on the roles and map Windows group and user accounts to the roles. This approach requires you to flow the caller's identity to the back end (if you are using the preferred Windows authentication to SQL Server).

SQL Server Application Roles

With this approach, permissions are granted to the roles within the database, but SQL Server application roles contain no user or group accounts. As a result, you lose the granularity of the original caller.

With application roles, you are authorizing access to a specific application (as opposed to a set of users). The application activates the role using a built-in stored procedure that accepts a role name and password. One of the main disadvantages of this approach is that it requires the application to securely manage credentials (the role name and associated password).

More information

For more information about SQL Server user defined database roles and application roles, see Chapter 12, Data Access Security.

.NET Roles versus Enterprise Services (COM+) Roles

The following table presents a comparison of the features of .NET roles and Enterprise Services (COM+) roles.

Table 3.2. Comparing Enterprise Services roles with .NET roles

Feature Enterprise Services Roles .NET Roles
Administration Component Services Administration Tool Custom
Data Store COM+ Catalog Custom data store (for example, SQL Server or Active Directory)
Declarative Yes
[SecurityRole("Manager")]
Yes
[PrincipalPermission(
SecurityAction.Demand,
Role="Manager")]
Imperative Yes
ContextUtil.IsCallerInRole()
Yes
(IPrincipal.IsInRole, and additionally Roles.IsUserInRole if you are running ASP.Net 2.0)
Class, Interface and Method Level Granularity Yes Yes
Extensible No Yes
(using custom IPrincipal implementation, and additionally creating a custom role provider if you are running ASP.NET 2.0)
Available to all .NET components Only for components that
derive from ServicedComponent base class
Yes
Role Membership Roles contain Windows group or user accounts When using WindowsPrincipals,
roles ARE Windows groups–no extra level of abstraction
Requires explicit Interface implementation Yes
To obtain method level authorization, an interface must be explicitly defined and implemented
No

Using .NET Roles

You can secure the following items with .NET roles:

  • Files
  • Folders
  • Web pages (.aspx files)
  • Web services (.asmx files)
  • Objects
  • Methods and properties
  • Code blocks within methods

The fact that you can use .NET roles to protect operations (performed by methods and properties) and specific code blocks means that you can protect access to local and remote resources accessed by your application.

Note   The first four items in the preceding list (Files, folders, Web pages, and Web services) are protected using the UrlAuthorizationModule, which can use the role membership of the caller (and the caller's identity) to make authorization decisions.

If you use Windows authentication, much of the work required to use .NET roles is done for you. ASP.NET constructs a WindowsPrincipal object and the Windows group membership of the user determines the associated role set.

To use .NET roles with a non-Windows authentication mechanism, you must write code to:

  • Capture the user's credentials.

  • Validate the user's credentials against a custom data store such as a SQL Server database.

  • Retrieve a role list, construct a GenericPrincipal object and associate it with the current Web request.

    Note   When using the Role Manager feature of ASP.NET 2.0, you do not need to populate the GenericPrincipal class with the role set. The Role Manager feature automatically obtains the role information for the user. For more information see, "How To: Use Role Manager in ASP.NET 2.0."

    The GenericPrincipal object represents the authenticated user and is used for subsequent .NET role checks, such as declarative PrincipalPermission demands and programmatic IPrincipal.IsInRole checks.

More information

For more information about the process involved in creating a GenericPrincipal object for Forms authentication, see Chapter 8, ASP.NET Security.

Checking role membership

The following types of .NET role checks are available:

Important   .NET role checking relies upon an IPrincipal object (representing the authenticated user) being associated with the current request. For ASP.NET Web applications, the IPrincipal object must be attached to HttpContext.User. For Windows Forms applications, the IPrincipal object must be attached to Thread.CurrentPrincipal.

  • Manual role checks. For fine-grained authorization, you can call the IPrincipal.IsInRole method to authorize access to specific code blocks based on the role membership of the caller. Both AND and OR logic can be used when checking role membership. Additionally, when using the Role Manager feature of ASP.Net 2.0, you can use Role APIs such as Role.IsUserInRole.
  • Declarative role checks (gates to your methods). You can annotate methods with the PrincipalPermissionAttribute class (which can be shortened to PrincipalPermission), to declaratively demand role membership. These support OR logic only. For example you can demand that a caller is in at least one specific role (for example, the caller must be a teller or a manager). You cannot specify that a caller must be a manager and a teller using declarative checks.
  • Imperative role checks (checks within your methods). You can call PrincipalPermission.Demand within code to perform fine-grained authorization logic. Logical AND and OR operations are supported.

Role-checking examples

The following code fragments show some example role checks using programmatic, declarative, and imperative techniques.

  1. Authorizing Bob to perform an operation:

    Note   Although you can authorize individual users, you should generally authorize based on role membership, which allows you to authorize sets of users who share the same privileges within your application.

    • Direct user name check

          GenericIdentity userIdentity = new GenericIdentity("Bob");
          if (userIdentity.Name=="Bob")
          {
          }
      
    • Declarative check

          [PrincipalPermissionAttribute(SecurityAction.Demand, 
            User="Bob")]
          public void DoPrivilegedMethod()
          {
          }
      
    • Imperative check

          PrincipalPermission permCheckUser = new 
            PrincipalPermission(
                                                         "Bob",
                                                           null);
          permCheckUser.Demand();
      
  2. Authorizing tellers to perform an operation:

    • Direct role name check

          GenericIdentity userIdentity = new GenericIdentity("Bob");
          // Role names would be retrieved from a custom data store
          string[] roles = new String[]{"Manager", "Teller"};
          GenericPrincipal userPrincipal = new 
            GenericPrincipal(userIdentity, 
                                                             roles);
          if (userPrincipal.IsInRole("Teller"))
          {
          }
      
    • Declarative check

          [PrincipalPermissionAttribute(SecurityAction.Demand, 
      Role="Teller")]
          void SomeTellerOnlyMethod()
          {
          }
      
    • Imperative check

          public SomeMethod()
          {
            PrincipalPermission permCheck = new PrincipalPermission(
                                                   null,"Teller");
            permCheck.Demand();
            // Only Tellers can execute the following code
            // Non members of the Teller role result in a security 
              exception
            . . .
          }
      
  3. Authorize managers OR tellers to perform operation:

    • Direct role name check

          if (Thread.CurrentPrincipal.IsInRole("Teller") ||
              Thread.CurrentPrincipal.IsInRole("Manager"))
          {
            // Perform privileged operations
          }
      
    • Declarative check

          [PrincipalPermissionAttribute(SecurityAction.Demand, 
            Role="Teller"),
           PrincipalPermissionAttribute(SecurityAction.Demand, 
             Role="Manager")]
          public void DoPrivilegedMethod()
          {
          ...
          }
      
    • Imperative check

          PrincipalPermission permCheckTellers = new 
            PrincipalPermission( 
                                                   null,"Teller");
          PrincipalPermission permCheckManagers = new 
            PrincipalPermission(
                                                  null,"Manager");
         (permCheckTellers.Union(permCheckManagers)).Demand();
      
  4. Authorize only those people who are managers AND tellers to perform operation:

    • Direct role name check

          if (Thread.CurrentPrincipal.IsInRole("Teller") &&
              Thread.CurrentPrincipal.IsInRole("Manager"))
          {
            // Perform privileged operation
          }
      
    • Declarative check

      It is not possible to perform AND checks with .NET roles declaratively. Stacking PrincipalPermission demands together results in a logical OR.

    • Imperative check

          PrincipalPermission permCheckTellers = new 
            PrincipalPermission(
                                                  null,"Teller");
          permCheckTellers.Demand();
          PrincipalPermission permCheckManagers = new 
            PrincipalPermission(
                                                null, "Manager");
          permCheckManagers.Demand();
      

Note   If you are running ASP.NET 2.0, you can use the Role Manager API to check whether the currently authenticated user is a member of a particular role. For an example of how Role Manager is used in ASP.NET 2.0, see "How To: Use Role Manager in ASP.NET 2.0."

Choosing an Authentication Mechanism

This section presents guidance that is designed to help you choose an appropriate authentication mechanism for common application scenarios. You should start by considering the following issues:

  • Identities. A Windows authentication mechanism is appropriate only if your application's users have Windows accounts that can be authenticated by a trusted authority accessible by your application's Web server.

  • Credential management. One of the key advantages of Windows authentication is that it enables you to let the operating system take care of credential management. With non-Windows approaches, such as Forms authentication, you must carefully consider where and how you store user credentials. The two most common approaches are to use:

    • SQL Server databases
    • User objects within Active Directory

    For more information about the security considerations of using SQL Server as a credential store, see Chapter 12, Data Access Security.

    For more information about using Forms authentication against custom data stores (including Active Directory), see Chapter 8, ASP.NET Security.

  • Identity flow. Do you need to implement an impersonation/delegation model and flow the original caller's security context at the operating system level across tiers? For example, to support auditing or per-user (granular) authorization. If so, you need to be able to impersonate the caller and delegate their security context to the next downstream subsystem, as described in the "Delegation" section earlier in this chapter.

  • Browser type. Do your users all have Internet Explorer or do you need to support a user base with mixed browser types? Table 3.3 illustrates which authentication mechanisms require Internet Explorer browsers, and which support a variety of common browser types.

    Table 3.3. Authentication browser requirements

    Authentication Type Requires Internet Explorer Notes
    Forms No  
    Passport No  
    Integrated Windows (Kerberos or NTLM) Yes Kerberos also requires Windows 2000 or later operating systems on the client and server computers. For more information, see How To: Implement Kerberos Delegation for Windows 2000 in the Reference section of this guide.
    Basic No Basic authentication is part of the HTTP 1.1 protocol that is supported by virtually all browsers
    Digest Yes  
    Certificate No Clients require X.509 certificates

Internet Scenarios

  • The basic assumptions for Internet scenarios are:
    • Users do not have Windows accounts in the server's domain or in a trusted domain accessible by the server.
    • Users do not have client certificates.

Figure 3.4 shows a decision tree for choosing an authentication mechanism for Internet scenarios.

Ff649350.f03sn04(en-us,PandP.10).gif

Figure 3.4. Choosing an authentication mechanism for Internet applications

For more information about Web service security and the WS-Security specification, part of the Global XML Architecture (GXA) initiative, see Chapter 10, Web Services Security.

Forms / Passport comparison

This section summarizes the relative merits of Forms and Passport authentication.

Advantages of Forms authentication

  • Supports authentication against a custom data store; typically a SQL Server database or Active Directory.
  • Supports role-based authorization with role lookup from a data store.
  • Smooth integration with Web user interface.
  • ASP.NET provides much of the infrastructure.

Advantages of Passport authentication

  • Passport is a centralized solution.
  • It removes credential management issues from the application.
  • It can be used with role-based authorization schemes.
  • It is very secure as it is built on cryptography technologies.

More information

Intranet / Extranet Scenarios

Figure 3.5 shows a decision tree that can be used to help choose an authentication mechanism for intranet and extranet application scenarios.

Ff649350.f03sn05(en-us,PandP.10).gif

Figure 3.5. Choosing an authentication mechanism for intranet and extranet applications

Authentication Mechanism Comparison

The following table presents a comparison of the available authentication mechanisms.

Table 3.4: Available authentication methods

  Basic Digest NTLM Kerberos Certs Forms Passport
Users need Windows accounts in server's domain Yes Yes Yes Yes No No No
Supports delegation* Yes No No Yes Can do Yes Yes
Requires Win2K clients and servers No Yes No Yes No No No
Credentials passed as clear text (requires SSL) Yes No No No No Yes No
Supports non-IE browsers Yes No No No Yes Yes Yes

* Refer to the "Delegation" topic in the "Flowing Identity" section earlier in this chapter for details.

Summary

  • Designing distributed application authentication and authorization approaches is a challenging task. Proper authentication and authorization design during the early design phases of your application development helps mitigate many of the top security risks. The following summarizes the information in this chapter:
    • Use the trusted subsystem resource access model to gain the benefits of database connection pooling.
    • If your application does not use Windows authentication, use .NET role checking to provide authorization. Validate credentials against a custom data store, retrieve a role list and create a GenericPrincipal object. Associate it with the current Web request (HttpContext.User).
    • If your application uses Windows authentication and doesn't use Enterprise Services, use .NET roles. Remember that for Windows authentication, .NET roles are Windows groups.
    • If your application uses Windows authentication and Enterprise Services, consider using Enterprise Services (COM+) roles.
    • For meaningful role-based authorization using Enterprise Services (COM+) roles, the original caller's identity must flow to the Enterprise Services application. If the Enterprise Services application is called from an ASP.NET Web application, this means that the Web application must use Windows authentication and be configured for impersonation.
    • Annotate methods with the PrincipalPermission attribute to declaratively demand role membership. The method is not called if the caller is not in the specified role and a security exception is generated.
    • Call PrincipalPermission.Demand within method code (or use IPrincipal.IsInRole, if you are running ASP.NET 2.0 with the Role Manager feature, use Role API such as Roles.IsUserInRole for fine-grained authorization decisions.
    • Consider implementing a custom IPrincipal object to gain additional role-checking semantics.

patterns & practices Developer Center

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

© Microsoft Corporation. All rights reserved.