+

Using Aspect Oriented Programming to apply fine-grained authorization

Introduction to AOP

Any computer application or system deployed in an enterprise environment has to deal with multiple distinct concerns. Some of them are cross-cutting, meaning they should apply globally across the system. Typically this includes logging, validation and authorization concerns. The problem with these cross-cutting concerns is that they can very easily turn into scattered and duplicated code (spaghetti code is a term used), which makes the maintainability and evolution of the system difficult. Also, often the responsibility of fulfilling these non-functional requirement is put on the shoulders of the functional developer, which is not ideal.

Aspect Oriented Programming (AOP) is a technique to modularize and separate these concerns into separated modules and call them based on business rules, letting a functional developer not have to deal with fulfilling logging or authorization requirements.

AOP uses the following terminology(pdf):

  • Aspect – A cross-cutting, possibly non-functional, concern, such as authorization.
  • Joint Point – A point in the code where cross-cutting concerns meets functional requirements.
  • Pointcut – A set of joint points linked to an advice.
  • Advice – The actual code to execute when a pointcut is triggered, with possibility to proceed with execution of the intercepted method.
  • Weaving – Process of assembling the final form of the modules and application.

AOP is very often used in conjunction with .NET Attributes or Java Annotations to specify the meta data (business rules) on joint points and how an aspect should behave, but it is not always necessary to use them.

Creating requests

Let us assume we have a student service with the functionality to assign grades to students. We can express this action in English, Java and XACML language as follows:

English:
Alice assigns grade ‘A’ on course c for student s.

Java:
Service s = new StudentService();
s.login(“alice”, password);
s.assignGrade(“A”, c, s);

XACML:
subject-category:
subject-id: “alice”
action-category:
action-id: “assignGrade”
resource-category:
grade: “A”
course-id: “c”
student-id: “s”

We go from english to java when we design the service implementation from use cases, which is a manual process. In order to separate out access control in a generic way, we need a generic way to translate java code into XACML authorization requests. When inspecting the elements of the respective language, according to the following table, one realizes that the XACML request can be created in a generic way by using Java/.NET reflection APIs and some metadata. 

 

Clause element

Java

XACML

Alice

Subject

Current session user

Subject attribute

assigns grade

Predicate

Method invocation

Action attribute

grade ‘A’

Object

Method parameter

Resource attribute

student s

Object

Method parameter

Resource attribute

course c

Object

Method parameter

Resource attribute

Resource attributes

Java annotations or .NET attributes are a form of metadata that can be added to classes or methods. This metadata is then available and can be processed at runtime. In this blog post we will see how annotations can be used to mark objects’ properties in order for it to become part of an XACML request. Once that is accomplished, we can use reflection to create XACML attribute and values at runtime.

class Student {
@XacmlAttribute
String name;

@XacmlAttribute
Integer age;

@XacmlAttribute
List enlistedCourses;

String telephoneNumber;
}

Whenever a Student instance is involved in an action (method invocation) as a method parameter, the annotated field’s value will be extracted and will be part of the XACML request.
Given the annotations above, the following method invocation:

service.deleteStudent(aStudent);

will result in the following attributes in the XACML request:

<xacml-ctx:Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" >
  <xacml-ctx:Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-type">
    <xacml-ctx:AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">Student</xacml-ctx:AttributeValue>
  </xacml-ctx:Attribute>
  <xacml-ctx:Attribute AttributeId="age">
    <xacml-ctx:AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">40</xacml-ctx:AttributeValue>
  </xacml-ctx:Attribute>
  <xacml-ctx:Attribute AttributeId="name">
    <xacml-ctx:AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">Bob</xacml-ctx:AttributeValue>
  </xacml-ctx:Attribute>
  <xacml-ctx:Attribute AttributeId="enlistedCourses">
    <xacml-ctx:AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">CourseA</xacml-ctx:AttributeValue>
  </xacml-ctx:Attribute>
  <xacml-ctx:Attribute AttributeId="enlistedCourses">
    <xacml-ctx:AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">CourseB</xacml-ctx:AttributeValue>
  </xacml-ctx:Attribute>
