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?