A Simple Permission Based Security Library in Scala

I started writing a simple security library in Scala that supports permission checks similar to the java.security package, but is a lot simpler to extend or use and meant for securing application code and model objects based on user roles and permissions, not for protecting malicious code from executing. I personally like the basic concept of how the java.security.Permissions work, but that implementation is not suitable for handling user permissions for several reasons. The programming model with PAW (current code name for the library, it may change) is simple:

Extend the Permission trait in objects or case classes to define your own permissions. The Permission trait defines only one method:

def implies(that: Permission): Boolean

This is very similar to how java.security works: permissions can imply other permissions. Testing if a permission is implied is the same as testing if a user has a permission. For your own permission classes you only have to implement the implies method. But if you have simple permissions that don’t imply each other, but only themselves, you can just do this:

object MyPermission extends SimplePermission // A SimplePermission only implies itself and nothing else

Coming versions of the library may provide convenience classes or traits for hierarchically named permissions, CRUD permissions etc.

Permissions are grouped into PermissionSets, and they can be nested because PermissionSets are Permissions as well. There are two special Permission sets: AllPermissions and NoPermissions. The former can be used for “superadmin” users or during development; the latter can be used for guest users for example.

When you have defined your permissions, you need to set up a SecurityContext. JAAS integration, which gets the user Principal from JAAS, but stores permissions in a ThreadLocal, is provided with the library, but other implementations (such as Spring Security) can be plugged in. To set up the JAAS Context, you need to make sure that JAASSecurityContext is loaded, by making your code refer to it somewhere during initial setup:

init {
// You could also skip this and just use JAASSecurityContext everywhere instead of SecurityContext
JAASSecurityContext
}

You can ask SecurityContext for the current user Principal (this is still java.security.Principal) and it’s permissions. But most of the time you should need just two methods:

SecurityContext has MyPermission // SecurityContext.has(MyPermission) if you prefer

will tell you if the user has the permission or not. However, this still requires you to write an if-else statement if you want to throw an exception in case the user doesn’t have the required permissions. You can also do this:

SecurityContext mustHave MyPermission // will throw AccessControlException() if the permission is not implied

SecurityContext mustHave List(MyPermission, YourPermission) // must have both of them

Mostly, that’s it. You can write one-liners to check for user permissions and IMHO, this is in most cases superior to using Java EE annotations like @RolesAllowed("storeManager", "truckDriver", "cleaner"). You can go into details as much as required and you can put the permission checks anywhere in your code, including unmanaged objects.

I personally strongly prefer this security programming model. When I’ve had to use the Java EE role-based stuff I’ve usually had to “hack in” permissions by representing them as roles, which seems conceptually wrong. I haven’t taken a look at Spring Security for a while, but it seemed to follow a model similar to Java EE when I last tried it (years ago).

Of course, my library currently doesn’t cover roles or authentication. These can be handled by Spring Security, JAAS or something else, and may require custom integration work. But some of these features may also make into the PAW library in the future.

Feedback about the library would be greatly appreciated. Go a head and take a look at the sources at GitHub, it’s only about 250 lines of code currently, half of which are ScalaDoc comments. The sources and binaries are also available in my Maven repo.

PS. One thing to consider is this: the implication of Permissions is not transitive by default. i.e. A implies B, B implies C does not mean A implies C. When you test: SecurityContext has C, but the user has only A, an instance of B may not even exist. A.implies(that) is coded so that if the argument is B, it will return true, but there is no way to ask A for a list of all permissions it implies and if it does not directly imply C, then C is simply not implied. Can you think of a good solution for this?

3 thoughts on “A Simple Permission Based Security Library in Scala

  1. Interesting brain-teaser (whether you meant it to be or not)!

    I think the problem with transitivity is that implies is a many-to-one function — a non-uniquely invertible relation matrix. In other words, you can not get the parameter to implies from its result (the boolean). So… one option is to write the function so that it is invertible (make it a bi-map or simply represent the results as a list of Permissions instead of a black-box function applied to them). This couldn’t be done without damaging the elegance of the user-experience. Another option might be to have the base Permission class register all instances (in this case, case classes and objects) with a PermissionManager or something during construction. The PermissionManager could test the permission against all “currently” known permissions to build a boolean adjacency matrix (say, using 1’s at (i,j) if Permission(i) implies Permission(j)). This builds the inverse for you and the matrix could be efficiently built (if efficiency is a concern here) or even trivially built using Floyd-Warshall to get the non-incremental transitive closure (there’s one in Apache Commons and one here: http://algowiki.net/wiki/index.php/Floyd-Warshall%27s_algorithm … thank you Wikipedia). Since you don’t need the transitive closure until the Permissions are tested in client code, this would be the *most* efficient method in most cases (barring using a more efficient transitive closure algorithm).

    …but what I’d like to see is a usage that is as nice and as powerful as what you have but maybe simpler than this solution. There is no way that it can be done using the implies function but its not too unreasonable to have the user provide a list of permissions instead of a general function… and then you could write implies to test against ‘this’ and against each element in the implied list. But you lose genericity, which you would have to because you can no longer say something like:

    var x
    override def implies(other: Permission) = x < 3

    since what permissions are implied changes with time. Note that the transitive closure solution suffers from the same problem.

    I'd also like to see someone come up with a neat solution. Frankly, I find most permissions APIs to be terribly painful to use when you consider how simple the problem is. But I like yours… except for the loss of transitive closure which is "a deal breaker, ladies".

    – David

  2. Thank you for your comment, David, it was an interesting read.

    I’d like to keep it simple at least initially so I would rather go with your second approach, also because it’s similar to what I was thinking. I just pushed a possible implementation to github: http://github.com/Villane/paw/blob/master/paw-security/src/main/java/org/villane/paw/security/TransitivePermission.scala

    It didn’t change anything about non-transitive permissions and doesn’t concern itself with performance, but adds a trait TransitivePermission which has two overridable methods: impliesDirectly and impliedPermissions. So you could write:

    object P extends TransitivePermission {
    override def impliesDirectly(that: Permission) = x < 3
    }

    and

    object P2 extends TransitivePermission {
    override def impliedPermissions = List(P)
    }

    One possible option to get a bit better performance in some cases is to make impliedPermissions a lazily computed Stream. Or maybe the return type should be Permissions (the base trait for PermissionSet, NoPermissions and AllPermissions), which allows more flexibility of implementing a performant solution.

    Also, some convenience classes might be required for better usability in more cases.

Leave a comment