hal helm's logo  
home Home

training Training

writing Writings

code Code

tutorials Tutorials

newsletters Newsletters

consulting Consulting

Hal Helms logo
hal.helms

What Students Say...

"Really, the class was outstanding. My confidence level is up 100%. I just got finished showing Wireframes and DevNotes to the gang in the office, along with a quick overview of Fusedocs. We are a VERY happy group of developers. Most of them have had some exposure to Fusebox and seeing it in the context of a development lifecycle has generated a lot of enthusiasm. We're already seeing significant performance gains. It's going to take some time to get everyone up to speed, but there is a sense of a turning point in the war." - Oliver E

"Training isn't really the right word. Your class was as much mentoring as training. I wish you would train other trainers!" - Jose G

"I really like your casual approach and the way you keep everyone involved. Well done!" - Roger R.

newsletters section

Rethinking Roles-based Security

Chances are good that if you're using security on your applications, you're applying some form of roles-based security model. The main feature of this model is that access is restricted to certain groups or roles. Such security schemes often have the user linked to a comma-delimited list of user groups they belong to, with such a list being placed into a persistent scope. A sample list might look like this:

<cfset session.currentUser.userGroups = "admin,supervisor" />

The challenge mechanism then may look like this:

<cfif ListFindNoCase(session.currentUser.userGrousp, aRequiredPermission)>
   Come right in
<cfelse>
   Not on my watch, pal...
</cfif>

ColdFusion MX supports this by providing an access attribute for the <cffunction> tag that works in conjunction with the <cflogin> tag to automate this scheme. I want to suggest some other aspects of security for environments in which change is the norm. In the process of exploring a solution for this problem, we may learn a lesson in better software design.

First, what's wrong with roles-based security? Initially, not much. It's simple to implement and it's effective. It does require you to place individuals in a user group, but this is common practice when adding a user into the system. When done, we have a direct mapping between the user group and access to protected areas of code.

But the notion of "direct mapping" poses a subtle problem--one that often lies hidden, only to reveal itself when we least want or expect it to. To uncover the problem, let's perform a few thought experiments. First the situation: we have three user groups defined in our system: RegisteredUser, Supervisor, and Administrator. When a user is registered with the system s/he can be place in any or all of the user groups. (This may be a good deal simpler than the environment you're operating in, but the principles for roles-based security remain the same.)

Andy, Bob, Carmen, and Dawn are new hires and are placed into the following user groups:
Andy: RegisteredUser
Bob: RegisteredUser, Administrator
Carmen: RegisteredUser, Supervisor
Dawn: RegisteredUser, Supervisor, Administrator

Now for the thought experiments:

1. A business rule tells us that junior new hires like Andy (with only a RegisteredUser role) have limited access to the system for an initial, probationary three month period. This does not apply to Bob, Carmen or Dawn. If we have a direct linking between user group/role and access, we have a problem. We will need to modify our challenge code so that it tests both for RegisteredUser and performs a DateDiff() against the hireDate and the current date. Must we put Andy in a special user group during his probationary time period? That causes problems unless we're operating on a small scale where we have control over all aspects of code and security.

Further, you can imagine that over time, the challenge code could grow to be more and more complex. And let's say we've implemented separation of logic and presentation (perhaps using the Model-View-Controller pattern) that our fundamental business logic code (including data persistence) serves more than one application--each possibly with their own sense of user groups and special logic. Is there no solution for the spaghetti code that is bound to follow?

2. What happens if the situation occurs where users from other systems--not in our user database--want to use parts of our system? All that we receive is a user validated on their home system with their user groups. It's unlikely that their user groups will match with ours. Adding these users into our system may be impractical and certainly presents a problem of duplicated data with synchronization issues. How can we give them access to the parts of our application we want them to have?

3. What happens if an existing user group is to be granted new permissions? Say that previously only administrators could delete a user, but now we want supervisors to be able to delete users. Note that we don't want to turn supervisors into administrators--we just want to extend their permissions.

4. What if we wish to promote or demote a specific user? Perhaps one of the RegisteredUsers is a team lead and is to be given additional access--but again, without changing their user group?

5. Your application is so successful that your company decides to sell it to others. But what user roles will these new customers have--and what access rights should be assigned to them?

These situations are similar in that they require that we go outside the prescribed security model in order to solve the problem. When we find ourselves writing such ham-handed code (called a "kludge"), we're actually getting important information that our model does not match sufficiently well with the real world. When we find this, the best solution is often to re-examine the model to see where we've gone wrong.

In the case of security, the problem is the direct mapping between user group/user role and challenge code granting or denying access. We can solve this problem easily if we separate the idea of permission from a user role. Let's introduce an analogy that may clear things up. Imagine that, instead of dealing with code and permissions, we're dealing with an office that has doors. Some of these doors have locks on them and a key is required tothem.

Locking doors are in no way tied to specific user roles: they were created by the manufacturer. The manufacturer also provided a key to these doors. It is up to the security officer of the building to determine to whom to give keys. Now, for the sake of convenience, it may be that we will give the key to the executive washroom to all members of the Executives group. But we also want to give access to the cleaning company. This presents no problem for the door follows a simple rule: if you have the right key, you can enter.

