Securing Grails Plugin Artifacts with Filters

So you’ve just installed the handy dandy Spring Security plugin (http://grails.org/plugin/acegi), which makes it incredibly easy to secure entire Grails controllers and/or controller actions with annotations, such as the following:

This is enabled by turning on controller annotations in your SecurityConfig.groovy file:

So all is now good in our project. We can secure either controllers or actions with annotations, enabling us to declaratively setup security side-by-side with the code that we’re securing in a very straightforward manner. You can continue developing your Grails applications with glee, fully assured that security is no longer an issue. But wait, one day you decide to install one of the many useful Grails plugins that add controller artifacts to your application. Lo and behold, you have no way to secure those controllers! Of course, you could descend into $USER_HOME/.grails/$GRAILS_VERSION/projects/projectName/plugins/pluginX and hack the source code for your individual instance of the plugin. This ought to work, but you’re now rather constrained in that every time you update the plugin you’ll need to remember to go make this manual change. That doesn’t sound very agile at all, does it? OK, so how about forking the plugin? This is a little bit better, but now you have the burden of merging changes from the global plugin repository to yours every time a new release happens. This is better, but still a bit cumbersome. How about becoming a committer and adding it to the global source? Of course not. Not everyone will want to secure their plugins the same way you do, and you’ve just introduced a rather unnecessary dependency on the Spring Security plugin. I say all this in an attempt to paint a grim picture. In reality, we’re actually in very good shape. Grails Filters to the rescue!

All that you need to do is create a Grails filter that will match requests to the plugin artifact in question and then delegate to Spring Security for authorization. If they are authorized, you simply return true. If not, you can direct them to your login screen. It’s this simple:

As you can see here, I’ve secured both the Blurb plugin and the Settings plugin in this manner by requiring that the logged in user be in the ROLE_ADMIN role. Now as Glen Smith would say, that’s a snack!

Update: Burt Beckwith enlightened me to an approach that will get this done without the use of filters that will also direct you to the requested URL after login rather than the main page. Unfortunately I’ve never been able to track this down before. Just add the following to SecurityConfig.groovy:


4 responses to this post.

  1. Check out the ‘controllerAnnotationStaticRules’ discussion in the annotation section of http://grails.org/AcegiSecurity+Plugin+-+Securing+URLs

    This is used to secure URL patterns that can’t be annotated, i.e. static resources (JavaScript, CSS, etc.) and controllers that you can’t edit for whatever reason:

    controllerAnnotationStaticRules = [
    '/blurb/**': ['ROLE_ADMIN'],
    ‘/setting/**’: ['ROLE_ADMIN']
    ]

    This has the advantage over the filter approach of being fully integrated into the plugin and Spring Security, in that when navigating to a secured controller the requested URL will be remembered, and after a successful login you’ll be redirected to that URL.

    Reply

  2. Posted by Matt on November 10, 2009 at 9:04 pm

    OK, so why have I never been able to find this before?!?!? This is exactly the behavior that I have wanted out of the plugin, but somehow I have never been able to track it down. Definitely a far superior approach. Thanks!

    Reply

  3. Posted by Bruce Richardson on November 29, 2009 at 4:54 am

    For me, this demonstrates the dangers and problems of using annotations in this way. Now you have two ways to indicate security settings and you have to audit them both. If you’d done with the external configuration option, you’d have the one way and the one set of problems.

    There are now a huge number of frameworks offering the use of annotations for configuration (Hibernate, Spring, JAX-WS etc.) Use all their annotations and your domain objects will be decorated like the outside of a Minnesotan house at Christmas (visit Minnesota any December to find out just how garish that is). Not only does it obscure the code rather than enhancing it, it means that code is changed much more frequently than it should.

    Annotations should be intrinsically meaningful to the objects they adorn, so that any code you write can make intelligent use of them, or they should be meaningful in contexts so widely understood that their purpose will not be lost . This often means that the only useful annotations are those meaningful to the Java compiler, but other annotations can be valid *if* the annotated object will only be used in a context where those annotations are universally understood. Security for Grails controllers is a good candidate for the second, but since the use of annotations for security isn’t part of the Grails core, which would encourage every security-plugin developer to adopt a single standard, they fail.

    The whole Java world and their pets seem to be gleefully ignoring this and adopting annotation-based configuration like crazy. It’s wrong, it will bite them and maybe they’ll learn.

    Reply

  4. Hi (other) Matt,

    I’m not sure how relevant this is after Burt’s very helpful suggestion, but I noticed that your second code snippet is exactly the same as the first. You meant to include some code from SecurityConfig.groovy there, right?

    –Matt

    Reply

Respond to this post