Simplify application development with a ready-to-use centralized user management system You are a developer embarking on an ambitious project to create the grandest and most powerful visionary system in the world. After designing the most amazing architecture and laying out the most meticulous plans, you start to assemble the necessary components to begin the project. But which module do you deal with first?Discounting utilities and similar applications, most systems need to identify their users. Without this ability, a system would be incapable of ensuring its own security. Further, it would not be able to provide appropriate access levels, personalized services and functions, or usage tracking. User identification proves critical, especially in enterprise systems, systems built for businesses, and generally any system that needs to have accountability for its users. Unfortunately, it is also the most often overlooked feature during systems development.This article describes Tapestry, a centralized user management system that allows developers to reuse the same set of users for every application system they build. Tapestry is a work in progress. For more information, visit the Tapestry Website. After reading this article, you will be able to:Understand why it is easier and more productive to employ a centralized user management system compared to other schemesUnderstand what Tapestry provides for you as a developerLearn more about Tapestry’s design and architectureUser managementWhen creating application systems, whether client-server or Web-based, the first module to be developed usually concerns user management. Some application systems hook themselves with the operating system or database management system to provide this function. Others develop their own user management and tracking capabilities. Indeed, no single converging standard exists for user management because most are proprietary and not usable beyond similar platforms or systems.User management’s ubiquity underlies its importance: every system needs to create and manage users, to control access, and to configure who can use or administer it. The user management module represents one of the most necessary modules of any application because an application’s whole premise centers on its value to users. Naturally any module with such critical and essential functions needs to be robust and fail-safe. An application system without a running user management module is for all practical purposes crippled.Considering its importance, it is quite surprising to realize that most, if not all, applications create their own user management system, often from scratch. From the arguments given above it would be logical to assume that reuse of a common user management module (see Figure 1), either built new or as a centralized user management platform, would be a better choice for development in a new system. Besides reducing development time, the developers of the new system would have the advantage of a tried and tested user management module to rely upon.The advantages of a centralized user management system include: Development time is reduced because there’s no need to reinvent the wheel.A ready-for-deployment user management system allows developers to concentrate on the business application.In an enterprise environment consisting of many systems, each system does not need to manage its own set of users; a separate system is dedicated to managing all its users, which allows for separation of tasks.A single sign-on system in which all applications that use the separate user management component would have one single login and password. User management and security authentication would be cleanly and modularly decoupled from the application itself.However, separation of user management from the application logic proves more difficult than it looks. The initial euphoria stemming from the benefits will soon bring doubts as to how realistically it can be achieved.Development approachesSo how can we create a centralized user management system that circumvents the issues highlighted above? There are three approaches:Ground-up approachFramework approachCentral server approachThe ground-up approachWith the first approach, we build the user management from the ground up by embedding it within each system. Ground up represents the most common method, with each application system possessing its own user management. One drawback: the different application systems cannot communicate user information with each other, resulting in isolated islands of automation. Application systems work perfectly well with their respective user management modules because they are tailored specifically to them. However, integration is a major issue, which frequently plagues most enterprises. The framework approachThe second approach uses frameworks, an abstract collection of software objects dedicated to solving a class of problems through a flexible and extensible architecture. It is prefabricated software that can be reused, extended, or customized for specific computing requirements. Frameworks have no real infrastructure, so building new systems can be as flexible as necessary. However, the framework approach takes some upfront work. After all, nothing concrete has been built yet, although a significant amount of infrastructure has been laid. In the end, overall development time is reduced and, because the framework standardizes access to the user data, there is a certain level of uniformity. Frameworks are usually tried and tested as well.However, frameworks are white-box tools and the reuse favors extensibility, not direct usage. As such, you will still need to build a user management system, although it will move along faster. You’ll still need to understand its internal structures, and the learning curve can be steep.The central server approachThe third approach employs a central server, actually the single-server, multiple-client approach widely used for client-server systems. In this case, a central user management server controls all user information, with client systems requesting the information from the user management server. The advantages: the application system is decoupled from the user management module, and user management is controlled at a single point of access. Moreover, it is much easier to develop with a central server approach since the developer does not need to create the user management module at all. However, because the application system is decoupled from the user management server, it is necessary for the user management server to provide the correct user data to each application system that accesses it — not an easy task. It’s difficult because user data is often tightly coupled with the application system itself. The ability of a user to access a system can be highly dependent on the existing user types.Another problem: a user in a particular application system possesses attributes completely different from users in other systems, not to mention different access rights. As an example, consider a scenario in which the initial environment includes a single user management system and three application systems. Moreover, we’ve solved the previous user/application logic coupling problem. However, by adding a fourth system, we will throw a monkey wrench into the delicately balanced ecosystem (see Figure 2). The user attribute needs and user/application coupling of the fourth application system will render the user management system useless, unless major changes are made to the system itself, which will cause repercussions to the other three applications. This will in turn cause negative feedback rendering the system unstable.The industrial factory analogyAs an analogy, consider the construction of industrial factories. The main component of every factory is the power generator. Every factory needs different power supplies, depending on the type of factory, its location, and the type of equipment used. Despite the differences, some form of power supply is always needed. In an industrial zone that contains many factories, power generators prove critical to their continuing operation. Imagine that you are the industrial zone operator responsible for providing power to all the different types of factories in the zone. How would you go about doing this? The ground up approach would be to build a power generator for every factory in the industrial zone, specific to the needs of each factory. In this case, to build each factory, the owner must find out his needs and build the power generator. While it’s a flexible choice, it can prove difficult to manage and maintain because each generator type would require its own spare parts and fuel types. Besides, building a new power generator for each factory is very time consuming and unproductive. The time spent could be used to concentrate on building the equipment used for manufacturing — the factory’s real purpose. The bottom-up approach represents the traditional approach to software construction.The framework approach is equivalent to building components that allow you to build power generators. This ensures certain uniformity in building generators that are easily maintainable, and all of which uses the same fuel and parts. In addition, you can build generators quickly, yet be able to tailor each generator to the specific needs. Still, each factory must build each power generator itself. (Of course you can also buy the power generators from suppliers and customize it to your needs, which, for the purpose of this mental exercise, is the same as what has been just described.) Frameworks represent the currently popular component-based approach to software construction.As for the central server approach, you as the industrial zone’s operator would build a powerful and robust power generator to supply power to all of the factories in the zone. This is the most effective means of managing the power supply to the factories; you need to take care of only one generator, one type of fuel, and one set of parts. At most, for power supply fail-over and load balancing, you can build two identical generators. Dependency is decoupled and based on interfaces. On the downside, each factory must conform to the standards of a single power generator — a very restrictive proposition. Returning to the discussion on user management and comparing all three approaches, we see the pros and cons of each software development model. What is needed is an approach that combines the flexibility of ground-up development, the easy assembly of standard components, and the loosely coupled interfaces of the central server.TapestryThe Java-based Tapestry Web services provide a user management system that address the requirements outlined above. It is defined with WSDL and SOAP, and published using UDDI. Tapestry clients do not need to be Web-based, as they can be activated via any SOAP-compliant client running on any platform. Further, it employs HTTP to transport the SOAP information to and from the client, which in turn is translated by the SOAP router to access the actual services.What does Tapestry do?Tapestry uses three mechanisms to provide the best-of-breed features from the three approaches above, while solving the problems stemming from each approach. Firstly, Tapestry is a Web service. Requests are made as SOAP envelopes encapsulated in HTTP requests to Tapestry, and returned as SOAP envelopes encapsulated in HTTP responses to the application systems. Therefore application systems that use Tapestry do not necessarily need to be Web-based or even Java-based, as long as they can understand SOAP. This effectively decouples the application systems from the service itself. In other words, there is no need to develop any user management system, or even extend from it. Secondly, Tapestry employs a package of dynamically generated base Java classes that represent the user data. A developer-modifiable configuration file dynamically generates these classes. Coding is not necessary or even possible for the base classes. This way, configuring for new applications is easily done, as long as the user’s older attributes are not removed. This plays on the strength of component frameworks: Tapestry is an open and flexible system. Classes are dynamically generated to hide away the complexity of coding the base classes. It also reduces the probability of errors in the code.Thirdly, Tapestry uses a role-based access control (RBAC) system that defines users by the roles they play. Each user plays one or more roles in Tapestry, and each application sees a different aspect/role of a user. As with the base classes, the roles are dynamically generated from a configuration file. Moreover, roles are closely tied with the application system. For example, in a human resource system, a user plays the role of an employee. A new application system has users as buyers, so the user plays both roles even though the user remains the same person. Roles can also be used for integration with existing systems to access their user management modules. Roles can be used as an abstract of the user login for a particular system. In the above example, you can use Tapestry to abstract the role of the user as an employee in a human resource system as well as a buyer in a B2B trading portal. His identity remains the same, but he now plays two roles — the data contained in both roles are different and used separately, but the login and the management of the user remains the same. The roles do not conflict because they are isolated from each other, and the user that plays the role links them. This way, each application is coupled with the user, yet decoupled from the user management system. This mechanism results in components that can be assembled into Tapestry without disruption of the existing infrastructure.In one important feature, Tapestry can be deployed immediately to provide a centralized user management system. Although it provides the features of the central server approach, it does not have any of its associated problems. It can be configured easily with XML, and developers can use this to develop and deploy application systems immediately. Note that Tapestry only provides server-side user management services; developers will still need to write application clients to access the services. Tapestry user management servicesTapestry’s user management services are based on the RBAC Reference Model in the Proposed Standard for Role-Based Access Control. Tapestry assigns users to roles and assigns permission to those roles. The basic elements in Tapestry are:User: a person accessing the systemRole: a job function within the context of an organization, with associated authority and responsibilitiesObject: an entity that contains or receives informationOperation: a processing function that executes on behalf of the userPermission: an approval to perform an operation on an objectSession: a mapping of one user to possibly many roles (implemented as a token)Group: an aggregation of users and groupsFigure 3. Tapestry’s user management componentsTapestry’s architectureTapestry Web services transport SOAP envelopes through HTTP. As a result, a major component in Tapestry is the Web server, which fronts the Web services.Three different types of users access Tapestry. First is the application or the user of the application. This user calls the Tapestry Application Service to perform actions including authentication, retrieving roles assigned to a user, and permissions attached to a role. The second is the application administrator who administers all user information including role assignment and user creation. This user calls the Tapestry Admin Service. The last type of user is the Tapestry administrator, who controls all matters concerning Tapestry and the roles played by a user, including role creation, granting permissions to roles, and creation of role constraints. The Tapestry administrator calls the Tapestry Security Service. Tapestry users access Tapestry services through a Web server that will redirect them to a SOAP router. The Web services then call the Tapestry core classes to perform the actual work. The current implementation of Tapestry uses JavaBeans as its core classes. Later releases are expected to employ Enterprise JavaBeans. Finally the core classes stores their data in an object data store.Tapestry Design ConsiderationsLet’s review Tapestry’s design considerations:Role constraintsTapestry implements three types of constraints on its users and roles assignments: Static separation of duty (SSD): This constraint allows a user to be assigned to a role only if that role is not mutually exclusive with any other roles that the user plays. The SSD avoids a conflict of interest for the same user. For example, a user who plays the role of a teller in a bank must not play the role of an auditor.Dynamic separation of duty (DSD): Sometimes it is desirable for a user to play multiple roles with conflicts of interest. For example, a user who is an employee can also be an HR manager. In cases such as these, Tapestry applies the DSD constraint, which specifies a user can hold either one of these roles but not both simultaneously. In the above example, a user can be an employee or an HR manager, but cannot be both at the same time.Cardinality of roles: Some roles can only be played by a certain number of users at any one time. For example, there might be a number of HR department users, but only one can be the leave clerk at any given time. A user can play such a role as long as the number of roles allowed is not exceeded.Role constraints are checked each time roles are activated or assigned.Role hierarchiesIn Tapestry, roles are hierarchical with an inheritance relationship among them. Role hierarchies are managed in terms of user containment relations: role r1 contains role r2 if all users authorized for r1 are also authorized for r2, meaning a user with role r1 also possesses the privileges and permissions of r2.The standard recognizes two types of role hierarchies: general and limited role. General role hierarchies provide support for multiple permission inheritances and user membership among roles, while limited role hierarchies do not. The role hierarchies are affected by the role constraints described above. For the separation of duty, if two roles are mutually exclusive, their child roles are also mutually exclusive. In the role hierarchy example given below, if the technical and nontechnical roles form an SSD set, then a user cannot play the role of a manager and an operator under whatever circumstances. Similarly, if they form a DSD set, then a user cannot play the role of a manager and an operator at the same time, though he can play those roles at different times.Cardinality is affected in the same way. If the cardinality of the role staff states that there can only be 10 users who play that role at any one point in time, then the sum of all the active child roles (technical, nontechnical, manager, clerk, operator, or supervisor) cannot exceed that number. The eleventh user can only play the admin, customer, VIP customer, and supplier roles.As stated above, Tapestry allows multiple role inheritance. However, Java does not permit multiple inheritance except through interfaces. Because interfaces do not contain data, it cannot be used to model role hierarchies. To get around this obstacle, Tapestry employs directed acyclic graph (DAG) to model the hierarchy. A DAG is a well-defined graph that has edges that allow only one-way traversal. A DAG, as the name implies, cannot contain cycles. An example of a DAG is the role hierarchy described in Figure 4.From Figure 5, we can see that a user playing the role of a clerk also plays the roles of nontechnical, staff, and user. To find the containing roles, a depth-first search traversal is made and each role is stored. The result of the traversal then becomes the roles the user plays. Note that this applies to active roles in a session, not a user’s permissible roles. Therefore, a user can be assigned the role of a clerk as well as an operator. When a session is created, and a role is activated, the role hierarchy will provide the roles that the user session contains. Token authenticationTapestry implements a simple token authentication scheme for user authentication. It’s not encrypted by default. However, the design allows for different authentication schemes through the use of interfaces. The mechanism itself is based on a simple handshake and acknowledgement protocol. The sequence of the events is as follows:The user logs into an application with a user name and password.The application retrieves the username and password and sends it to Tapestry.Tapestry calls up an authenticator from the AuthenticatorFactory and verifies if the user is valid. If it is, it will create a token, send it back to the calling application as a SOAP envelope, and store the token object into a token repository. If it is not a valid user, an invalid token is returned. The default authenticator verifies the existence of the user and the correctness of its password from a database.The token contains the user ID, a status field (valid or invalid), and an expiry time.Each subsequent call to Tapestry requires the token to authenticate the call. The sequence is as follows:The received token is first checked for expiry time. If the expiry time is exceeded, the token is invalidated and returned. No further action is taken.The received token is compared against the token repository. The token repository is implemented as a splay tree for optimal retrieval efficiency.If the token is not valid, the processing is abandoned. Otherwise, the call is processed.Users, groups, and rolesA closer study of the Tapestry model reveals an ambiguous usage of roles and groups. Clearly roles are a form of group that aggregates a number of users for the purpose of access control. For example, users who play the role of a clerk form a group that has the permissions of a clerk. So what function does the group concept play in Tapestry since roles already perform a group’s most obvious function?A key difference is that groups in Tapestry do not grant access control, that is, they do not represent an aggregation of users with similar permissions towards certain objects. Groups aggregate users and other groups, but the users do not necessarily need to have the same roles. For example, a manager and a clerk can belong in the same group without compromising security and access control, simply because belonging to a group does not grant permissions. At the same time, groups do not play a role, though they can be hierarchical (groups can contain subgroups).How are groups used if not to aggregate access control? Tapestry defines groups as a user and group collection, created by the users to conveniently aggregate users and groups for usage of an application. The actual membership and use of a group is defined by the application that creates and uses it, not by the administrator. There are no special rights for each member of the group — the membership is arbitrary and defined by the application itself. A mailing list serves as an example group. Each member of a mailing list does not have special access rights to any part of the system. The mailing list conveniently aggregates a number of users for the sole purpose of sending emails to them.Roles are a powerful and flexible concept that allows Tapestry to segregate user functions from the user itself. Using the same scenario as seen in Figure 2, where there are three existing applications that use Tapestry and a new system is added, we can see how roles can solve the problem flexibly. The user plays a different role in each system, and the role contains the information that relates to that particular system.For example, the user plays the role of an employee in the Human Resource System with information like department, salary, reporting manager, and amount of leave outstanding. If a new system is added into the equation, in this case a Content Management System, we can just as easily add a new role, publisher, in this example. This way, user information is separated from role information, yet they are linked sufficiently to allow centralized control.Figure 7 : Adding a new application system into TapestryFor more flexibility, Tapestry implements users as interfaces, meaning the defined user is not fixed and is generated for each implementation. From a practical perspective this is a necessity: there are rarely two implementations that possess the same data kept for its user set.Additionally Tapestry implements its data set as Java objects in an object-oriented database. That is, Tapestry stores the objects in the database instead of converting them into records stored into a relational database.The user and other implementation-configurable classes are auto generated for each implementation. If it were stored in a relational database, the entire system would need to be shut down, the database tables recreated, and the data itself migrated to the new tables. By using an object-oriented database instead, the classes generated are instantiated as objects, populated with data, and stored in the object-oriented database. Changes to the classes due to the change in requirements are not as disruptive as in a relational database.User-session-role bindingTokens implement the session as described in the architecture above. Users are tied to a token upon initial login, and active roles are subsequently tied to these tokens as well. Each successful login will have a token/session that eventually contains a number of active roles. Note that roles are still bound statically to users, but tokens define a user’s currently active role. This is used effectively during the definition of role constraints.Role constraints define the separation of duty constraints (SSD or DSD sets) on the various roles in the system. Each constraint is implemented as an object with a list of roles that form either the SSD or DSD set, as well as a cardinality that describes the maximum number of roles that can be active at the same time. The role constraints are checked each time roles are activated or assigned.Permissions, objects, and operationsOne major purpose of a user management system is to control access to applications by users of the system. As described above, Tapestry provides a centralized means of managing users through a Web service mechanism. This effectively segregates the application from the user management system; the application becomes the client and the user management system becomes the server.As you will realize, permissions, objects, and operations are tied in with each individual application. For example, each application will have its own set of transactions and resources (objects) and its own set of operations on those objects. As a result, the permissions that map the objects to operations must be flexible enough to support such diversity. Note that there is no way Tapestry can enforce access control for an application should it choose not to follow Tapestry’s permission access control. This is unavoidable since the application and the mechanism that provides the access control are separate entities.ConclusionMost application systems need user management, but it’s generally ignored during the design process. At the same time, enterprises with more than one system do not usually have any unified way of managing their users because each of the systems is added in without forethought on how the same user can be managed.Tapestry solves user management. It’s a Java-based system built as a set of Web services based on open standards. Tapestry is a centralized user management system decoupled from the application systems. It provides extensibility and flexibility through dynamically generated classes and uses role-based access control to tie the user to the application system.With Tapestry, developers who wish to develop more than one application system with the same set of users can be ensured that the user management aspects of the application are properly handled. Tapestry also allows single sign-on for applications that use it, as well as any existing application that adapts itself to Tapestry. As a result, developers can concentrate on the application logic instead of worrying about how to integrate with existing applications. Tapestry provides a niche but key need of enterprise software developers for a reusable centralized user management system.Tapestry is currently a work in progress, and only a subset of the services described here have been implemented. Readers who are interested in learning more about Tapestry are encouraged to visit the Website. Web DevelopmentJava