Using XACML to apply fine-grained access control on Java Servlets with Filters

XACML Policy Enforcement Points

A policy enforcement point (PEP) in the XACML architecture is responsible for:

  1. intercepting a business request (e.g. a user web request to a backend servlet)
  2. creating an authorization request using any number of attributes available from the business request and the context
  3. sending the request to the Policy Decision Point (PDP)
  4. receiving and enforcing the decision it gets back from the PDP

At Axiomatics, we call this process the SAFE process – it stands for Stop; Analyze; Forward; Enforce.

In this post we explain how to use XACML to apply fine-grained access control on Java Servlets using Filters.

Use Servlet Filter as a Policy Enforcement Point

To use the XACML model with Java Servlets, developers will need to look for an interface where they can intercept incoming and optionally outgoing requests.

Luckily, the J2EE platform provides such an interface, namely the Filter. This filter conforms with the Servlet JSR specifications (JSR 154 and 315 for Servlet 2.4 and 3.0 respectively).

Any class implementing the Filter interface will need to implement a minimal set of methods:

public abstract void init(javax.servlet.FilterConfig arg0) throws javax.servlet.ServletException;

In this method, developers will need to initialize the PEP and pass it any configuration it needs to connect back to a PDP e.g. the PDP’s URL. Other configuration may include mapping rules (e.g. how to go from the principal’s username to a XACML attribute).

public abstract void doFilter(javax.servlet.ServletRequest arg0, javax.servlet.ServletResponse arg1, javax.servlet.FilterChain arg2) throws java.io.IOException, javax.servlet.ServletException;

In this method, developers will need to create the XACML request based on the ServletRequest and/or ServletResponse objects. Developers will then need to send the XACML request to the PDP, receive the response, and enforce the decision.

public abstract void destroy();

For the purpose of this blog post, this method can be left empty.

For an in-depth understanding of these methods and the lifecycle of a servlet filter, please refer to the further reading section.

Using Axiomatics PEP SDK to implement a Servlet Filter

The Axiomatics PEP SDK for Java provides developers with the means to easily develop any type of enforcement point in a Java environment. The PEP SDK decouples the creation of the XACML request from the specifics of the communication (or plumbing) between the PEP and the PDP. For in-depth documentation on the SDK, please refer to the SDK’s documentation and javadocs.

The first step is therefore to create an instance of a PDP connection. The simplest way to do so is to use the SDK’s connection factory as follows:

PDPConnection connection = PDPConnectionFactory.getPDPConnection();

The PDPConnection variable should be implemented as a static variable. Its value can be initialized in the Servlet filter’s init() method as displayed in the following code snippet.

public class FilterPEP implements javax.servlet.Filter{
    	
    	PDPConnection connection;
 
    	@Override
    	public void init(FilterConfig config) throws ServletException {
            	try {
                    	connection = PDPConnectionFactory.getPDPConnection();
            	} catch (Exception e) {
                    	throw new ServletException(e);
            	}
            	
    	}
}

The connection factory’s getPDPConnection() method uses a default properties file called pdp.properties to build the connection to the PDP. It is read from the classpath. It contains basic connection information such as the PDP’s URL, authentication credentials, and the type of connector to use. An example is displayed below:

driver=com.axiomatics.sdk.connections.aps5.ws.Aps5WsPDPConnection
ws.url=https://localhost:8143/asm-pdp/pdp/pdp?wsdl
truststore.type=jks
truststore.file=C:/users/djob/.keystore
# The trust store password, can be obtained from the PDP admin.
truststore.password=changeit

# Basic java.net authentication credentials
# These can be obtained from the PDP admin
username=pep
password=password

The second step is to stop the business request and create an XACML authorization request from it. To do so, we need to:

  1. implement the doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) method
  2. create a XACML request using the ServletRequest parameter as input.

To be able to access as many variables as possible, it is necessary to cast the ServletRequest object to an HttpServletRequest. This is done as follows.

@Override
public void doFilter(ServletRequest req, ServletResponse resp,
            	FilterChain chain) throws IOException, ServletException {
    	// 0. grab the HttpServletRequest object
    	HttpServletRequest hReq = (HttpServletRequest) req;

 Next, we can start creating the XACML request. To facilitate this task, the PEP SDK provides a builder which follows the Builder Pattern. It is possible to add any number of attributes using the builder pattern in any given category. For additional information, check out our SDK documentation.

// 1. create XACML request
XacmlRequestBuilder builder = new XacmlRequestBuilder();
try {
    builder.addSubjectAttribute(Constants.SUBJECT_ID, hReq.getUserPrincipal().getName());

Note that good code should always check whether the values requested such as hReq.getUserPrincipal() in the above example are accessible and valid. In this particular example, if a user accesses a servlet anonymously (which is the vast majority of accesses), then hReq.getUserPrincipal() is null as a result of which calling hReq.getUserPrincipal().getName() will yield a NullPointerException.

Let’s add some additional attributes to make the authorization request more complete.

builder.addActionAttribute(Constants.ACTION_ID, hReq.getMethod());
builder.addResourceAttribute(Constants.RESOURCE_ID, hReq.getRequestURI());

So far, we’ve created a request which – in English – expresses the following: “Can the user who’s currently authenticated do the HTTP action (GET, POST… depending on the value) on the URL ‘http://example.axiomatics.com’?”. That type of request is fairly coarse-grained. To make it more context-aware, additional attributes such as HTTP headers, IP address, and the time of the day can all be added. For instance, the following code snippet iterates through HTTP headers and adds them all as XACML attributes of the environment category.

Enumeration<String> headerNames = hReq.getHeaderNames();
	while (headerNames.hasMoreElements()){
		String headerName = headerNames.nextElement();
                builder.addEnvironmentAttribute(headerName, hReq.getHeader(headerName));
        }

Adding headers to a XACML request can help enable device-based (or more simply browser-based) access control. This is an essential step towards enabling BYOD.

Finally, it’s time to create the XACML request and send it off. The previous steps covered the Stop and Analyze parts of SAFE. We are now implementing the Forward (of the request from the PEP to the PDP) part.

// 2. Send request and save response
RequestCtx xacmlRequest = builder.buildRequest();
SDKResponse xacmlResponse = connection.evaluate(xacmlRequest);

Once we receive the response as an SDKResponse object, we need to consider how to handle it. Handling a Permit is fairly straightforward though it is specific to the type of PEP being written. In this case, we use the Servlet filter’s chain to continue the processing of the XACML request as follows. This is the Enforce part of SAFE:

// 3. enforce the response and any XACML obligations/advice that come back
if (xacmlResponse.getDecision()==Result.DECISION_PERMIT){
	chain.doFilter(req, resp);
}

However, things may not be as straightforward. There may be obligations and advice along with the result (Permit, Deny, NotApplicable or even Indeterminate) that need to be handled. In addition, the PEP might have a bias i.e. a default result when neither of Permit or Deny (e.g. NotApplicable) is returned as a result. Lastly, it’s important to consider how to handle a Deny situation.

else {
	HttpServletResponse hResp = (HttpServletResponse) resp;
	hResp.sendRedirect("./accessdenied.html");
}

In the above example, we redirect the business flow to an error page.

Since the building and sending of a XACML request can lead to multiple exceptions, it’s important to catch them all and either handle them or throw them in line with the Servlet API, i.e. to wrap them as ServletException and throw them.

	} catch (Exception e) {
		throw new ServletException(e);
	}	
}

Tying It All Together

To apply the newly written Servlet PEP, all that needs to be done is update the web application’s web.xml to include the following lines as per the Servlet specification.

<!--  List of filters -->
<filter>
	<filter-name>Authorization Filter</filter-name>
	<filter-class>com.axiomatics.samples.pep.FilterPEP</filter-class>
</filter>
<filter-mapping>
	<filter-name>Authorization Filter</filter-name>
	<url-pattern>/foobar/*</url-pattern>
</filter-mapping>

Benefits of a Servlet PEP

Servlet PEPs or any type of PEP that is implemented against a well-known framework interface has several benefits:

  1. It promotes un-intrusive authorization: the target application code does not need to be changed when a policy change is made. This means XACML authorization can be applied to home-grown, greenfield or off-the-shelf applications equally easily.
  2. It builds on top of developers’ know-how of frameworks. Most J2EE developers are familiar with servlets, JAX-WS, JAX-RS, and EJB APIs. Writing or applying a PEP on such interfaces should be extremely easy for them. The same holds true for .NET-based environments.
  3. It promotes decoupled authorization through configuration. The Servlet PEP – for instance – can be configured through the web application’s web.xml as previously described.

Conclusion

Writing enforcement points using the Axiomatics PEP SDK is quite simple. Developers should always strive to develop PEPs that are in line with the target environment’s best practices and framework APIs. PEPs should also be configurable and un-intrusive to promote reuse, easy configuration, and efficiency.

The Entire Code Snippet

You can download the full code below. {rsfiles path=”blogposts/FilterPEP.java”}

To run it, the Axiomatics PEP SDK for Java libraries – as explained in the PEP SDK Documentation – must be added to the classpath.

Further Reading

Other Blogs

3 keys to re-evaluate your authorization management
Business
On May 27, I had the pleasure to join the KuppingerCole KCLive event with several industry peers in a panel discussion about  “Enabling the Future...
How OAuth is related to Attribute Based Access Control
Tech
What is Authorization? Authorization, also referred to as Access Control, is the process that follows authentication (which checks your identity and ensures that you are...
Modern Enterprise Authorization Management System
Business
Gartner has an interesting article titled “Modernize Your Runtime Authorization” that highlights some aspects you need from a modern enterprise authorization systems. Over the years...