We would do well to adopt a similar scheme. When we build our code, we determine that areas should be locked. Instead of a key, a specific permission is required to use the code. Our challenge code follows a simple rule: if you have the right permission, you can enter.

But surely, we don't want to have to assign permissions to each person? No. One way to automate the process is to let everyone that is in a user group have certain permissions mapped to them at run time. But all this means is that a tedious process of associating individuals with permissions is automated--it does not change the fundamental nature of that process.

When a user reaches a locked door (to extend the analogy), they are interrogated for a permission (not a user group). In order to get that permission, they must first have gone through a "permissions binding" phase which assigns runtime permissions to them. This component needs access to a map from which it can determine that some aspect of a user (user group, SSN, name, etc.) maps to one or more positions. As an example, the map may say that Administrators maps to addUser, editUser, deleteUser and createUser while RegisteredUser maps to editUser only.

Let's review the five thought experiments and see if this improves things:

1. Andy's special case is handled in the permissions binding phase by removing certain permissions that he would have had by virtue of being a RegisteredUser. Depending on what the special case is, the code involved could be quite complex. At challenge time, though, the only thing that matters is the possession of permission--regardless of what rules the permissions binder used to assign those permissions.

2. Users who aren't part of our database may not have user groups that match up with ours. But the permissions binding doesn't require them to be in one of our groups--only that some aspect of that user that is provided to us can be used to determine permissions. In this case, we are given the user group of the foreign user, which we can map to individual permissions.

3. Adding permission to an existing group involves only a change in the permissions binding table, since all permissions binding is done at run time.

4. Since the use of user groups is merely a convenience (as far as permissions go), we can add to or take away from the user any specific permissions we wish to. Again, this logic would go in the permissions binding code.

5. Since no direct mapping is made between user groups and challenge code, we don't need to know prior to runtime how to bind permissions to users.

How you build a permissions binding mechanism depends on what framework (if any) you have in place. In Fusebox 4, each circuit and each fuseaction has an optional attribute called "permission". These attributes can be used by someone writing a security plugin to ensure that the user's available permissions matches the required permission for circuit and/or fuseaction.

For example, here's a circuit.xml.cfm file from a sample FB4 application:

<circuit access="public" permission="useQuizBuilder">
   <fuseaction name="deleteQuiz" permission="deleteQuiz">
      ...
   </fuseaction>

   <fuseaction name="viewQuizzes">
      ...
   </fuseaction>
</circuit>

Fusebox itself does not apply any security check, but does make the values set in these attributes available to the programmer. It then becomes a simple matter of a few lines of code to write any challenge code you wish. For example, we might write a plugin to ensure that to use any fuseaction in the circuit, the user must have the useQuizBuilder permission. If the user wants to delete a quiz, s/he can now be challenged for the deleteQuiz key.

The rules for permission binding can be stored and gotten from database table(s), XML files, .ini files, through the use of web services, etc. For more info on Fusebox 4, come to beta.fusebox.org.


Computers are incorporated in modern ice cream vending machines to enhance their functionality. Ice Cream Vending machines are manufactured by many companies. Your competition will try to overcome all requests for high-tech ice cream vending machines and credit card acceptors

At the beginning of this newsletter, I said that we may be able to learn something about designing better software. I think we can. The problem with the direct user group-to-challenge code so often employed is an example of a much larger class of problems in which two components are tightly bound together. Tightly bound components tend to be fragile, breaking with changes in the environment and requiring kludge code to keep the system running. The solution for the security model was a complete separation of one design time component (user groups) with another (challenge code). The two are dynamically bound together only at run time. By following a similar course for similar types of problems, we can help ensure that our code is robust, adaptive, and long-lived.


Work is underway on a Discovering Fusebox 4 book due out in the Fall. Once the date is set, info on the book will be posted at techspedition.com.

Interested in Fusebox 4 training? If so, start planning on coming to Las Vegas August 27-29. John Quarto-vonTivadar and I will be holding a three-day class on Fusebox 4. The class is held Wednesday through Friday. On Saturday and Sunday, we're hosting the Fusebox conference. The conference will be less formal than previous years with primary concentration on some of the advanced aspects of Fusebox 4. (There's a lot in there!) The cost hasn't been nailed down yet, but it will be less than $100. If you're interested in coming to the training class and/or the conference, please drop me a line at hal. Students attending the class will receive free registrations to the Fusebox conference.

There are only a few seats left for the June 23-27 "Java for ColdFusion Programmers" class in the Washington, DC area. For more info, got to halhelms.com

©copyright      designed by in-tuition.co.uk
hal helms' personal site Updates

Computers are incorporated in modern ice cream vending machines to enhance their functionality. Ice Cream Vending machines are manufactured by many companies. Your competition will try to overcome all requests for high-tech ice cream vending machines and credit card acceptors

teamallaire.com v 4_3