3A framework = f(Spring Boot custom filters + Aspect Programming)

Authentication, Authorization and Accounting (3A) is now the most desirable part in any application development process. Any framework with the three A’s feature will provide the ability to control access, authority and accountability for any compute resources involved in processing.

In this blog, we will focus on the concepts that are required to develop framework with AAA ability with help of Spring Boot libraries. For Authentication and Authorization, we will walk-through on developing a custom security filter leveraging Spring Security library and for Audit Log, we will focus on the Aspect Oriented Programming.

Authentication and Authorization — Custom Security with Spring Security

Few basic concepts for quick reference before we deep dive into the topic:

  • Authentication: It is the process of verifying the claims done by a user for his/her identification, usually with a password and user name or SSO tokens.
  • Authorization: It is the process of providing the user authority to perform a task/activity based on the roles he/she has.
  • Servlet Filter: A servlet is a program that runs within a Web server that receive and respond to requests from clients, usually across HTTP. Filter is an object that can transform the header and content (or both) of a request or response.

We used Spring Security library to develop a framework for authentication and authorization. Bearer token is required to authenticate and authorize an user for using compute resources. Below is the high level flow diagram of authentication and authorization, first step is to verify the SSO token, then based on the successful verification fetch the user information and then check for the required AD-Group of which user should be part of to access and use the resources.

Flowchart for Authentication & Authorization

Now coming to Spring Security library, Spring Boot provides security with the help of Spring Security library and Spring Security is a collection of servlet filters that allows the monitoring, processing of the requests and the responses before reaching to the spring controllers and client respectively.

Spring application is basically one servlet i.e. DispatcherServlet, which redirects every requests to @RestControllers or @Controllers. And unfortunately DispatcherServlet does not have any security mechanism. Thus there should be some secondary supporting mechanism for restricting unauthenticated and unauthorized requests before it reaches to their target, and that is where Spring Security library helps by providing Filters on the incoming requests and responses. And it also allows to write and configure custom SecurityFilter in the Spring Boot application to filter every incoming request before it reaches DispatcherServlet.

Small snapshot of how simple implementation of the Security filter looks like:

public class RequestAndResponseFilter extends GenericFilterBean { 
@Override
protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {

Token token = request.getHeaders("Token"); // (1)

// checking if valid token is passed
        if (Authenticated(token) == false) {  // (2)
            // when token passed is invalid we would send HTTP 401 response to the user  
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // HTTP 401.

return;
}
       // since token passed in the request is valid, fetch the required info of user 
UserInfo user = FetchUserInformation("token"); // (3)
       // checking for required AD-Group of which user should be part of 
if (Authorized(user) == false) { // (4)
            // user is not part of the AD-Group 
response.setStatus(HttpServletResponse.SC_FORBIDDEN); // HTTP 403
return;
}
        // Setting up authentication for authorized user 
CustomAuthentication authentication = new CustomAuthentication(userId, name,email); // (5)

SecurityContextHolder.
getContext().setAuthentication(authentication);
// (6)
        //  request is allowed to Dispatcher servlet 
chain.doFilter(request, response); // (7)
    }
private UserInfo fetchUserInformation (Token token) { 
// getting all information of user for setting security context and the user authorization
        return userInfo; 
}
    private boolean Authenticated(Token token) {
        // verifying the to the databases
        return false; 
}
    private boolean Authorized(UserInfo user) {
        // checking for required AD-Group.
        return false;
    }
}

Steps:

  1. Extracting token from the request.
  2. Verifying token’s validity from the database.
  3. After successful authentication, fetching the essential user information from the database.
  4. Checking for the required AD-Group of which user should be part of.
  5. CustomAuthentication is a class implementing the Authentication interface provided by Spring Boot. Authentication interface is provided the Spring Security library to store the essential information like username, password and roles regarding a user.
  6. SecurityContextHolder and SecurityContext are two important classes provided by the Security library. SecurityContext holds the authenticated user information. Thus, to have the information about the user, we need to find SecurityContext. Now, SecurityContextHolder is a class that uses ThreadLocal object to store the SecurityContext. Here, we are trying to set the SecurityContext of the authenticated and authorized user to the SecurityContextHolder, so that we can have the information of user, whenever we require in future.
  7. Allowing the request to go to filter chain and then to DispatcherServlet and hence to controller.

Filter Chain: In Spring Boot application, with Spring Security every request passes through 15 security filters, arranged in a chained fashion. This concept is referred as filter chain.

Now, for configuring Spring Security i.e. what all endpoints to which we want to authenticate every request and what all endpoints to which we want to permit every request and many more; we need to have a class with the following properties:

  1. EnableWebSecurity annotation for allowing Spring to find this class and apply it to the global web security.
  2. Extending WebSecurityConfigurerAdapter to use configuration methods offered, with which one can define which endpoint is to be protected.

A simple WebSecurityConfigurerAdapter looks like:

@Configuration
@EnableWebSecurity // (1)
public class CongurationForSecurity extends WebSecurityConfigurerAdapter { // (1)
    @Override
protected void configure(HttpSecurity http) throws Exception { //(2)
    http
.authorizeRequests()
.antMatchers("/").permitAll()
//(3)
.anyRequest().authenticated(); // (4)
    }
}

Steps:

  1. Simple class annotated with @Configuration and @EnableWebSecurity and extending WebSecurityConfigurerAdapter.
  2. Overriding configure( HttpSecurity http) method to specify rules for filters to treat requests.
  3. All request to URI “/” are permitted.
  4. Any other request except “/” should be authenticated.

