Middleware platforms must cater to a variety of applications. The access control services integrated in these platforms support only access control policies with limited expressiveness and typically enforce only an invocation access policy. 1
Enforcing such a policy only takes into account information in the method invocation and fails to include application state or context in the access decision process. For example, the declarative access control system in Java 2, Enterprise Edition (J2EE) makes decisions based only on application method names and invocation caller roles. This doesn't suffice for distributed applications in which the access control policy relies on application-specific information, such as a workflow's state. For these cases, existing platforms provide an API to interact with the access control service and leave it up to the developer to enforce the application-specific access policy in the code. Embedding this imperative access control makes it difficult to adapt the access logic to new requirements resulting from policy or application changes. Imperative access control enforcement is cross-cutting—that is, it's spread all over the application and entangled in the application functionality.
Our goal was to build a modular access control service that can enforce expressive policies while accounting for application-specific state. This access control service should be bound to an application without requiring invasive changes to the application, so you can change the policy without modifying the application. Moreover, a modular access control service should encompass a reusable authorization engine, which decides on access requests according to a given access policy. Plugging such an engine into the access control service should be straightforward.
To realize these objectives, we treat our access control service as a container-managed service, which an application server provides to the application without the application's awareness. We configure the service using a deployment descriptor. It enforces the desired access policy by intercepting critical operations, calling the authorization engine, and enforcing the engine's decision. For this purpose, the access control service introduces common abstractions: subjects, (target) objects, and actions. We tune the access control service to a particular application domain by making explicit the application-specific information that's needed to evaluate access requests in the application domain. Our approach uses aspect orientation to bind the access control service to an application. Aspect-oriented languages and frameworks obtain a better separation of concerns by providing support to modularize crosscutting concerns. They therefore promise to improve the support of application-level access control services in middleware, or at least the development of enhanced access control modules that are reusable across a variety of applications. 2
We implemented a prototype of our access control service using CaesarJ ( http://caesarj.org), an aspect-oriented language that supports the modularization of the access control logic. 3
Access control service design
We based our design on two concepts, namely an access interface and a view connector. We briefly illustrate these concepts using a small calendar application. You can find a more detailed example elsewhere. 4
We based our calendar application on that of Gerald Brose, Manuel Koch, and Klaus-Peter Löhr. 5
The calendar system lets users book appointments, or entries. Entries can be singular (one entry) or continual (repetitive). A calendar entry involves participants and resources (laptops, projectors, and so on). The following access policy determines access rights for the three main actors (calendar owner, secretary, and employee):
• A calendar owner is an employee who can create, edit, and delete both singular and repetitive entries. However, the owner can't book resources for these entries.
• A calendar owner's secretary is an employee who can create only singular entries and edit existing entries in the owner's calendar. The secretary can also book the necessary resources.
• All employees can access the information in a calendar, but only the owner or the owner's secretary can change it.
An access interface provides an abstraction layer that reflects only information relevant for access control. An access interface is like a domain model in that it specifies all that's needed to formulate the access policy. In this model, the application is viewed as a set of target objects and subjects. Subjects can make an access request to perform an action on an object.
An access interface consists of several object and subject interfaces (one per role). These interfaces declare the information that the policy might need in the form of attribute declarations. An object interface also declares semantic actions. These semantic actions abstract syntactic actions and represent the security-sensitive operations to which the policy applies.
The UML diagram in figure 1
shows a possible access interface for the calendar application. An entry in the matrix at the bottom of the figure represents each access rule. The condition that must hold for the rule to be applicable is in square brackets. In our approach, the precise syntax and semantics of the language used to express the access rules are not defined in detail. What's important is the amount of information available through the access interface, which contains all information needed to formulate the access policy. In contrast, the declarative role-based access control in existing application containers such as J2EE and COM+ (an extension of the Component Object Model) limits the available information to method name and subject roles.
Figure 1. Calendar access interface and matrix.
In a more general setting, an access interface is an additional abstraction layer over several applications within one application domain. The access interface can contain application-domain-specific information while remaining reusable over different applications. For example, an access interface could introduce concepts such as a high-risk transaction for a financial application domain or emergency access for a healthcare application domain.
The access interface is bound to the application through an application-specific view connector, which you can think of as a kind of deployment descriptor. We subdivide this binding into three parts. To specify the view connector, we need a detailed representation of the application, as in figure 2
. Figure 3
contains a snippet of the view connector for the calendar application.
Figure 2. Calendar application UML diagram.
Figure 3. Calendar view connector.
The view connector performs several functions:
• It decides how application objects map to (target) objects and subjects. For example, it can define object instances of type Calendar and Entry as instances of CalendarObject.
• It determines how to compute the necessary attributes for target objects and subjects. For example, the view connector in figure 3 maps the calendarOwner attribute to the method getOwner() on Calendar.
• It identifies all security-relevant operations on application objects that map to target objects and associates them with the corresponding semantic actions in the object interface. For example, all methods on Calendar representing an editEntry action—that is, updateEntry(..) and addUserToEntry(..)—are labeled as such.
Although this simple example illustrates the access interface and view connector concepts, it's too small to show all of the benefits. For example, it implies a one-to-one correspondence between syntactic and semantic actions. For more complex applications, multiple application methods will typically map onto the same semantic action.
In a typical setting, an organization uses one access interface to abstract application details. This single access interface is bound to various applications, using one view connector per application. An organization-wide security officer, who need not be concerned with application details, manages the single access interface. The view connectors, written by application deployers, map application-specific concepts to the more generic concepts identified in the access interface.
Access control service
As figure 4
shows, we can view the access control service as a collaboration between three entities: a third-party authorization engine, an access interface, and the view connectors, each binding the access interface to a particular application. The view connector uses the access control decision functionality ( checkAccess
) each time an application event occurs that is annotated as a semantic action in the access interface. Conversely, the authorization engine can query the view connector through the access interface to retrieve the required object and subject attributes. The authorization engine then evaluates whether an access request conforms to the policy.
Figure 4. Access control service.
We implemented a prototype of our service in CaesarJ. This aspect-oriented extension of Java focuses on a better modularization of cross-cutting concerns into reusable components. Central to CaesarJ is the concept of a Caesar class ( cclass). The Caesar class offers two important features:
• it declares a set of collaborating nested classes, and
• it specifies not only what it provides, but also what it expects from the application to fulfill its contract.
The nested classes declared by a Caesar class form a collaboration and are implemented as virtual classes, which are similar to virtual methods. Each subclass of the encompassing (or outer) Caesar class inherits or overrides the virtual classes.
A Caesar class contract has two parts: a provided part, realized by the implementation, and an expected part, implemented by the binding. Composing both binding and implementation through mixin composition results in a deployable aspect (or weavlet). This subdivision into implementation and binding is only conceptual. The current CaesarJ syntax doesn't distinguish between the provided and expected parts of a Caesar class interface.
The support for modularizing cross-cutting concerns lies in the binding. CaesarJ supports the application of the decorator pattern (wrappers) and the declaration of point cuts analogous to AspectJ. 6
A point cut lets you select where in the application's execution to invoke the provided functionality.
We modeled the access interface as an abstract top-level Caesar class, as figure 5
a shows. This class declares two nested classes: AccessSubject
, in turn, declares a nested class AccessMethod
Figure 5. (a) An access interface in CaesarJ, an aspect-oriented extension of Java and (b) the access interface for the calendar application.
To implement an access interface for a specific application domain, we extend the AccessInterface
and provide the necessary object and subject interfaces. For expected attributes, we provide an (abstract) getter. The access interface for the calendar application might then look like figure 5b
We leave the choice of a specific authorization engine to the application deployer. The interface for the authorization engine (see figure 6
) is independent of the specific access interface bound to the application. It only uses the abstract AccessInterface
class. As you can see, the type of parameter m
depends on the object instance o
(that is, it's a dependent type). This guarantees that m
is a valid action on o
Figure 6. Authorization engine interface.
For the prototype, we implemented the authorization engine ourselves. Integrating existing authorization engines is straightforward: you can write an adaptor to translate the access request into a format the engine understands. The only assumption here is that the engine can cope with the common subject, object, and action abstractions, and with subject and object attributes. We could, for example, integrate the authorization engine with the Ponder 7
or Extensible Access Control Markup Language 8
frameworks with the access service.
In this adaptor implementation, we can choose to push all of the information that the authorization engine might need. Alternatively, we can use a lazy strategy, whereby the authorization engine pulls the attributes using callbacks when needed for evaluating an access request.
We implemented a view connector as a cclass
that binds the CalendarAccessInterface
to the calendar application as shown in figure 3
. ( Figure 7
shows a small part of this implementation.) It does this by extending the corresponding access interface. We distinguish two parts of the implementation:
• Wrappers (lines 2-14 in figure 7) implement the retrieval of attributes for both target objects and subjects. These attributes can be retrieved from the application object itself (using the wrappee construct) or declared by the wrapper.
• Pointcuts (lines 15-22) translate application-specific requests in terms of the access interface wherever applicable and invoke the authorization engine. Depending on the access decision, the call proceeds or the enginereports an access failure.
In the pointcuts, the AccessSubject (line 18) represents the subject that makes the access request. The view connector interacts with a session to retrieve this subject, which represents the active role for a user or process.
Figure 7. Calendar view connector.
CaesarJ doesn't provide explicit support for representing semantic actions. So, we implemented semantic actions as virtual classes in the AccessInterface
. Reifying the semantic action lets us keep the authorization engine interface generic. CaesarJ's family polymorphism and dependent types, moreover, render the interface typesafe. Table 1
summarizes how we use CaesarJ concepts to implement the access control service collaboration.
Table 1. Mapping of CaesarJ concepts to the access control service implementation.
Alternatively, we could implement the semantic actions as (provided) methods on the AccessObject
and invoke them in the binding instead of instantiating an AccessMethod
object ( figure 7
). Implementing the semantic actions this way requires invoking the checkAccess
method in every method's implementation. To avoid this code duplication, we could declare a generic pointcut in the AccessInterface
, which intercepts each provided method declared by an AccessObject
. We also should make provisions such that the application conveys the subject ( AccessSubject
) to the authorization engine.
In the prototype implementation, we implemented the view connector by hand. However, we should be able to generate the view connector's code given its descriptor.
To what extent did we fulfill our goal?
Modular binding to the application
Current systems can't support access control modularly. Rather, the application developer must enforce the access policy by hard-coding the access logic or embedding calls to an external authorization engine in the application. In the latter case, the developer must ensure that the application conveys all of the information the engine needs for the access request evaluation. Moreover, the application might need to translate the access request into terms the access engine understands before the engine is called. When using the CORBA Resource Access Decision (RAD) service (see the " Related Work
" sidebar), for example, the application conveys a protected resource name and access operation to the access decision function, which abstracts the object accessed and the action. Entangling access logic or calls to an authorization engine with business logic makes adapting the enforced access policy difficult.
We modularize the access control implementation through aspect orientation. Aspect orientation lets us define the abstractions required by the access logic as a view onto the application and bind these abstractions to the application modularly.
An open challenge pertaining to services that are transparent to the application is how to deal with exceptions or exceptional conditions originating within that service. In our case, an access denial could potentially occur at each method invocation. Consequently, the application can be left in an inconsistent state. Future work should reveal how and at what cost we can provide recovery/rollback operations.
A reusable authorization engine for enforcing expressive policies
Common authorization engines include Tivoli Access Manager's authorization server and the RAD service (see the sidebar
). Our approach adds to these engines' functionality by making explicit their expectations of the application without compromising their reusability. Thus, deployers can detect inconsistencies early. For example, they can verify whether corresponding view connectors define the mappings of all attributes declared in the access interface.
Middleware support for access control
Our system is an aspect-based subsystem that manages the separation of concerns between security-specific components (such as the authorization engine) and the application logic. Realizing this approach on state-of-the-art middleware technologies requires that the middleware provide support for retrieving application state and additional context information. Consequently, applying the approach to standard J2EE or COM+ environments requires trade-offs. Supporting access interfaces that only need information provided by the middleware platforms is easy. But, when the application needs a more expressive access interface, implementing the view connector might require that you modify the application code before it can retrieve the necessary information.
Application containers that incorporate aspect-oriented concepts, such as JBoss aspect-oriented programming ( http://labs.jboss.com/portal/jbossaop/index.html), are perfect environments for our approach. We've also implemented a prototype on top of Java Aspect Components 9
to demonstrate this, as we describe elsewhere. 4
Although in our prototype the access control service collaboration itself is reusable, we still custom-make the view connector for each application. An interesting question is whether the middleware should support these kinds of aspects by rendering view connector construction more straightforward and even configurable.
Although challenges remain, aspect orientation provides good support for access control modularization. We believe this modularization of platform services is a prerequisite to satisfying the varying and evolving requirements of today's applications.
A PhD grant from the Institute for the Promotion of Innovation through Science and Technology in Flanders (IWT-Vlaanderen) supported this research. This article is an extended version of a paper presented at the First Workshop on Aspect-Oriented Middleware Development. 10
We thank Riccardo Scandariato and the reviewers from both the AOMD workshop and IEEE Distributed Systems Online
for their comments and suggestions.
is a PhD research student in the Department of Computer Science at the Katholieke Universiteit Leuven. Her research interests include application-level access control and aspect-oriented software development. Verhanneman received her master's degree in computer science from K.U. Leuven. Contact her at DistriNet, Dept. of Computer Science, K.U. Leuven, Celestijnenlaan 200A, B-3001 Leuven, Belgium; email@example.com.
is a professor in the Department of Computer Science at the Katholieke Universiteit Leuven. His research interests include software security aspects, including security in operating systems and middleware, security architectures, application security, secure programming languages, Java and .NET security, and software interfaces to security technologies. Piessens received his PhD in computer science from K.U. Leuven. Contact him at DistriNet, Dept. of Computer Science, K.U. Leuven, Celestijnenlaan 200A, B-3001 Leuven, Belgium; firstname.lastname@example.org.
Bart De Win
is a postdoctoral researcher in the Department of Computer Science at the Katholieke Universiteit Leuven. His research interests include security engineering, access control, aspect-oriented software development. De Win received his PhD in computer science from K.U. Leuven. Contact him at DistriNet, Dept. of Computer Science, K.U. Leuven, Celestijnenlaan 200A, B-3001 Leuven, Belgium; email@example.com.
is a postdoctoral researcher in the Department of Computer Science at the Katholieke Universiteit Leuven. His research interests include middleware, dynamic customization of distributed systems and services, collaboration-based design, component-based design, and aspect-oriented software development. Truyen received his PhD in computer science from K.U. Leuven. Contact him at DistriNet, Dept. of Computer Science, K.U. Leuven, Celestijnenlaan 200A, B-3001 Leuven, Belgium; firstname.lastname@example.org.
is a professor in the Department of Computer Science at the Katholieke Universiteit Leuven. His research interests include software architecture for distributed systems, aspect-oriented and component-based software development, adaptive middleware, security solutions, and secure software. Joosen received his PhD in computer science from K.U. Leuven. Contact him at DistriNet, Dept. of Computer Science, K.U. Leuven, Celestijnenlaan 200A, B-3001 Leuven, Belgium; email@example.com.