Dynamically Securing Method Execution with Spring Security

Preface

Spring Security provides a robust support for securing Spring based applications but it fails in some way when it comes to design dynamically configurable security, especially regarding dynamic configurability of java methods access. How we can overcome these limitations?

Introduction

When we want to secure an application, we must define access policies to its functions and we basically cope with two main models that we can call  ‘role-based security’ and ‘object-based security’, where the first works by defining roles played by users and by them limiting the access to specific system functions while the second focuses on permissions defined on single domain objects. This dichotomy is true also for Spring framework. Spring Security provides both these models and for each provides a robust solution on its own. The role-based security is implemented by the base spring security authorization API and the object-based security by the ACL module. Each solves a particular problem area and perhaps they both cover most of the needs but there are some limitations when it comes to design more advanced solutions. What if we want, for instance, to dynamically configure authorization to methods execution? In Spring Security we can secure methods by setting an annotation with an expression based on a role, but a role is something that is defined and configured in advance, not dynamically. Another possibility would be to use ACL to secure a method based on which permissions a domain object passed as an argument has, but this does not cover the situation in which we only want to authorize the method execution without any reference to its parameters. There are certainly ways of customizing the Spring Security classes to overcome this limitations, but in this article we want to point out a possible solution that exploit the ACL security model itself to provide a unique base for securing the whole application in a dynamic way. But first let’s have a quick  look on  how methods are authorized with  ‘role-based’ security and  ACL in practice.

Role-based security

A Role in spring Security is represented by an instance of   GrantedAuthority class.  A list of GrantedAuthority objects can be stored on an Authentication object to represent the roles played by current authenticated user. The AuthenticationManager is responsible to insert the GrantedAuthority into the Authentication object.  An AccessDecisionManager is responsible for making authorization decisions based on statements configured in Spring xml configuration files or as expressions in annotations. One can implement its own AccessDecisionManager or use one of the Spring implementations based on voting by the AccessDecisionVoter interface. Methods can be secured both with AOP configuration or in a simpler way using annotations and expressions like the following

@PreAuthorize("hasRole('ROLE_USER')") 
public void method();

Secure objects (ACL)

ACL relies on an API backed by database tables to define authorization permissions (like write, delete, admin) on single domain objects. A common way to secure an object is to use the hasPermission expression in an annotation like the following:

@PreAuthorize("hasPermission(#contact, 'admin')") 
public void admin(Contact contact); 

In the example above the method admin execution is authorized only if the current contact parameter has an ‘admin’ permission.

A solution to dynamically secure method execution

Spring does not seem to offer an out-of-the-box solution to dynamically secure methods, i.e. to set the permission to execute a method on the fly. One can limit the access to methods using roles or defining the access permission rules on method parameters by ACL. Roles are a rather static way to define access rules, they must be defined in advance and are course-grained, a role is not directly targeted to a single method or object but represents some general rule that limits the access to certain areas of the application. ACL on the other hand, is used for securing single objects by permissions, which are very fine-grained concepts directly related to the objects to be secured and not to some general application behavior. One way to overcome these limitations would be to perform some customization of the Spring Security API, for instance one can provide its own implementation of AccessDecisionManager class. Nevertheless in the middle of spring security ACL model there is already something that could do the trick, maybe in a more straightforward and cleaner way. The key would be to represent  a role not as a general application behavior associated to a user but simply as a set of permissions. Let’s recall briefly the main entities involved in the ACL design:

  • Acl: it represents an object, normally a domain object by an ObjectIdentity and it stores a set  of AccessControlEntries
  • AccessControlEntry (ACE): it is composed of a Permission, Sid and Acl.
  • Permission: A permission represents what can be done to an object (like write, read, admin) and it is implemented by a particular immutable bit mask.
  • Sid: it represents a Principal or GrantedAuthority.
  • ObjectIdentity: Each domain object is represented internally within the ACL module by an ObjectIdentity.

