Model Glue Event Security Using Broadcasts and Results

When building web applications, you will inevitably need to provide secure pages or an entire area of your application for users and administrators. For my most recent Model Glue project I wanted to define a common approach to securing all access to the admin area with the exception of login pages. After several failed attempts at universal security, I decided that securing events is best achieved through explicit broadcasts and results, with a minimal amount of logic handled within the controller. Here's a simple example. Let's presume that the default event for my admin sub-application is "admin.home", here is my event listener declaration. <event-handler name="admin.home">
<broadcasts>
<message name="loginRequired" />
</broadcasts>
<results>
<result name="noValidLogin" do="login.go" redirect="true" />
<result do="layout" />
</results>
<views>
<include name="content" template="home.cfm" />
</views>
</event-handler>
The loginRequired has a listener defined by the following. <controller name="SecurityController" type="admin.controller.SecurityController">
<message-listener message="loginRequired" function="verifyLogin" />
</controller>
Finally, in my SecurityController, the verifyLogin method looks like this. <cffunction name="verifyLogin" access="public" returnType="void" output="false">
<cfargument name="event" type="any">
<cfif not getSecurityService().adminLoggedIn()>
<cfset arguments.event.addresult("noValidLogin")>
</cfif>
</cffunction>
In a previous application I chose to use event.forward() within my controller to redirect the request to the login event. Although this works, it is, in my opinion, better to use addResult and have Model Glue handle the redirection. Although the xml is more verbose, I really like that the intent of each event is clearly defined. Which provides a nice roadmap for any other developers that may take over the project.

8 responses so far ↓

Dan Wilson - Jun 5, 2008 at 5:31 PM

I agree Paul. The way you have this structured makes it really easy to make a security review. As long as all secured events have the message configured for broadcast, then security is in place. This is way better architecture than whitelisting a set of events, or by relying on convention, or any other such magic_string methodology.

Depending on how it all worked, I might go ahead and use the event.forward.... but you are right in saying it is clearer and more easily understood by being more explicit.

DW

salvatore fusto - Jun 6, 2008 at 4:29 AM

hi,
in the real world, you can have many types of users each with his own roles to be able to go only to some areas of the app: every event can pass an argument containing
a list of roles compatible with it, so in the onRequestStart of your login Controller you can test if the logged user has the grants required to fire that event and then
continue or rediretct to a login form or to other actions.
hope been clear
regards
salvatore

Paul Marcotte - Jun 8, 2008 at 11:34 AM

Hi Salvatore,

I agree that using a white list as you describe is a fine design choice. My preference would be to announce the type of privileges required for the event like, &quot;requiresAdminRights&quot; and have the controller return results like, &quot;noLogin&quot; or &quot;accessDenied&quot; and have model glue process the re-direct.

In the end there are many ways to secure you application and it really comes down to a matter of preference.

Justice - Jun 17, 2008 at 9:26 AM

I am using EventGuard (http://eventguard.riaforge.org/), with some small modifications. I added the ability to add secure or public events with wildcards, so a single entry can add security to all admin.* events. I find it really easy to use, check out the config for it (single XML entry that goes in coldspring adds security for all events)

http://pastebin.com/d3222e658

Granted, EventGuard is not as evident while constructing events or looking at your event config, but its working out great for me thus far.

Bill - Oct 14, 2008 at 4:06 PM

I do something very similar and it has worked pretty well..

&lt;broadcasts&gt;
   &lt;message name=&quot;checkLoginStatus&quot;&gt;
    &lt;argument name=&quot;access&quot; value=&quot;admin&quot; /&gt;
   &lt;/message&gt;
&lt;/broadcasts&gt;

This method helps me support various access levels as well.

Paul Marcotte - Oct 20, 2008 at 2:38 PM

Hey Bill,

I like it! I'll give it a shot next time I roll an MG project.

salvatore fusto - Oct 21, 2008 at 3:07 AM

hi all,
i implemented a safe events role, in which there is a manytomany relation among user's role and events, in this way:
1) in coldspring i defined a map, ie a struct, in which every key is the name ofa safe event and the value is the requested role, may be a list of roles,
requested to run the events, plus a value corrisponding the event to announce if user has not the requested role;
2) in onRequestStart in the login ctrl, first i test if event name is in the struct: if not, i continue, if yes i test if there is a logged user, fetch his role, and test in the sctruct value is in the user's roles list: if not i announce a forward() to the login event.
this way i've have a safe mechnism indipendent from mg.xml and than from the app
regards
salvatore

salvatore fusto - Oct 21, 2008 at 3:11 AM

excuse me, ideed of :
-and test in the struct value is in the user's roles list-
read
- and test if user's role is in the struct value list of allowed events for the requested event-
excuse me again

Leave a Comment

Leave this field empty: