Access filters for JSON-RPC 2.0 services

Services on the web often have to be controlled for who and how accesses them. If they deal with sensitive data, such as usernames and passwords, you may want to ensure that all requests come in over encrypted HTTPS. If you’re running a private service, you may want to ensure that only selected internet hosts can make use of it. Or you may want to limit access to portions of the web API, such as administration, to selected users and clients.

For this purpose I created an Access Filter package for JSON-RPC 2.0 services. Today I released it to the public in its stable 1.1 version under a generous Apache 2.0 licence. I wanted filtering to be fast and robust, so the package was designed to be as simple and efficient as possible. It also nicely complements the proven Java libraries JSON-RPC 2.0 Base and JSON-RPC 2.0 Server.

The package defines four basic filters:

  • HostFilter Access filter ensuring JSON-RPC 2.0 requests originate from selected host names / IP addresses.
  • HTTPSFilter Access filter ensuring requests are passed over HTTPS.
  • X509ClientCertFilter Access filter ensuring HTTPS requests carry an X.509 client certificate with optional specified principal (subject DN).
  • APIKeyFilter Access filter ensuring clients present an API key for protected JSON-RPC 2.0 request methods.

There is a ready CompositeFitler which combines these four basic filters into a chain. You can then plug this filter chain into your JSON-RPC 2.0 service and call it prior to passing the incoming requests to the actual execution logic.

The CompositeFilter can be configured with a simple properties text file. The properties format is detailed in the JavaDocs for the CompositeFilterConfiguration class.

access.https.require=true
access.https.requireClientCert=true
access.https.clientCertPrincipal=cn=John Doe,ou=people,cd=company,dc=org
 
access.hosts.allow=*
 
access.apiKeys.require=true
access.apiKeys.exemptedMethods=ws.getName ws.getVersion ws.getTime
access.apiKeys.map.f70defbe-b881-41f8-8138-bea52b6e1b9c=sso.login sso.logout sso.getSession
access.apiKeys.map.08d1e641-b1c1-4d88-8796-e47c06430efb=sso.proxiedLogin sso.proxiedLogout sso.getSession
access.apiKeys.map.d881afe0-4d7d-4520-9fda-bffffc3022ba=sso.userCount sso.sessionCount sso.listUsers

Alternatively, you may devise your own custom filter chain, based on the AccessFilterChain class.

How do you use the CompositeFitler?

// Parse config from properties, create composite filter
java.util.Properties props = ...
CompositeFilter filter = new CompositeFilter();
filter.init(new CompositeFilterConfiguration(props)); 

// Invoke the filter for each incoming JSON-RPC 2.0 request

// Parse JSON-RPC 2.0 request
JSONRPC2Request request = JSONRPC2Request.parse(...);

// Set the message context, i.e. client host IP, etc.
MessageContext mctx = new MessageContext(...);

// Call the filter
AccessFilterResult result = filter.filter(request, mctx);

if (result.accessAllowed()) {
    // Continue with request processing...

}
else {
    // Return specified access denied JSON-RPC 2.0 error
    // to the calling client
    JSONRPC2Error error = result.getAccessDeniedError().toJSONRPC2Error();
}

The Access Filter package is available at Bitbucket: https://bitbucket.org/vdzhuvinov/access-filter/

We plan to integrate into the upcoming new releases of the Json2Ldap, NimbusSSO and AuthService web services from NimbusDS software.

If you have comments of feedback to share, get in touch or leave a ticket at the Bitbucket repo.