</xacml-ctx:Attributes>

Fields annotated with the @XacmlRequest are expected to be of attribute category resource, since their objects (Student) are parameters to methods (deleteStudent()).

Action attributes

We will also use an annotation, @XamlEnforcementPoint, to instruct the execution of the program to insert an enforcement point, a PEP, at given points. This means that this annotation defines the joint points; we have a functional goal to do what the service method is designed to do (ie, create or delete a student), but also a non-functional goal to not execute it if the current user is not authorized to do so.

This annotation can either be inserted on a service interface or at the implementation level. If we add the enforcement point annotation on the interface level, all implementation will be automatically protected by an XACML PEP.

public interface StudentService {
    @XacmlEnforcementPoint
    Student createStudent();
    
    @XacmlEnforcementPoint
    void updateStudent(Student student);
    
    @XacmlEnforcementPoint
    void deleteStudent(String studentId);
    
    @XacmlEnforcementPoint
    List<Student> listStudents();
    
    @XacmlEnforcementPoint
    Student listStudent(String id);
    
    @XacmlEnforcementPoint
    void gradeStudent(String id, Course course, Integer grade);
}

With the help of AOP we can intercept all calls to methods annotated with @XacmlEnforcementPoint. Via reflection we can extract the method name and use it as an action attribute:

service.deleteStudent(aStudent);

will yield the following attribute:

<xacml-ctx:Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action" >
  <xacml-ctx:Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id">
  <xacml-ctx:AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">deleteStudent</xacml-ctx:AttributeValue>
</xacml-ctx:Attributes>

Subject attributes

Assembling the subject attributes is a bit different. Since these attributes are normally not part of a service method invocation but belongs to authenticated session, it is most likely they have to be accessed in a static manner or via callbacks, depending of the authorization or session frameworked used. This pattern can be used:

AttributeProvider subjectProvider = new AttributeProvider() {
  public void consume(List attributes) {
    String user = Application.getCurrentSession().getUsername();
    map.put(new SubjectIdAttribute(user));
  }
};
PolicyEnforcementPoint.getInstance().addAttributeProvider(subjectProvider);

The pointcut

We have annotated all our domain model objects with @XacmlAttribute annotations to assemble resource attributes. We have also annotated the methods we want to protect and which constitutes the action attributes with @XacmlEnforcementPoint annotations. We have seen how an AttributeProvider interface can be used to have callbacks for subject attributes.

A pointcut can now be defined to call the PEP whenever an annotated method is to be executed. With AspectJ notation:

@Aspect
public class XacmlEnforcementPoint {

  @Around("(execution(* *(..)) || call(* *(..))) && @annotation(com.axiomatics.xacml.aop.api.annotations.XacmlEnforcementPoint)")
  public Object policyEnforcementPoint(ProceedingJoinPoint pjp)
            throws XacmlAdviceException, AccessDeniedAdviceException,
            ObligationFullfillmentException, Throwable {
            ...
  }
}

The body of the policyEnforcementPoint should carry out the following tasks:

  • Discover a PDP (or be configured with one)
  • Extract the intercepted method’s parameters and scan for @XacmlAttribute annotations in order to find resource attributes.Potentially there is a need to call the DAO layer to retrieve current persisted values for the parameter objects, since the values intercepted may have pending updates, which access control should not be performed upon.
  • Extract the called method and create an action attributes based on the intercepted method
  • Extract the current session’s authentication information to create subject attributes.
  • Build the request and call the PDP.
  • Enforce the PDP’s evaluation response (decision, obligations and advice).

The following invocation

Service s = new StudentService();
s.login(“alice”, password);
s.deleteStudent(aStudent);

can now be protected by an PEP and yields the following request:

