Monday, December 22, 2008

Grails + JSecurity

I have been using the Grails JSecurity Plugin for authentication/authorization in my proto-type Grails app.

While there are many good things about the JSecurity Grails Plugin, "thorough documentation" is not one of them. I had some difficulty figuring out how to tie it all togethr, so I am posting here my basic set up.

For apps where authorization is, to some degree, external to the core object model, the WildcardPermission is the flexible, powerful way to go.

In my app, however, authorization rules are deeply embedded within the domain model -- whether or not User X can edit object Y is a function of some of Y's member values. I do not see how that can be accomplished via WildcardPermission.

My first cut of a solution involves defining an enum and an interface


public enum PermissionActionEnum {
VIEW, EDIT, EXECUTE, DELETE, CREATE, ...
}

public interface AuthProvider<E> {
public boolean isPermitted(User u, PermissionActionEnum a, E on);
public Class<E> getClazz();
}


Each of these AuthProviders knows how to determine authorization by examining the target object. I have a class "GlobalAuthProvider" which contains references to all the known AuthProviders and its own isPermitted method which delegates appropriately.

I defined a JSecurity Permission to link resource/target with a PermissionAction.


public class ResourcePermission implements org.jsecurity.authz.Permission {
Object resource
PermissionActionEnum action
...
//So that action can be set with either an Enum or String
public void setAction(String name) {
action = PermissionActionEnum.valueOf(name.toUpperCase());
}
}


Next, I defined a groovy authService which wraps the GlobalAuthProvider


public class AuthService {
...
public boolean isPermitted(User user, ResourcePermission resourcePermission) {
GlobalAuthProvider gap = ...
Object on = resourcePermission.resource
PermissionActionEnum action = resourcePermission.action
return gap.isPermitted(user, action, on);
}
...


My Realm then delegates to the authService

class MyRealm {
def authService
...
//Assumes ResourcePermision
def isPermitted(principal, requiredPermission) {
def user = User.findByName( principal )
return authService.isPermitted(user, requiredPermission)
}
...


Now the JSecurity tag can be used in the gsp. This is a little tricky because the GSP jsec:hasPermission tag, appears to be slightly different from the general JSP one


<jsec:hasPermission
permission="${ new ResourcePermission(resource:obj,action:'VIEW') }">
...
</jsec:hasPermission>

5 comments:

  1. Hi Marc,

    Please understand that JSecurity and the JSecurity Grails plugin are two different projects. JSecurity core has good documentation, although of course, we are trying to make it better! It would be nice if you could clarify "JSecurity Grails Plugin" instead.

    Btw, the Grails plugin documentation is a wiki - would you mind helping update it to improve the quality of the documentation so others don't have the same complaint? Peter Ledbrook (the author of the plugin) does a fantastic job, but as you can imagine, is incredibly busy. Any help you could lend would make his life easier as well as those of future users.

    Regards,

    Les

    ReplyDelete
  2. P.S. Nice job with the Permissions. If WildcardPermission, even as powerful as it is, does not fit your needs, then implementing your own Permission is the way to go.

    ReplyDelete
  3. Thanks for the post. I'm more familiar with Acegi/Spring Security than JSecurity, but would like to get to know JSecurity better (especially in conjunction with Grails).

    Quick comment on presentation: your blog's overall appearance is fine on IE7 and Firefox 3, but in Firefox the code lines wider than the main content column (~45 chars) are being cut off rather than wrapped.

    ReplyDelete
  4. what a pity. I tried to use < jsec:hasPermission permission="${ new org.jsecurity.grails.JsecBasicPermission("jsecRole","create") }" >
    it always shows permission is null. I used Grails 1.0.4 and JSecurity 0.3 plugin

    ReplyDelete