Chapter 3. Authentication and Authorization Design

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?

  • What are the implications and design considerations for heterogeneous and homogenous platforms?

  • 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.

Note

An application level role-based authorization approach still requires the use of resource-based authorization to secure system level resource, for example configuration files, registry keys and so on.

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 Authorization

With a role (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 Authorization

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 on the next page 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.

The Trusted Subsystem model

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.

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.

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

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.

The impersonation/delegation model

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 Act as part of the operating system privilege). (This restriction applies to Windows 2000 and will not apply to Windows .NET Server).

  • 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, 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 (AUTHORITYANONYMOUS 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 "Appendix " in the References section of this book.

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.

Role-Based Authorization

Most .NET Web applications will use a role-based approach to 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 revolve around IPrincipal objects that contain the list of roles that an authenticated identity belongs to. .NET roles 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 using PrincipalPermission demands or programmatically in code, using imperative PrincipalPermission demands or the IPrincipal.IsInRole method.

.NET Roles with Windows Authentication

If your application uses Windows authentication, ASP.NET automatically constructs a WindowsPrincipal that is attached to the context of the current Web request (using HttpContext.User). After the authentication process is complete and ASP.NET has attached to object to the current request, it is used for all subsequent .NET role-based authorization.

The Windows group membership of the authenticated caller is used to determine the set of roles. With Windows authentication, .NET roles are the same as Windows groups.

.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

  • For more information about .NET role-based authorization, see Chapter 8.

  • For more information about creating GenericPrincipal objects, see "How to use Forms authentication with GenericPrincipal objects" in the Reference section of this book.

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.

.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

Class, Interface and Method Level Granularity

Yes

Yes

Extensible

No

Yes (using custom IPrincipal implementation)

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.

    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.

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.

  • 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.

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();

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
      . . .
    }

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();

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();

Choosing an Authentication Mechanism

This section presents guidance which 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.

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

  • 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 and accounts configured for delegation. For more information, see "Appendix " in the Reference section of this book.

    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.

Choosing an authentication mechanism for Internet applications

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.

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. Relatively little custom code is required in comparison to classic ASP.

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

  • For more information about Web service authentication approaches, see Chapter 10.

  • For more information about using Forms Authentication with SQL Server, see "Appendix " in the Reference section of this book.

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.

Choosing an authentication mechanism for intranet and extranet applications

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) for fine-grained authorization decisions.

  • Consider implementing a custom IPrincipal object to gain additional role-checking semantics.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.14.132