<xacml-ctx:Request ReturnPolicyIdList="true" CombinedDecision="false" >
   <xacml-ctx:Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:environment" >
   </xacml-ctx:Attributes>
  <xacml-ctx:Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" >
      <xacml-ctx:Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-type">
         <xacml-ctx:AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">Student</xacml-ctx:AttributeValue>
      </xacml-ctx:Attribute>
  <xacml-ctx:Attribute AttributeId="age">
         <xacml-ctx:AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">40</xacml-ctx:AttributeValue>
      </xacml-ctx:Attribute>
 <xacml-ctx:Attribute AttributeId="name">
         <xacml-ctx:AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">Bob</xacml-ctx:AttributeValue>
      </xacml-ctx:Attribute>
 <xacml-ctx:Attribute AttributeId="enlistedCourses">
         <xacml-ctx:AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">CourseA</xacml-ctx:AttributeValue>
      </xacml-ctx:Attribute>
 <xacml-ctx:Attribute AttributeId="enlistedCourses">
         <xacml-ctx:AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">CourseB</xacml-ctx:AttributeValue>
      </xacml-ctx:Attribute>
   </xacml-ctx:Attributes>
   <xacml-ctx:Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action" >
      <xacml-ctx:Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id" IncludeInResult="true">
         <xacml-ctx:AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">deleteStudent</xacml-ctx:AttributeValue>
      </xacml-ctx:Attribute>
   </xacml-ctx:Attributes>
   <xacml-ctx:Attributes Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject" >
      <xacml-ctx:Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id" IncludeInResult="true">
         <xacml-ctx:AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">alice</xacml-ctx:AttributeValue>
      </xacml-ctx:Attribute>
   </xacml-ctx:Attributes>
</xacml-ctx:Request>

Only if the PDP returns PERMIT will the deletion of student be performed, otherwise it is not.

Weaving

Last the weaving should take place. The following ant task will call the AspectJ post-compiler and weave in our authorization aspect into the already compiled code. New bytecode will be created and packaged into a weaved jar.

<target name="taskdef-aspectj">
  <taskdef resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties">
    <classpath>
      <pathelement location="${lib.dir}/org.aspectj/aspectjtools/jars/aspectjtools.jar"/>
    </classpath>
  </taskdef>
</target>

<target name="weave" depends="taskdef-aspectj,">
  <mkdir dir="${build.lib.weaved.dir}"/>
  <iajc
      inpath="${build.lib.dir}/${application.jar}"
      outJar="${build.lib.weaved.dir}/${application.jar}"
      verbose="${iajc.verboase}"
      showweaveinfo="${iajc.verboase}"
      classpathref="runtime-classpath"
      source="1.5">
    <aspectpath>
      <pathelement path="${build.lib.dir}/${axio-enforcement-aspect.jar}"/>
    </aspectpath>
  </iajc>
<!-- Delete the original jar so we never risk mixing the un-weaved with the weaved jar -->
  <delete file="${build.lib.dir}/${application.jar}"/>
</target>

Conclusion

We have seen that AOP and the XACML reference architecture fits very well together, sharing the same concepts. Introducing generic, fine-grained attribute based access control into your system as a well-separated aspect via AOP is possible and is expected to lead to more maintainable and reusable code.

In short, let a Policy Decision Point (PDP) provide decision advices at Policy Enforcement Points (PEP) to handle AuthZ concerns in applications, without interfering with functional code developers.

The introduction of authorization in the system is can be made transparent to both the developer, implementation and the consumer of an API.

Although the techniques described in the article does not alter the existing functional state of the application, it requires access and re-compilation of it in order to add annotations to classes and methods. Other AOP techniques can be used to accomplish the same goals in legacy applications without need of recompilation, but will result in less generic, less reusable code.

Related Articles

Meeting today’s dynamic authorization and access challenges: The Axiomatics story | Dynamically Speaking
Dynamically Speaking
For more than 15 years, Axiomatics has worked with companies worldwide to define and deliver solutions to the most complex authorization and access challenge. In...
Getting started with Zero Trust using dynamic authorization | Dynamically Speaking
Dynamically Speaking
Zero Trust. It’s everywhere. It’s a methodology that’s been around for years, and we are now seeing a significant uptick in the number of enterprises...
The case for dynamic authorization in banking and finance
Attribute Based Access Control (ABAC)
More than other organizations, banks, and financial institutions face the highest levels of scrutiny when it comes to how they protect critical assets and sensitive...