General-Purpose Authentication and Authorization for Webapps, Page 2
Part of the authentication process is to define the "roles" of the authenticated user. Roles fulfill the same purpose as what Unix old-timers (such as myself) call groups. They allow authorization to be granted or denied en-masse, to entire groups, rather than one user at a time.
Having established who we're communicating with, verifying this identity, and protecting the communication from casual interception, we finally come to the point of determining what this user is allowed to do. This is authorization, and it is often applied at several different levels:
A single class or related group of classes providing a service to an application can be considered a component. The most straightforward type of authorization is to grant or deny access to entire components, based on group membership. An example would be saying all members of group "customers" have access to the "DisplayAccountBalance" component.
Once a user has access to a component, what can they do with it? This is handled by defining Operations, where the set of operations available depends on the component being secured. For example, a persistent object, stored in a database, the available operations might be create, update, delete and read.
Securing an entire component may be too coarse-grained for many applications. By implementing a simple interface, components can become InstanceSecurable. Each instance of the secured class can then have permission assigned independently. An example might be a database factory component - if the name of the database were used as the identifier, security could be assigned to allow only users belonging to the appropriate groups access to certain databases. Of course, this is a simple example.
There is one even more detailed level of authorization that is sometimes required. If the specific state of an object is one of the factors determining whether or not that object is allowed, then invokation security is required. This allows the state of the object to be queried, and compared to one or more rules. For example, if a user is allowed to access a component called 'Account', but only if the account balance is over zero, a rule is set up to reflect this, and each access to the 'Account' component is checked through this rule. This level of security is also applicable to "row-level" database authorization, where the actual contents of the data determine the security for that item - an example of this is a user only being allowed to update a record he or she created.
IOC and security
Keel employs a concept (inherited from the underlying Apache Avalon framework) called "inversion of control". A popular design pattern for component architectures, IOC refers to the approach where the container "drives" the components, supplying them with all they need to operate, and leading them through their execution lifecycle. The container always calls the component, never the reverse. If a component has dependencies on another component, it requests an instance of the needed component from the container. The fact that the container is the 'single point of access' makes it easier to implement a pervasive security structure such as Keel's.
Interfaces and swappable implementations
Many projects involving web-applications are not a "clean start" - they must integrate in some fashion with existing applications, this often includes making use of an existing application security mechanism. Frequently this will include a 'single sign on' feature, making use of authentication information such as login and password from the legacy application (or possibly from the underlying operating system itself). JAAS helps here, as often all that is required is writing a new LoginModule. Legacy-based authentication is then often combined with customized authorization - starting from the basis of the three tiers described above (component, instance and invokation). The question then becomes "how do I implement part of the security system as custom code, while still maintaining the benefits of using a standards-based framework. We could of course just copy the standard code and modify it to suit, but this throws away one of the benefits of an open source solution - that the entire developer community shoulders the burden of maintenance collectively. By creating an orphan version, we take this responsibility on alone. This is why Keel is called a meta framework - it is designed to connect multiple frameworks and components, allowing specific portions of functionality to be 'swapped out' and replaced with custom code only where needed.
All of the security functionality we describe in this article are in daily use in web applications, and specific examples can be seen in the open-source Keel meta framework. We've taken a very fast tour at a high altitude over some of the major topics of securing a web application - as you can imagine, it's a topic you can go on learning about for a long time, and one which is sure to continue to evolve in the future.
About the AuthorMichael Nash is the president of JGlobal Limited, a software development, consulting, training and support company specializing in open source Java technologies. He is also a core developer of the Keel meta-framework, the author of two books and a number of articles and papers about next-generation web-application development with Java, and a member of the JSR-127 (JavaServer Faces) Expert Group. He can be reached at firstname.lastname@example.org.