Java Token Validator (10.1 release)

Release 10.1 (Beta)

This topic demonstrates how to secure Java REST applications using the PMF Java Token Validator (JTV). The validator enables token-based authentication for external resources by validating access tokens against the PMF authorization server.

Prerequisites

  • PMF-Tools-10.1.0.zip package
  • Java development environment
  • Maven-based project

Jump to

Installation

Involves following steps.

  1. Install security tools.
    1. Download the PMF-Tools-10.1.0.zip package.
    2. Extract the pmf-security-tools.zip archive.
    3. Navigate to the security-maven directory.
    4. Execute the installation script by using the following command.

      Linux/Mac

      ./install.sh

      Windows

      install.bat

  2. Add Maven dependency.
    1. Add the following dependency to your project’s pom.xml file.

        <dependency>
            <groupId>com.ibm.mfp</groupId>
            <artifactId>mfp-java-token-validator</artifactId>
            <version>10.1.0</version>
        </dependency>
      

Implementation

Creating a Protected REST resource

Involves following steps.

  1. Define the REST resource.
    1. Create a REST resource class that will be protected by the token validator:
    import jakarta.ws.rs.GET;
    import jakarta.ws.rs.Path;
    import jakarta.ws.rs.Produces;
    import jakarta.ws.rs.core.MediaType;
    
    @Path("/hello")
    public class HelloResource {
    
        @GET
        @Produces(MediaType.TEXT_PLAIN)
        public String sayHello() {
            return "Hello from application!";
        }
    }
    
  2. Implement the Authentication filter.
    1. Create a servlet filter to validate incoming requests:
     import java.io.IOException;
     import java.net.URI;
    
     import com.ibm.mfp.java.token.validator.AuthenticationError;
     import com.ibm.mfp.java.token.validator.TokenValidationException;
     import com.ibm.mfp.java.token.validator.TokenValidationManager;
     import com.ibm.mfp.java.token.validator.TokenValidationResult;
    
     import jakarta.servlet.Filter;
     import jakarta.servlet.FilterChain;
     import jakarta.servlet.FilterConfig;
     import jakarta.servlet.ServletException;
     import jakarta.servlet.ServletRequest;
     import jakarta.servlet.ServletResponse;
     import jakarta.servlet.annotation.WebFilter;
     import jakarta.servlet.annotation.WebInitParam;
     import jakarta.servlet.http.HttpServletRequest;
     import jakarta.servlet.http.HttpServletResponse;
    
     @WebFilter(
         urlPatterns = "/rest/*",
         initParams = {
             @WebInitParam(name = "scope", value = "accessRestricted")
         }
     )
     public class AuthenticationFilter implements Filter {
    
         private static final String AUTH_HEADER = "Authorization";
         private static final String AUTHSERVER_URI = "http://localhost:9080/mfp/api";
         private static final String CLIENT_ID = "your-client-id";
         private static final String CLIENT_SECRET = "your-client-secret";
    
         private TokenValidationManager validator;
         private FilterConfig filterConfig;
    
         @Override
         public void init(FilterConfig filterConfig) throws ServletException {
             try {
                 URI authServerUri = new URI(AUTHSERVER_URI);
                 this.validator = new TokenValidationManager(authServerUri, CLIENT_ID, CLIENT_SECRET);
                 this.filterConfig = filterConfig;
             } catch (Exception e) {
                 throw new ServletException("Failed to initialize token validator", e);
             }
         }
    
         @Override
         public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                 throws IOException, ServletException {
    
             HttpServletRequest httpRequest = (HttpServletRequest) request;
             HttpServletResponse httpResponse = (HttpServletResponse) response;
    
             String expectedScope = filterConfig.getInitParameter("scope");
             String authHeader = httpRequest.getHeader(AUTH_HEADER);
    
             try {
                 TokenValidationResult result = validator.validate(authHeader, expectedScope);
    
                 if (result.getAuthenticationError() != null) {
                     // Authentication failed
                     AuthenticationError error = result.getAuthenticationError();
                     httpResponse.setStatus(error.getStatus());
                     httpResponse.setHeader("WWW-Authenticate", error.getAuthenticateHeader());
                 } else if (result.getIntrospectionData() != null) {
                     // Authentication successful
                     httpRequest.setAttribute("introspection-data", result.getIntrospectionData());
                     chain.doFilter(request, response);
                 }
             } catch (TokenValidationException e) {
                 httpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
             }
         }
    
         @Override
         public void destroy() {
             // Cleanup resources if needed
         }
     }
    

Configuration

@WebFilter annotation

Configure the filter by using the following parameters.

Parameter Description Example
urlPatterns URL patterns to protect /rest/*
initParams Filter initialization parameters scope=accessRestricted

Environment configuration

Update the following constants in the filter class to match your environment:

  • AUTHSERVER_URI: The base URI of your PMF authorization server.
  • CLIENT_ID: Your confidential client identifier.
  • CLIENT_SECRET: Your confidential client secret.
Last modified on