Enterprise Authorization Strategy
Curt Devlin, Solution Architect
Developer & Platform Evangelism
Active Directory Application Mode (ADAM)
Microsoft .NET Framework
Windows Communication Foundation (WCF)
Summary: This article provides prescriptive architectural guidance for an enterprise authorization strategy. It makes the case for developing an enterprise authorization gateway. Discussion touches on some of the enterprise-level requirements and challenges that motivate this approach. (24 printed pages)
This article provides prescriptive architectural guidance for an enterprise authorization strategy. It makes the case for developing an enterprise authorization gateway—a shorthand term for a role-based access-control (RBAC) service hosted by the enterprise service bus (ESB). Discussion touches on some of the enterprise-level requirements and challenges that motivate this approach, such as increasingly stringent and granular authorization needed for legal compliance and the need to ensure that enterprise authorization is tightly integrated with robust authentication and identity management.
The merits of an authorization gateway strategy are considered in light of an authorization maturity model, a conceptual framework for assessing some of the pitfalls inherent in traditional approaches to access control, such as application entitlement and makeshift, application-specific mechanisms that create added cost and complexity for development, manageability, and provisioning.
Active Directory Application Mode (ADAM) and Microsoft .NET are offered as ways to implement an effective, low-cost infrastructure that can support an enterprise authorization architecture, while leveraging existing infrastructure such as Active Directory directory services and the service bus itself to provide an enterprise-wide, cross-platform authorization gateway.
Later, we will complete this strategy by showing how this approach can be readily adapted over time to accommodate a claims-based access-control system capable of supporting federated scenarios without having to completely revise the architecture or overhaul the existing infrastructure.
Finally, attention is called to the importance of planning and implementing this architecture as a high-performance, scalable, and highly available service.
Most technical terminology has become so overloaded with meaning, it's a wonder that we can communicate intelligibly at all. The terminology and concepts surrounding authorization are hardly an exception. In the interest of clarity, here are some working definitions for our discussion:
Authentication—Determines the identity of a user or process.
Authorization—Determines what resources can be accessed or what actions can be executed by an authenticated user or process.
Authorization gateway—A term coined to identify the strategy of consolidating the roles stores behind a well-defined authorization service interface hosted on the enterprise service bus.
Access control—Constraint(s) on what resources can be used or what actions can be executed; for our discussion, access control is used synonymously with authorization.
Claim—An assertion about the right of a user or a process to access resources or execute an action. A claim has three constituents: a type, a right, and a value. A value in most cases is the resource or action to which a right pertains.
Claim-based access control—A form of authorization based upon certified assertions about a user or process.
Application entitlement—The method of authorizing access to an application when the application is installed or loaded. This should; not be confused with the concept of entitlement that is sometimes used to denote the sum of all roles and resource for which an individual user or group is eligible.
Group—A collection or association of user account (identities) and/or other groups. A group typically has its own identity; in some contexts, such as Active Directory, a group can function as a role; in other contexts such as Authorization Manager, a group is used as a collection of identities which can be assigned to a role.
Role—An abstraction that represents a set of functional responsibilities; a role can be comprised of specific permissions needed to discharge those responsibilities. Typically users and groups are assigned to roles to authorize these permissions.
Role-based access control (RBAC)—An access-control mechanism based upon assigning users or processes to roles.
Permission—Defines access to a specific resource or the right to perform a specific action. In a well-defined authorization model, permissions have a many-to-many relationship to roles. For example, the author role and the editor role might have permission to read and write a document, whereas publisher and subscriber roles might have only read permissions.
Impersonation—When a process assumes the security context or identity of a specific user, to acquire access authorization to resources or perform an action on the user's behalf. When impersonation is extended to remote resources, it is referred to as delegation.
A good authorization strategy is fundamental for any enterprise security model. Yet for various reasons discussed in a moment, authorization seems to be one of the most neglected elements of the enterprise security model.
Despite neglect, many industries are coming under increasing pressure from government regulatory-compliance requirements—such as Sarbanes-Oxley, HIPAA, and CFR21 Part11—to ensure that proper and effective access controls are in place for a wide range of electronic resources and information. The trend across many industries seems to be toward increasingly stringent and granular access-control requirements. Compliance is one of several reasons this challenge can no longer be ignored.
The Tragedy of the Commons
The "tragedy of the commons" is a condition that occurs when a common resource or service is needed by all, but neglected, because self-interested individuals are unwilling to bear the cost of development or maintenance. Perhaps an enterprise strategy has been neglected for authorization, because it is a common resource that is intended to be shared by applications across the organization. Building shared application infrastructure of this kind must be planned and funded independent of any specific application budget.
So, the manner in which budgets are allocated might partly explain why some organizations have neglected authorization infrastructure. In some respects, it makes perfect sense to view authorization as a key element of security infrastructure in the same way that identity management and authentication are. In other respects, however, access-control requirements can be viewed as specific to each individual application.
All too often, the result of this apparent ambiguity is that authorization gets pigeonholed into specific project budgets and the same mechanisms are implemented over and over again with each new application, while the true costs of this redundancy are hidden as line items in individual projects. Yet no project has the budget or mandate to build a robust, shared service that meets the needs of all. Beyond the added cost, this siloed pattern typically yields inconsistent security in the best cases, and consistently poor security in the worst. To begin treating authorization as a first-class citizen of the security infrastructure, will undoubtedly require some investment in the security "commons."
Lack of Standards
There are numerous methods for controlling access to information and resources and some methods are better suited to certain scenarios than others. This has given rise to a great deal of confusion about which method(s) of authorization are most appropriate for a specific situation. Adding to the confusion, software vendors are often forced to provide built-in authorization mechanisms in their own solutions to ensure that it can be securely deployed in a broad range of customer environments. Of course, software vendors can hardly be blamed, because, until recently, industry-standard protocols and interfaces for authorization were ill-defined or completely undefined. In the absence of such standards, vendors are at pains to supply built-in access-control mechanisms—frequently, more than one.
Without enterprise-standard protocols and interfaces, in-house developers are faced with the same difficulty as vendors. Over time, the inevitable result is a patchwork quilt of proprietary and home-grown access-control mechanisms, increasing both development and administrative cost and complexity. The need to build custom tools and scripts for provisioning and routine administration can also add greatly to the cost and time-to-market for a solution.
Assessing the Situation
If you are a CIO reading this, you can gauge your own situation by asking these questions: What would it take to determine with some precision which permissions are granted to any given individual across my entire enterprise? What steps must be taken to ensure all proper authorization is granted for a new employee acting in a given business role? If you can give a concise answer to these questions, take a mental victory lap, as you are ahead of the curve. Even if you are, however, this level or organizational maturity probably comes at a much higher cost than you would prefer. And, by the way, if you do not have good answers to these types of questions, you at least can take some comfort from the fact that you are far from alone in this predicament. It is commonplace in the enterprise.
The emergence of service-oriented architecture (SOA) tends to amplify existing authorization challenges. Services are often specifically designed to be accessible across traditional security domain boundaries and platform boundaries as well. The economies of scale and scope that can be achieved through service orientation are compelling, but pose new challenges for both authentication and authorization to satisfy the growing need to transcend these boundaries. The adoption of SOA might complicate the security picture; but, as such, it is a powerful motivation for improving authorization.
Increasingly, organizations will seek to federate with one another to achieve economic and/or competitive advantages. In most cases, each organization already has its own established system for managing the identity of its members. Each organization is sovereign, providing electronic identity and controlling access to resources within its own borders. To form a federation, therefore, each organization has basically two choices. It must either issue and maintain identities for individuals who are not members, or devise a means to recognize the electronic identity already provided by a foreign system. The former has been tried with limited success, but maintaining multiple identities for the same individual tends to be costly and confusing for organizations and highly inconvenient for the unfortunate individuals who must maintain multiple accounts with different passwords, password strength policies, and expirations. Infrequently used accounts lead to expensive resets and business delays. When users write passwords down in the clear to avoid these issues, they create far more serious security risks.
A single identity for each individual seems preferable for these reasons, but then how can authorization be performed in one domain for an individual whose identity is defined in another? For that matter, how can authentication be reliably performed in this situation? Because reliable authorization begins with reliable identification (authentication), federation creates a real dilemma. We are forced to accept either multiple identities or multiple identity providers. Given the serious drawbacks of the former, most federations are based upon the latter.
If we accept multiple identity providers as an operative assumption of federation, access control must rely on some portable form of identity to determine which roles and permissions pertain to each access request. The need to extend trust to individuals from foreign or semi-trusted domains for the purpose of federation only complicates the requirements for enterprise authorization strategy.
The Software-as-a-Service (SaaS) architecture also poses an interesting challenge for authorization strategy. Services hosting multiple consumers (multi-tenancy) must confront the fact that a single user (identity) will often need to access resources and execute actions for more than one tenant.
Shippers furnish a great example of this, because shipping is so often outsourced. Direct competitors frequently use the same shippers for distribution, setting up a many-to-many relationship. Consider scenarios where a shipping manager might need to access SaaS resources for several customers hosted by the same service provider. One approach to this problem has been to issue multiple identities to the same individual, but this creates cost and complexity for providers and all the well-known inconveniences of managing multiple account credentials for the shipping manager. Clearly one identity and multiple distinct roles is a more sensible solution. Additionally, each SaaS tenant is at liberty to accord each shipper only those roles and permissions appropriate to its policies and business terms with the shipper.
A maturity model can provide a conceptual framework for understanding some of the shortcomings of traditional approaches, the benefits that an enterprise authorization gateway strategy can provide, and how it might evolve in the future. Few organizations, if any, can be expected to fit neatly into any phase the model shown in Figure 1. Perhaps most organizations will exhibit elements of several phases at once. These discrepancies are not important as long as the model helps to explain how an authorization gateway can help to address the challenges we have already mentioned and help define a road map for improvement.
Figure 1. An authorization maturity model
The Basic Maturity Level
Authentication is not authorization, but it sometimes serves as the de facto form of authorization for many organizations. By definition, the purpose of authentication is to determine the identity of the user with assurance. Once the identity of the user is known, the purpose of authorization is to determine what resources the user is allowed to access. Often at this basic level of maturity, however, if allowed to logon to an application, the user is also allowed to execute any and all functions performed by the application; in effect, authentication becomes full authorization. This approach is far too coarse-grained to meet most contemporary compliance requirements.
Impersonation and Scalability
This security model was prevalent for client/server applications when access to resources could be controlled at the resource instead of the application tier. For this model to work, the application must assume the identity of the logged-on user. This approach, generally referred to as impersonation (or delegation in n-tiered scenarios) has long outlived its usefulness. For several reasons, it is obsolete and should be abandoned for multi-tiered solutions.
The impersonation model creates a serious drag on scalability. For example, it completely vitiates the benefits of database connection pooling. Making a connection to the database can be one of the more expensive data-access operations, especially when frequency and latency are both considered. Connection pooling reduces the run-time cost of creating connections by opening multiple connections to the database at one time and then sharing them on an as-needed basis. Sharing connections also reduces the burden on the database server by reducing the total number of connections that must be managed. However, connections can only be pooled if they share the same connection context. For the middle tier to take advantage of pooling, it must make each connection with the same identity. Connection pooling is not possible when impersonation is used, because impersonation requires that each connection use a different identity—that of the user. For this reason, an authorization model that relies on impersonation is simply not compatible with a scalable middle tier.
Another negative impact on scalability from impersonation results from the fact that the application does not know whether it has access to a specific resource until a request is made. This means many more doomed requests are made only to discover that access is denied. This approach can be very costly both in terms of network and in terms of processor cycles for the resource dispenser itself. The resource dispenser must use precious cycles to check authorization for both valid and invalid queries. This form of access control can also create a very confusing and unfriendly user experience, because it is not clear why access has been denied. As Charles Petzold pointed out long ago, disabling options that are not valid provides a much better user experience. In the distributed computing environment, however, this advice presupposes an independent means to determine what actions are valid before they are executed.
Undoubtedly, it will be pointed out that Microsoft Windows uses Access Control Lists (ACLs) to secure files and other network objects. An ACL is essentially a list of identities denoting user, group, or process accounts that have permissions to access a particular object. In effect, when an operating system uses ACL-based security, it is relying upon impersonation to determine what permissions to accord for a particular object. You can bet that, as primitives of the operating system, ACLs and impersonation are not going away anytime soon. Impersonation will continue to play a part in machine-local access control. For applications, however, avoiding impersonation still makes sense. In most scenarios, ACLs can be superseded by role-based access control (RBAC), because primitive permissions—such as "read," "write," and "execute"—do not pertain to the higher-order functional abstractions. Consider a document-publishing application for a moment. The "publish" permission might entail many complex actions, such as reading documents, writing documents, versioning, notifying subscribers, and so on. Under the covers, some of these tasks might even rely upon the ACLs associated with the application process to control certain actions.
What is important to realize here is that the application does not have to resort to impersonation to control access to the publish action. In fact, the primitive "read" or "write" permissions of a given file on the file system are not really relevant to determining who can publish at all. Perhaps for this reason, document management systems typically store documents in a central relational database where it is much easier to model the complex relationships between physical files, users, workflows and, of course, the defined roles required to manage the document life cycle. In this case, for example, a single check to determine if the user is assigned to the publisher role is a far simpler, more intuitive, and more efficient way to control access.
Design Implications of Impersonation
In some cases, applications that were originally designed as client/server and then retrofitted with a middle tier fail to achieve expected improvements in scalability. One reason for this is that the database was designed to support impersonation and it was deemed too costly or time-consuming to redesign the data tier.
One major advantage of the authorization gateway strategy is that it forces developers to abstract roles and permissions from the physical resources that are controlled by them, preventing a design that tightly couples control to data access. In some legacy applications, these might be so intertwined that it requires a complete re-architecture to eliminate this tight coupling. The remedy for some of the scalability issues discussed above can be fairly intractable for legacy systems. A remedy can be exceptionally difficult or costly when a large body of legacy data has been accumulated over time based upon an authorization scheme built into the data tier. However, this fact should not be used as the reason for perpetuating this authorization design.
In general, a good authorization design should be an integral part of the solution design, treating roles as a higher-level abstraction that models the organizational responsibilities of intended users. Even permissions, which are more granular than roles, should most often be fairly coarse-grained and represent actions or activities, instead of the specific resources needed to conduct and execute them. Often, the actors defined during the design phase of an application will map quite closely to the roles needed for a good authorization design.
Impersonation Security Issues
Impersonation creates a potentially serious security issue. When individual users can connect to a data source using their own credentials, there is nothing to prevent them from connecting to the same source with another tool or utility. Users are at liberty to make data changes outside the confines of business rules implemented in the application. Because it is neither practical nor advisable to implement all business logic at the data tier, it is nearly impossible to prevent access to the data outside the constraints of business rules when impersonation is in play. When this situation exists, it can be very difficult to achieve full compliance with regulatory requirements.
Application entitlement is another authorization strategy that is sometimes found at the maturity level. In this strategy, the user's access to applications is controlled, instead of access to specific resources. In some cases, this is implemented at application load time. If the user does not have access to the application, the application simply terminates itself. In other cases, entitlement is determined at installation time. Applications are installed by administrative push, and each user receives only the applications to which each user is entitled. In either case, this strategy reduces itself to using authentication as authorization, unless more granular authorization is also implemented within the application at run time.
Excessive licensing costs are one very serious drawback to the strategy of controlling application access at run time. Many EULA agreements, for example, require an organization to pay a user license for software if it is installed, regardless of whether it is actually used. When entitlement is not determined until load time, it might be necessary to install many applications that will never be used by a specific user. This is one place, at least, where a more mature authorization strategy can pay real dividends.
In either form, application entitlement amounts to using authentication as authorization. As a result, this approach tends to suffer from many of the same issues already discussed.
In general, the strength of authorization depends upon the strength of authentication; if authentication is weak, so is authorization. Before directory services were widely deployed in the enterprise, many applications assumed full responsibility for authentication, too. The security problems that result when applications implement custom authentication are myriad and well-known. Here is a list of the most egregious flaws; this list is by no means exhaustive:
- Different identities for each application
- Different passwords for each application
- Different password strengths for each application
- Different expiration policies or no expiration policies
- Passwords stored and/or transported in the clear
- No universal means to enable or disable accounts
- No universal way to audit or report activity for an individual
- Administrative chaos and high cost
Hopefully, recalling some of these negative aspects will help remind us of why it is important to move to a more mature stage of our model. Instead of further belaboring the point, let's turn our attention to the next level or maturity.
At this level, authorization is accomplished at the application tier. Authentication is typically accomplished thru at least one directory service such as. Active Directory directory services in the Windows environment. Organizations with mixed platforms might have multiple directory services (DS) depending on the OS platforms deployed. Ironically, multiple DS often creates the need for federated trust between domains within the enterprise first, necessitating metadirectory services to unify identity management and facilitate the "holy grail" of identity management: the single sign-on (SSO).
Curiously, no one seriously questions the necessity for enterprise-wide authentication today. Yet, it seems that the idea of an enterprise-wide authorization strategy is just beginning to take hold—to say nothing of a federated strategy for authorization that would extend access control to identities beyond enterprise security borders.
For our discussion, it is sufficient to note that some form of robust identity management and integrated authentication is possible at this level of maturity. Strong authentication is a necessary prerequisite for strong authorization. Applications can and should defer authentication to external authority. Authorization can then be accomplished by assigning identities to groups and/or roles. Applications can test for membership in specific roles to determine which authenticated user should be allowed to access which resources. Applications simply test the each user's identity for assignment to a specific role to determine what they are authorized to do.
RBAC is a much more robust form of authorization, because it fully abstracts functional roles from the resources or actions that are part of any specific application. Roles can be defined that more accurately reflect spheres of business responsibilities within an organization. By modeling functional responsibilities, roles are potentially more useful and reusable across various solutions. The term "potentially" is used advisedly here. For roles to be reusable, they must be declared and implemented outside the confines of any one solution so that they are readily accessible to other solutions. Centralizing roles and authorization can also dramatically reduce cost and improve operational efficiency by eliminating unnecessary redundancy.
Note: Not all roles are meaningful to all applications. In many cases, very granular roles must be distinguished to properly control access for a specific application. One of the principal advantages to RBAC is that roles can be defined as coarse- or fine-grained as they need to be. In either case, there are benefits to be gained by centralizing authorization where, for example, global roles can be defined once and then shared across multiple applications.
Decentralization of Access Control
Unfortunately, centralizing role-based authorization is the step typically not undertaken at this level of maturity. More often than not, each solution implements its own roles repository, provisions it, and stages its own authorization mechanism as an integral part of the application. Each application becomes an authorization silo unto itself. Roles are often difficult or impossible to reuse by other applications, because no provision is made for such reuse. In some cases, developers who are focused on defining application-specific roles lose sight of the importance of leveraging global roles where it makes perfect sense to do so.
Let's face it: As developers, we are notorious for ignoring or underestimating the operational consequences of our designs, but as architects we must pay close attention to them, because they are usually key factors of success. When you combine the proprietary authorization mechanisms of vendor solutions with the silos created in-house, the inevitable result is the patchwork quilt of different role definitions, repositories, and authorization devices that we spoke of earlier. Add to this the sometimes heavy price that is paid for implementing these redundancies—along with the custom tools and scripts for provisioning each system—and the price tag can be very high indeed, both in terms of real dollars and in time-to-market for a particular solution. Whether these costs are hidden as project line items or not, the impact to your budget and your organization is very real.
Figure 2. Authorization and roles in application silos
Figure 2 depicts a hypothetical scenario in which roles are defined in a variety of different stores. Role information might be provided in a variety of forms, including everything from directory entry (DE) objects to recordsets.
Authorization APIs are called over many different protocols.
Each roles store might require different tools and operations to perform routine administrative tasks such as assigning a user to a role, or provisioning new users. These silos can make it difficult, if not impossible to get a three hundred and sixty degree view of the roles and responsibilities of individual users in an organization.
Physical security layers such as firewalls pose difficult decisions for this model as well. One of the most common quandaries occurs when an Internet-facing Web application is hosted in front of a corporate firewall (in the DMZ). This model faces the dilemma of placing the roles store and potentially other sensitive data in the DMZ or opening sensitive ports on the firewall. Neither choice is ideal.
Fortunately, the authorization gateway strategy that we discuss next can directly address many of the pitfalls of decentralized authorization.
Advanced Maturity: Authorization as a Service
In the advanced level of maturity for authorization, role storage and management is consolidated and authorization itself is a service available to any solution that is service-enabled. The expression "consolidated" is not a weasel word in this context, because total centralization is generally not achievable when numerous legacy applications are still in use. This is a fact of life in the enterprise. But we should not let perfection be the enemy of progress here. Later, when we discuss how this model can be implemented, we will see that completely centralized management might not be practical and is not really possible in the federated model, anyway. However, the operational advantages and efficiencies of consolidating the authorization infrastructure and providing a service facade are obvious. Fewer tools are needed. System maintenance and routine administration are simplified. Fewer changes are needed, because redundancy has been minimized.
An authorization service with a well-defined interface is a hallmark of advanced maturity. Establishing a service facade eliminates the burden of re-implementing authorization for each solution. Service-enabled authorization provides a simple, consistent programming model for implementing access control and makes it more readily available to developers across platforms as well as security boundaries such as firewalls. Broad availability of an authorization service also allows developers to focus on the definition and mapping of roles and permissions to specific resources or application activities, knowing that these can easily be declared and exploited without writing a lot of custom code. This allows them to make access control a first-class element of design, instead of a burdensome afterthought that inevitably engenders refactoring. An authorization gateway, therefore, tends to promote a more agile development cycle.
The Trusted Subsystems Model
Once authorization is available as an autonomous service, the need for impersonation is eliminated. Instead of assuming the identity of the user, the application uses its own credentials to access services and resources, but it captures the user's identity and passes it as a parameter (or token) to be used for authorization when a request is made. This model is referred to as the trusted subsystem model, because the application acts as a trusted subsystem within the security domain.
The trusted subsystem model overcomes many of the weaknesses inherent is less mature models that must rely upon impersonation. For example, trusted subsystems can take full advantage of connection pooling, reducing the number of connections that must be managed at the data tier, and generally producing a much better scalability.
Even more importantly with the trusted subsystem approach, domain administrators can lock down key application resources, permitting access to only one or two accounts: the trusted subsystem (application) account and an administrative account. Locking down these resources helps to ensure that access to them is properly constrained by application business rules and more fully protects the integrity of the data. Data access through tools and utilities other than the application is simply not allowed. In security terms, the attack surface of core application assets is dramatically reduced.
The Power of a Service Contract
Before we move on to discuss how an authorization gateway could be implemented, it is worth dwelling on the importance of a well-defined service contract for this strategy. Consider an example from the hotel industry, if you will. For a very long time, hotels used hard keys to provide guests with secure access to their rooms. In this model, additional keys would be needed to provide special guests with access to other amenities such as the pool, the mini bar, or the health club. Guests often inadvertently took the keys when they left or lost them, imposing maintenance and tracking burdens on the staff as well as the cost and inconvenience to the guests themselves. Many redundant keys are also needed for shared amenities. Each key is tightly coupled to its lock, just as the access-control mechanism is tightly coupled to certain application resources or activities in less mature authorization models. Of course, the larger the hotel, the greater the burden becomes.
A more advanced model, and the one used almost universally by every major hotel chain today, is the cardkey system. In this system, it's important to realize that it isn't just the key that is different; it's the lock, too. Every key "fits" every lock, because there is a simple, consistent interface that every lock throughout the system supports. To cast this in more service-oriented terms, think of the lock as providing a contractual guarantee to read all cardkeys and unlocking only for the right one. This makes it much easier to provide access to additional amenities simply by reconfiguring the key. Much of the maintenance and inconvenience of hard keys is eliminated. But even more importantly, consider the prospect of making a wholesale improvement across the system. In the case of hard keys, it might be cost-prohibitive, because all locks and keys must be changed. In the case of cardkeys, some improvements might require no change to the fundamental contract. This is a powerful benefit of separating the service interface (contract) of access control from the underlying implementation and one of the principal benefits that accrues when the access-control service contract is loosely coupled to the underlying implementation(s).
Defense-in-depth is such a widely accepted principle of security modeling that it can accurately be referred to as an axiom. If the idea of an authorization gateway violates this axiom, it would be a very grave indictment of our authorization strategy. We have to ask: Does the idea of a single authorization gateway exchange many layers of defense for a single layer of access control? The answer to this question is emphatically "No." In fact, the gateway approach can support an arbitrary number of defense layers or "gates" based upon the requirements of a given solution. As a general mechanism, an authorization gateway can simplify and streamline authorization without limiting access control to predefined security boundaries. Instead, the solution designer has the flexibility to define and test authorization at any point within a specific tier, based upon the actual security policies of the business model.
Implementing an Authorization Gateway
If you build an authorization gateway on Microsoft Windows Server 2003 and .NET, many of the core components you will need are ready-made and designed to be integrated with one another:
- Microsoft Active Directory Application Mode (ADAM)—Provides a freely downloadable directory store that is fully compatible with any LDAP v3–capable clients. ADAM is a lighter-weight version of Active Directory that runs as a Windows service, making it is easier to manage and offering a schema that is specially designed for role-based authorization. It can fully integrate with Active Directory identity management and authentication.
- Authorization Manager (AzMan)—Provides a convenient Microsoft Management Console snap-in tool for routine administrative tasks, such as declaring, assigning, and revoking roles and permissions (operations). Several other tools—such as ADSIEdit, and LDIF—are also available for managing the ADAM schema and bulk provisioning.
- .NET 2.0 Framework Role Providers—A collection of provider classes that are part of a framework that adapt role-based authorization to specific data stores, such as ADAM, AD, SQL Server, and others.
- Windows Communication Foundation (WCF)—Provides a means to build an authorization service that is itself secure, interoperable, and takes full advantage of WS-Security and WS-* standards.
Figure 3. An authorization gateway on the ESB
Referring back to our hypothetical example from Figure 2 for a moment, we can imagine adapting authorization from application silos into an authorization gateway as shown in Figure 3. Notice that some legacy applications might remain untouched. Still other applications might already have an existing set of roles that can be used in place. Finally, ADAM might be used to host roles and permissions for new applications, as well as those migrated from other stores.
It is also worth noting that other services on the ESB can use the authorization service directly in scenarios where it makes sense. Often, it might make more sense to make requests for authorization directly from other services, because it ensures that precisely the same authorization criteria are always used regardless of which application avails itself of that service. Used as a general utility, a well-designed authorization service can help to support a service facade, promote service autonomy, and ensure broad compliance to the most stringent requirements The composition of business services at the facade layer is an established service-design pattern. Exposing underlying services directly is not a violation of this pattern.
If we delve too deeply into the details of implementation here, we risk missing the forest for the trees. Fortunately, the main elements of authorization in WCF along with code samples and explanations have been elegantly covered by Microsoft Windows Communication Foundation: Hands-On!. We will stay focused on the key architectural elements of this implementation. For example, if AD is already used in your enterprise, why not just use it instead of ADAM? We will have more to say about WCF in a moment; but, for now, let's turn our attention to ADAM.
Using the ADAM Store
Active Directory provides a very rich and powerful set of directory services and it is perfectly possible to use it as the store for our authorization strategy—especially if you are already using it for identity management and authentication. However, there are still some important considerations that make ADAM a worthy choice for authorization.
ADAM and Active Directory
As a product, ADAM is cut from the same cloth as Active Directory. As such, ADAM bears a close family resemblance to Active Directory, providing many of the same powerful LDAP directory services such as management of user and group hierarchies, replication and so on. But unlike AD, ADAM installs and runs as an NT Service on Microsoft Windows 2000 or greater. You can install multiple instances on the same machine without need for virtualization. In fact, it will also run on Windows desktops of the same versions as well. This means that developers can run it on their workstations, permitting them to build and test the authorization pathways of their code and treat authorization as an integral part of the application design, instead of a burdensome afterthought—hence, the "Application Mode" extension to its name. Because ADAM is freely downloadable, development, testing, and production deployments are much less costly and much easier to manage than Active Directory for implementing application authorization.
Another enormous advantage of using ADAM instead of AD is that it can be deployed and administered independently, but still take full advantage of AD identity management and authentication. By storing roles in ADAM, the routine administrative tasks of assigning users and groups to specific roles or revoking their assignments can be managed without burdening domain administrators with these responsibilities. Operationally, this approach makes sense for some of the same reasons that it makes sense to separate domain administration from database administration. Administration of application roles and permissions often requires an understanding of application design that domain administrators should not be expected to possess. In a large enterprise, it is often impractical for domain administrators to understand the myriad roles and responsibilities of each application. Using ADAM can improve operational efficiency by permitting independent administration of application roles and responsibilities, without any special authority with the AD itself.
Run-Time Authorization Loads
Using ADAM for authorization can also help to alleviate substantial run-time loads on AD, reducing the need to scale out a more costly layer of the infrastructure. Ordinarily, authorization requests are invoked much more frequently than authentication. In some application scenarios, users might authenticate very infrequently, keeping sessions alive for hours at a time. During those same sessions, however, the application might need to authorize hundreds or even thousands of specific actions, creating run-time loads that might be several orders of magnitude greater than those imposed by authentication. ADAM can be easily and cost effectively scaled out, leaving more processing cycles on AD domain servers for core functionality such as authentication, management of the global catalog, replication, and so forth. We will return to the subject of scalability in our closing discussion.
Developers will be quick to point out that much of the load of authorization requests could easily be reduced by caching roles at the middle tier or even the presentation tier, leaving full control of authorization to AD. While it is true that caching can reduce run-time overhead, it can also have the effect of actually reducing control. When an application uses cached role information, administrators cannot immediately revoke access to resources or actions unless they can also flush all caches. In a highly distributed environment, this might be impractical. Moreover, it might be completely unacceptable to rely on cached role information for some high-security environments. As a scalable authorization store, ADAM gives application developers the latitude to use caching if it makes sense and scale out the roles store if it does not.
Authorization Manager and Other Tools
Authorization Manager provides a rich set of APIs for administering the ADAM role store when the ms-azRoles schema is installed. Any administrative tasks that can be managed with the Authorization Manager Snap-in for MMC can also be used programmatically through these APIs. This means that developers do not have to build a special tool for declaring, assigning, or provisioning roles in ADAM.
More importantly for our discussion, Authorization Manager provides the APIs needed for access and permissions checks against ADAM. Using Authorization Manager and ADAM together provides a highly functional and complete system for role-based authorization (see McPherson, under References).
Using WCF Services and the .NET Role Providers
The provider pattern is a time-honored and flexible way to loosely couple an API to its underlying implementation. This pattern is used, for instance, by OLE/DB to unify data access beneath a single, rich set of well-defined APIs. This pattern works equally well for implementing service contracts. The .NET Framework 2.0 provides a collection of built-in role providers that support this pattern for RBAC.
Using the AuthorizationStoreRoleProvider
Specifically, the AuthorizationStoreRoleProvider in .NET 2.0 provides a built-in .NET class that is well-suited for implementing our authorization gateway strategy. This class is a managed code wrapper, encapsulating an RBAC API called using Authorization Manager. Leveraging this class directly allows you to implement authorization with very little custom code and take full advantage of a broader framework within .NET for configuration and integrated security, including the RoleManager, WindowsPrincipal, Windows Identity, and User classes, for example (see Meier, under References).
The AuthorizationStoreRoleProvider could be embedded and used directly from application code, doing this would amount to reverting to the previous level of maturity. Authorization is now tightly coupled to each application. We would be back to silos. It also limits the use of these frameworks to .NET applications, whereas using this framework behind a service facade means we can use authorization with service-enabled applications on other platforms, too.
Using the SqlRoleProvider
Figure 4. Details of the .NET providers
Looking more closing at the details of the provider pattern shown in Figure 4, one might ask why the SqlRoleProvider is even necessary. The answer is simply that it might not be, but it is shown this way to call attention to several important points.
The first point is that there are other built-in providers. If, for example, a role database were already in use prior to constructing a service facade, it could be used in place without forcing migration of all role information to ADAM.
The second point to notice is that our authorization service could easily aggregate multiple roles stores behind a single service contract if properly designed. In a well-designed service contract, the potential for multiple stores and providers should be assumed even if not immediately needed. This means that each authorization service request message should contain parameters that indicate what store should be referenced to obtain the correct role assignments.
The third point is that the complexity of multiple protocols and different programming models can be effectively encapsulated by the service facade. Developers who use this authorization service can take advantage of a consistent programming model and a single source for RBAC across applications. Because services can be accessed via the HTTP protocol, applications hosted in the DMZ can more easily access the service without opening other sensitive ports such as LDAP and creating additional vulnerabilities to core resources such as Active Directory. This assumes, of course, that the service is itself well-secured. We turn to that topic next.
Note: The role providers we have been discussing are part of an extensible framework. In addition to other stock providers, it is possible to build a completely custom provider as well. These details are beyond our scope; but, fortunately, they are covered in detail in an article by Jit Ghosh called "Building Custom Providers for ASP.NET 2.0 Membership." A custom provider can sometimes be used to great effect for integrating the use of legacy application roles or permissions into new applications. In addition, the Enterprise Library provides a fully developed Security Block that enriches this provider framework and further integrates it with other important capabilities, such as auditing.
WCF and the WS-Security Specifications
In Plato's The Republic, Socrates asks, "Who will guard the guardians?" This question is directly pertinent to our authorization gateway strategy. Any service that controls access to a very broad range of resources and actions across the enterprise must be as trustworthy as we can make it. At a minimum, the following measures should be taken:
- Authorization service consumers must be authenticated with trusted subsystem credentials by the authorization service—not with an impersonated account.
- The authorization service itself must be authenticated with different trusted subsystem credentials by the role store.
- Trusted subsystem passwords are stored only in an encrypted form inaccessible to applications users. Ideally, the management of passwords should be left up to the operating system, but this can prove impractical where cross-platform interoperability is needed. If possible, trusted account passwords should be changed periodically (though this can be difficult to achieve as well in practice).
- Consider encrypting either the communication channel or the messages between the consumer and authorization service, and between the authorization service and the store. The information that "John is assigned to the BlueMan role" might not seem very sensitive, but it is a good practice to eliminate opportunities for systematic scanning that allow attackers to better understand the inner working of a system.
- Always audit all changes to role assignments at the role store, including when auditing is turned on and off. The idea is to prevent a phantom authorization where a user is momentarily given elevated privileges to conduct an illicit action and then these privileges are immediately revoked without a trace.
- Keep the principle of least privilege in mind. Implement an authorization service that is limited to read-only privileges for the roles store if possible.
- Both the authorization service host server(s) and the authorization store server(s) must be kept physically secure at all times.
- Administrative access to the authorization store should be limited to a few, well-trained and trusted administrators.
The foregoing list might make building authorization service consumers seem formidable, but don't despair. Developers can be shielded from most of the complexity with a well-designed consumer service proxy and a software factory approach—a topic we will return to in our closing remarks. For the moment, we should note that even the proxy framework itself is more approachable with Windows Communication Foundation (WCF).
Strictly speaking, WCF is not absolutely necessary for building an authorization service. It could be built with NET 2.0 Web services (ASMX 2.0) and WSE 3.0. In fact, ASMX 2.0 allows the Web service developer to do a contract-first design approach, implementing the Web service contracts as a .NET interface. This helps to ensure the loose coupling between interface (service contract) and implementation that is needed for our authorization gateway strategy. However, implementing our authorization as a WCF service can provide all these benefits and much more when it comes to security.
The System.ServiceModel namespace that WCF adds to .NET is comparatively well known, but it also adds the less well known System.IdentityModel (see "Managing Claims and Authorization with the Identity Model," under References).Together, these two namespaces provide much more complete coverage of the WS-Security specifications. This coverage is important in its own right, because these specifications are among the most broadly recognized and supported industry standards that we have today. Moreover, broad industry standards are an essential prerequisite for achieving federated security, which we discuss next. However, the System.IdentityModel namespace will prove particularly valuable for taking our role-based authorization gateway strategy to the next level. If you cut WCF, it will bleed WS-Security specifications.
Federation-Capable Maturity Level
The authorization gateway is not the final step in our maturity model, because it is not federation capable, but it can be adapted to support federation without requiring sweeping changes to the existing architecture we have defined for our authorization gateway strategy.
Broadly defined, federation means extending limited trust to users, groups, and systems identities from foreign security domains. As mentioned at the outset, the potential benefits of federation are a powerful motivation for employing federation with other organizations, but it must be supported without compromising security.
The concept of federation has been around for a long time. If you have ever driven your car in a neighboring state using the driver's license issued in your home state, you have enjoyed the benefits of federation. If requested, of course, you are responsible to provide evidence that you are legally licensed to drive. If you are stopped by the police in a neighboring state, for example, they might not be able check with the issuing authority in your state to ensure that your license is valid, the way that they would if you were local. In this circumstance, your license must speak for its own authenticity in the same way that legal tender must distinguish itself from counterfeits.
This type of authorization is referred to as claims-based authorization. The authenticity of a claim token (such as your license) stands for the validity of an authorization claim—that you are licensed to drive, in this case. Each claim has three elements including: a claim type, a right (to specific access), and a value that represents the resource or action to which the right pertains. Claims can be organized into related sets. While this might sound a bit gnarly, it's actually quite simple. We are already accustomed to documents that contain a set of claims about us. A birth certificate, for example, contains a set of claims about date of birth, place of birth, given name, parents, and so forth. This is a set of claims, each of a different type. One difference is that many of the "values" are implied instead of explicit, as they are in an electronic claim. Taken together, the set of claims on a birth certificate implies the right of citizenship.
Beyond the Trusted Subsystem Model
The most important point for our discussion is that roles and permissions can be expressed as claims. In other words, roles can be the raw material from which claims are constructed. Ultimately, claims are the more powerful construct, because they are portable across domain and network boundaries. It is also worth noting that claims are not limited to authorization; they can also be about identity, for instance. Because claim sets can be delivered as part of a service-request message, they do not have to originate from a trusted subsystem within the local domain to be valid. The claim-based authorization model is much better suited to the task of controlling access in federated scenarios. It is also important to note that federation is not always an extension of trust across completely independent organizations. Mergers, acquisitions, and siloed business models frequently create the need for federation within the borders of a large enterprise.
There are two sides to the federation concept. On one side, claims must be constructed and issued with requests for access to resources. On the other side, services must be able to evaluate the validity of claims in the context of a service request to permit or deny access to specific resources or actions. Of course, to be truly portable, claims must be transported in a form that is based upon widely accepted, platform-independent industry standards.
Fortunately, the Identity Model in WCF provides the machinery to address this using a consistent .NET programming model. The System.IdentityModel namespace provides a set of classes both for issuing claims and evaluating them in the context of a service request processing. Many of these classes should have a familiar ring by now: Claim, ClaimSet, ClaimTypes, and Rights. The intent of these classes should be fairly obvious after the foregoing discussion. In addition to the claim-related classes, the WCF Identity Model also provides a collection of classes for packaging up claims into a highly portable token format based upon Secure Assertions Markup Language (SAML). SAML is essentially an XML-based language for describing claims. A Security Token Service (STS) is simply the packaging agent that constructs claim sets (assertions) into SAML tokens and then seals the package with a digital signature to ensure that the token can be trusted.
Recalling our earlier example of a driver's license, the STS acts like the Department of Licensing, constructing and issuing a tamper-proof token. The details of these classes are beyond the scope of our present discussion, but it is vital to realize that it is not necessary to master SAML or the WS-Security specifications to begin to reach a federation-capable authorization system, because the WCF Identity Model provides the necessary machinery in a familiar programming model. The WS-Security specifications are not quite completely baked, but WCF can provide very broad coverage of these industry standards as they exist today. And this includes WS-Authorization, WS-Federation, and WS-SecureConversation, which are especially germane for our strategy.
If you have been paying close attention, however, there is something core to our strategy that WCF does not provide: the actual claims. If we can borrow a page from Aristotle's Metaphysics, WCF can provide the form, but not the substance of authorization claims. The question for us is: Where do we get the substance of claims? Like roles, claims must be defined in ways that are specific to the business rules and policies of applications.
Hopefully, you have already reached the answer to this question. Because roles can be expressed as claims, we can adapt our role-based authorization infrastructure to supply the raw materials for constructing claims. By adapting our authorization gateway strategy so that it supports a claims-based approach, we can take a strategy that already meets fundamental enterprise requirements for access control and adapt it to support federation scenarios based upon widely supported industry standards. Adapted in this way, we advance our authorization strategy to the federation-capable level of maturity.
Adapting the Authorization Gateway
Figure 5. Adapting the gateway strategy for federation-capable authorization
Figure 5 depicts what our hypothetical scenario might look like when adapted to a federation-capable, claim-based authorization strategy. Some legacy applications might still exist. Some applications might continue to operate using only local services and request authorization directly.
Notice that we have now introduced an STS to provide claim-based tokens for federated service requests, providing reach beyond the boundaries of our hypothetical organization. However, at least some of the claims provided in the token are composed from the existing authorization service. In effect, both the authorization service contract and implementation are still intact.
Because we have not radically changed our implementation, many of the benefits that accrued at the advanced level are still available at the federation-capable level. The same administrative tools and expertise can be leveraged, and the strengthened security model is also still in place. Neither local nor federated users are permitted to have direct access to resources through impersonation.
With apologies to Søren Kierkegaard for this subheading, our authorization gateway does not address all the security challenges that were outlined at the outset.
One especially difficult challenge remains only partially addressed. The idea of a STS, the underlying technology, and industry standards that underpin it are still comparatively new. As a result, many vendors who provide solutions to the enterprise are just beginning to embrace this approach to authorization. In fact, the standards that we have such as WS-Security and SAML are not completely solidified. While broad agreement has been achieved at the core, discussion is ongoing at the edges. For example, the WS-Security specifications seemed destined to be integrated with SAML, but we are not quite there yet. Even when firm agreement has been established along platform independent lines, platform interoperability is not guaranteed, just as the early versions of the LDAP specification did not guarantee cross-platform compatible Directory Services. Further refinement is still needed.
In absence of firm and refined industry standards, it will be extremely difficult for software vendors to produce solutions that can be readily integrated with existing enterprise authorization services. Under the circumstances, many vendors will be forced to rely upon access-control mechanisms built into their own solutions instead of relying on existing services provided by the enterprise. It might be very difficult to completely eliminate authorization silos for vendor-provided solutions. Enterprise IT will be forced to wrestle with difficult trade-offs when making the buy-versus-build decision.
This challenge cannot be fully addressed with technology alone. These standards must be driven by industry demand and cooperation. The call to action is clear and the potential benefits are compelling.
Nothing Fails Like Success
In a vain attempt at humor, I have sometimes referred to this statement as Devlin's corollary to Murphy's Law; however, there is a very serious point behind it. If the authorization gateway strategy is embraced and successfully implemented, the availability and scalability requirements will only increase over time. Hence, the more successful, the greater the likelihood of failure—unless due diligence is taken. As more and more applications leverage it, greater and greater load must be supported. The potential impact of failure is amplified. Perhaps one advantage of integrating authorization with individual applications is that a failure will only effect one application. A failure or even a slow down, for that matter, of an enterprise authorization service could have far-reaching consequences.
This caveat should not be misconstrued as discouraging the gateway approach. The same caveat applies equally well to enterprise authentication. The benefits far outweigh the risks in both cases. The real point is to recognize the risk and take the proper steps to mitigate it. The same precautions that apply to enterprise authentication must be applied to enterprise authorization. Redundancy, scale-out planning, operational excellence, and recovery planning are all strict operational requirements for authorization services.
An Authorization Factory
The authorization strategy we have laid out here cries out for a factory approach. There are a number of key artifacts needed to implement this approach that could be produced in an automated way, improving consistency across applications and accelerating development:
- A secure authorization service proxy
- A client-side (consumer) framework that integrates with the prescribed authorization model
- The declaration of application-specific roles, permissions, groups, and assignments
- Provisioning of user identities
- Unit test code for the defined roles
The Web Client Software Factory does provide some of these artifacts as part of a more elaborate factory for Web service consumers. This factory provides authorization artifacts based upon the Security Application Block implemented in the Enterprise Library (see "patterns & practices: Web Client Software Factory," under References). However, this factory was not specifically designed to support the authorization gateway strategy advocated here. Potentially it could be adapted for this purpose, or at least serve as a model for building a custom factory that more closely fits our strategy. Unfortunately, the authorization elements of the Web Client Software Factory can lend themselves equally well to the siloed authorization model, too. Care must be taken to avoid reverting to authorization silos for the sake of convenience.
An enterprise authorization strategy can no longer be neglected—and no longer needs to be. Building a service-enabled authorization gateway, based upon RBAC can reduce cost, promote a more agile development cycle, strengthen enterprise security, and simplify routine administration. ADAM, Authorization Manager, the .NET Role Providers, and WCF provide many of the core technologies needed for a robust, low cost implementation of this strategy. This approach can also be readily adapted to support claim-based authorization in federated scenarios, bringing enterprise authorization to fuller maturity. Ultimately, platform-independent industry standards are still being refined. Complete refinement of these standards is an essential prerequisite for reaching the fullest maturity.
I would like to acknowledge Keith Homiski, John Pelak, and Allan Da Costa Pinto for taking the time to provide valuable comments and criticisms that helped to make this document better. I would also like to thank Jon Tobey for improving the architecture of this document, without resorting to a heavy hand. Finally, I would like to thank my colleagues at Microsoft whose comments, discussions, and e-mails have influenced my thinking. While it is not possible to acknowledge everyone by name, I recognize and appreciate your thoughts and contributions. Of course, I take full credit for any defects or mistakes that might remain.
- Petzold, Charles. Programming Windows: The Microsoft Guide to Writing Applications for Windows 3.1. Redmond, WA: Microsoft Press, 1992.
- McMurtry, Craig, Marc Mercuri, and Nigel Watling. Microsoft Windows Communication Foundation: Hands-On!. Indianapolis, IN: Sams Publishing, 2006.
Chapter 4, "Security," provides very detailed coverage of both role-based and claim-based authorization in WCF. It is important to note, however, that this book was based upon the CTP version of WCF. As a result, technology referred to here as "XSI" is now referred to as the "Identity Model," and the namespace System.Security.Authorization was renamed to System.IdentityModel.
- McPherson, Dave. "Developing Applications Using Windows Authorization Manager" (MSDN Library, August 2006) and "Role-Based Access Control for Multi-Tier Applications Using Authorization Manager" (Microsoft TechNet, July 2004).
- Meier, J.D., Alex Mackman, Blaine Wastell, Prashant Bansode, Andy Wigley, and Kishore Gopalan. How to: Use ADAM for Roles in ASP.NET 2.0." MSDN Library, August 2005.
- Ghosh, Jit. "Building Custom Providers for ASP.NET 2.0 Membership." MSDN Library, May 2004.
- Microsoft Corporation. "Security Application Block." MSDN Library, April 2007.
- Microsoft Corporation. "Managing Claims and Authorization with the Identity Model." MSDN Library, 2007.
- Kierkegaard, Søren. Concluding Unscientific Postscript to Philosophical Fragments. Princeton, NJ: Princeton University Press, 1992.
- patterns & practices: Web Client Software Factory