We have completed the development of our custom Authentication and Authorization mechanism in our application. Now, let us let us move to next section for the development of the Accounting feature of our application.

Spring Aspect Oriented Programming

We used Aspect Oriented Programming to develop a framework, that can provide us with the ability to have access-logs, without disturbing any primary functionality code.

Audit Aspect

Aspect-Oriented Programming is a paradigm that enable us to think about the program structure differently than OOP. The unit of modularity in AOP is the aspect like class is for OOP. Aspects provides the way to dynamically add the cross cutting concern.

Now, let us focus of on what is cross-concern, but first let us understand the concern: it is the behaviour we want to have in a particular module of an application, it can be defined as a functionality we want to implement. Concern are of two type:

  1. Core concerns: primary functionality of the module
  2. Cross-cutting Concerns: functionality for secondary requirement, which are applicable throughout the application, e.g. logging, security and so on, which are needed in every module.
Core Concerns & Cross-Cutting Concerns

This picture shows the application broken in modules. Each modules primary focus is to provide core service. However, each of these modules requires ancillary functionality such as logging and security. These ancillary functionality are cross-cutting concerns.

In this blog, our primary focus is to implement aspect for audit logging. The over-simplified implementation for aspect for logging:

@Aspect // — — — — — — — (1)
@Component
public class CustomAspectForAuditLog {
    //Pointcut containing all the classed annotates with Service and RestController
    @Pointcut("within(@org.springframework.stereotype.Service *)" +" || within(@org.springframework.web.bind.annotation.RestController *)") // — — — — — — — (2)
public void pointcutBasedOnAnnotation() {
        // Pointcut methods are empty, since it’s for containing the joinpoint.
     }
     //Pointcut based on packages
@Pointcut("within(com.wlamartlabs.springExample.service.*)" +" || within(com.walmartlabs.springExample.controller.*)") // — — — — — — (3)
public void pointcutBasedOnPackage() {
         // Pointcut methods are empty, since it’s for containing the joinpoint.
     }
    //Advice for dealing Exception thrown by controller.
@AfterThrowing(pointcut = "pointcutBasedOnPackage() && pointcutBasedOnAnnotation()", throwing = "exception") // — — — — — — — (4)
public void handlingErrorFromController(JoinPoint joinPoint, Throwable exception) {
    // implementation dealing with the exception thrown
    }
    //Advice for dealing the request while entering and exiting the controller
@Around("pointcutBasedOnPackage () && pointcutBasedOnAnnotation ()") // — — — — — — — (4)
public Object prepareAuditLog(ProceedingJoinPoint joinPoint) throws Throwable {
        // operation before entering controller method
        // Useful info can be extracted for Audit
        Object result = joinPoint.proceed();// — — — — — — — (5)
        // operation after exiting from controller method
        // Useful info can be extracted for Audit
        return result;
    }
}
  1. Java class annotated with @Aspect, for declaring this class as implementation of cross-cutting concerns. The process of linking the aspect and advised object is done at load time.
  2. For understanding PointCut, we need to know about the JoinPoint. JoinPoint is a candidate point in the Program Execution of the application where an aspect can be plugged in. This point can be a method being called, or an exception being thrown. At these points aspect code can be plugged in the normal flow of application to add new feature. Since, it is not good or better to say feasible to apply the aspect code in every point of code, so a set of JoinPoint(s) are selected, and they are called as PointCut. From sample code, all classes annotated with the @Repository, @Service and @RestController are selected as JoinPoint.
  3. PointCut can also be defined by defining the name of the packages from application.
  4. For understanding @AfterThrowing and @Around, we need to know what is Advice. Advice is defined as the action taken by the aspect at particular join point. There are five advice namely: Before, After, Around, AfterThrowing and AfterReturning.

Let us have brief discussion about the various advices:

a. Before: Advice that executes before the JoinPoint.

b. After: Advice that executes after the JoinPoint either the JoinPoint executes successfully or with exception.

c. AfterRunning: Advice that executes only if the JoinPoint is executed successfully without any exception.

d. AfterThrowing: Advice that executes if the JoinPoint exits by throwing exception.

e. Around: It is the most powerful advice, it surrounds the JoinPoint. Around advice can perform custom behaviour before and after the method invocation.

5. In the Around Advice, the decision to allow the execution of the JoinPoint, is in the hands of the programmer. The proceed() method allows the JoinPoint to be executed and it also returns the object returned by the JoinPoint.

To have a complete and clear picture of the Aspect Programming structure, we can take the reference of this below figure.

Aspect Oriented Paradigm Representation

Conclusion

We developed a custom filter having custom methods for Authentication and Authorization, using the Spring Security library of Spring Boot. And we also developed aspect using the Aspect-Oriented Programming, to have the Accounting feature in the application. And hence, we achieved our goal for understanding the concepts that are required to develop an application with AAA ability with help of Spring Boot libraries.

Reference

  1. https://docs.spring.io/spring-security/site/docs/current/reference/html5/
  2. https://docs.spring.io/spring-framework/docs/2.5.x/reference/aop.html

3A framework = f(Spring Boot custom filters + Aspect Programming) was originally published in Walmart Global Tech Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

Article Link: 3A framework = f(Spring Boot custom filters + Aspect Programming) | by Shashwat Rai | Walmart Global Tech Blog | Nov, 2021 | Medium