These classes are persisted to the database by the following set of tables:

  • ACL_SID it stores Sid instances
  • ACL_CLASS its purpose is to identify any domain object class in the system.
  • ACL_OBJECT_IDENTITY stores information for each unique domain object instance in the system, it is related to Acl instances and contains a foreign key to a ACL_CLASS instance representing the object type
  • ACL_ENTRY stores AccessControlEntry instances

If we think that a Sid could represent both a principal or a GranthedAuthority we are taken straight to the point: the ACL model offers us already a way to implement roles as a set of permissions, since an ACE is a set of Permission, Sid and Acl instances. A set of ACEs in which the Sid represents a single GrantedAuthority can be seen exactly as a role made up of a set of permissions.  We can even assign permissions directly to a user, using a Sid as a Principal instead of a GrantedAuthority. But what kind of permission can we associate to a method? What we want to secure is method execution so we can define a custom permission, and we can call it ‘execute’, for instance. We can then represent an Acl as a method execution, precisely as a wrapper of an instance of the java.lang.reflect.Method class. The wrapper is needed to provide an additional id property to identify the specific method execution instance. The ACL will then be given its own set of ACEs with the ‘execute’ permission associated with a user or role (i.e. with a Principal or GrantedAuthority). In order to secure a method then, a custom annotation could be implemented, let’s call it SecureMethodExecution , as:

 

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Secured("ROLE_DUMMY")
@interface SecureMethodExecution {
}

Here the SecureMethodExecution annotation declaration uses the Spring Security’s @Secured annotation as a meta-annotation so that the @SecureMethodExecution is recognized by Spring as if it was @Secured with the attribute value “ROLE_DUMMY”. The sole purpose of the attribute “ROLE_DUMMY” is to get  the default AccessDecisionManager to “think” that @SecureMethodExecution  is a regular @Secured annotation.

Then the methods could be annotated like this:

@SecureMethodExecution 
public void methodName(){...}

Finally a specific implementation of AccessDecisionVoter interface would provide the access logic. The following is an example of what the vote method code might be:

public int vote(Authentication authentication, Object object,
Collection attributes) {

 if(object instanceof ReflectiveMethodInvocation){
   MethodInvocation methodInvocation = (MethodInvocation) object;
   if (methodInvocation.getMethod().getAnnotation(
    SecureMethodExecution.class) != null) {
    MethodWrapper methodWrapper = new MethodWrapper(methodInvocation.
	   getMethod());
    boolean haspermission = permissionEvaluator.hasPermission(
           authentication,methodWrapper, CustomPermission.EXECUTE);
    if (!haspermission) {
     return ACCESS_DENIED;
    }
   }
 }

 return ACCESS_GRANTED;
}

Using this model an user interface could be built up by which ACE instances could be created or removed on the fly for every method that needs to be secured (service methods, usually), without the need of statically configure and restart the application.

Conclusions

Given that there could be several different ways to dynamically secure methods in Spring Security, nevertheless the solution above relies on the spring security architecture itself and it needs only minor customizations.

References

Spring Security reference documentation: http://docs.spring.io/spring-security/site/docs/3.0.x/reference/springsecurity.html

Dynamically Securing Method Execution with Spring Security last modified: 2014-10-14T22:45:18+00:00 by Mario Casari

5 thoughts on “Dynamically Securing Method Execution with Spring Security

    • Hi Imteyaz,

      at the moment I’m very busy with my work, but surely as soon as I have time I’m going to post a more detailed article with a working example, please be patient.

      thanks for your interest in reading this article,
      Mario

  1. Hi,

    Its a great idea! Thanks very much.
    In fact, it should become a feature in spring security.
    I would suggest raising a JIRA feature request in Spring Security project.

    Best Regards,
    Chary

    • Hi Chary,

      thank you very much for your appreciation.
      Actually in this solution I exploit the current features of Spring Security with some minor customization as you can see in an example in another article http://itshrine.com/dynamic-spring-security-sample/ , anyway I agree that it would be better to get it in a more direct way by some Spring Security facility, so I’m thinking of following your suggestion.

      Best regards,
      Mario

Leave a Reply

Your email address will not be published. Required fields are marked *