10 Securing Oracle Coherence REST

Authenticate REST callers, authorize operations, and constrain published resources and request-controlled expressions.

Coherence REST security combines the HTTP acceptor's authentication and TLS configuration with service/storage authorization and request-input policy. Configure each layer explicitly. The following topics retain the HTTP authentication setup; use Constraining REST Resources and Expressions for hardened resource/query policy.

Basic, client-certificate, and combined certificate-plus-Basic authentication are supported by the HTTP acceptor. Use TLS for credentials and verify which subject/principal is passed to authorization. A configured authentication scheme with an unusable security context must not be treated as a successful anonymous login in the hardened profile.

Protect both reads and mutations. A published resource name, a query predicate, and an authenticated user each convey different information; none substitutes for an authorization decision on the requested cache operation. Configure a storage authorizer for protected cache schemes and test denied access with valid credentials.

Serializer boundaries

JSON class metadata and XML parsing are input boundaries even for authenticated requests. Use REST JSON and XML Input Policy and the application serialization configuration. Preserve the selected marshaller and application types across client upgrades.

Constraining REST Resources and Expressions

Publish only intended cache resources and let callers select configured queries and expressions.

In the hardened profile, an unconfigured pass-through cache is not automatically published. Declare each public resource in coherence-rest-config.xml. An allowed resource still needs authentication and operation authorization where required.

This complete REST configuration illustrates a bounded resource and configured expression aliases. Replace the application value class with the deployed model and package its serializer/security resources. The attribute and child-element ordering follows the REST schema.

<rest xmlns="http://xmlns.oracle.com/coherence/coherence-rest-config">
  <resources>
    <resource name="people" max-results="100">
      <cache-name>people</cache-name>
      <key-class>java.lang.Integer</key-class>
      <value-class>com.example.model.Person</value-class>
      <query engine="DEFAULT">
        <name>adults</name>
        <expression>age &gt;= 18</expression>
      </query>
      <direct-query enabled="false" max-results="100"/>
      <expression-aliases>
        <sort-alias>
          <name>by-age</name>
          <expression>age</expression>
        </sort-alias>
        <projection-alias>
          <name>summary</name>
          <properties>name,age</properties>
        </projection-alias>
        <aggregator-argument-alias>
          <aggregator>long-sum</aggregator>
          <name>total-age</name>
          <expression>age</expression>
        </aggregator-argument-alias>
        <processor-argument-alias>
          <processor>increment</processor>
          <name>age-value</name>
          <expression>age</expression>
        </processor-argument-alias>
      </expression-aliases>
    </resource>
  </resources>
</rest>

The aggregator and processor names must exist in the deployed REST registry. Aliases approve expressions, not arbitrary implementations or an operation for every user. Restrict state-changing processor endpoints independently.

Query and alias use

Prefer named queries for public APIs. To permit direct q queries, set <direct-query enabled="true"> explicitly on the resource and choose a result bound. An empty <direct-query/> does not enable ordinary HTTP cache operations in either profile. Hardened mode requires enablement on the SSE path too and validates the supported REST-safe subset before evaluation. The legacy SSE compatibility path retains its bypass; do not depend on that behavior for a secured deployment.

Callers select configured aliases in URL sort/projection/aggregator/processor input. For example, a named-query request can select the approved sort with /people/adults;sort=by-age. Projection aliases use the projection input with the configured alias name. Test the exact URL, encoding, resource precedence, and processor/aggregator signature used by your released REST module. Compatibility callers can retain historical raw expressions; plan their migration before hardened activation.

Verification

  • Verify a declared resource and approved named query succeed for an authorized user.

  • In hardened mode, request an unconfigured pass-through resource and expect 404.

  • Under hardened policy, test both ordinary HTTP and SSE direct queries: disabled queries must fail with 403; an enabled supported predicate should succeed for an authorized caller, and an unsafe expression must fail with 400. Ordinary HTTP cache operations also enforce direct-query enablement in compatibility mode; the historical SSE compatibility path differs.

  • Verify configured aliases succeed and unknown/raw restricted expressions fail with 400.

  • Test a denied write with otherwise valid credentials. Resource/alias approval must not bypass operation authorization.

REST JSON and XML Input Policy

Resolve JSON types deliberately and retain XML external-entity protections on every parser path.

Hardened JSON metadata policy rejects class literals and arbitrary class-name fallback. Configure exact server-owned aliases for application types that require polymorphism. Package aliases do not satisfy the hardened @class metadata requirement. The resolved class must also meet the application class and executable policies for its eventual use.

For a deliberately configured serializer, the JsonSerializer builder modifier is an extension point for application aliases. The following factory fragment requires the Coherence JSON module; deploy the application class on the receiver and reference the factory from the intended serializer configuration.

var serializer = new com.oracle.coherence.io.json.JsonSerializer(
        Thread.currentThread().getContextClassLoader(),
        builder -> builder.addAlias("person", com.example.model.Person.class),
        false);

Test the actual REST marshaller and gRPC serializer path that consumes the configuration. A separately configured serializer does not reconfigure every JSON consumer. The gRPC JSON materialization path checks denied metadata in nested and statically typed values as well as untyped roots. Other paths have different contextual checks; do not assume that one gRPC check proves coverage for every REST marshaller. Verify unknown aliases, denied class metadata, and malformed input on the actual consuming path.

XML parser protections

Coherence applies external-entity and related parser protections before processing XML. If required protections cannot be applied, hardened policy fails closed. Compatibility can warn and retain its fallback behavior. Use a supported parser/provider that implements the required controls and resolve approved schemas/resources through the supported local mechanisms.

Keep product configuration resources and application XML inputs distinct. A controlled local schema source is not permission to fetch an arbitrary remote entity named by a request. A parser-capability failure requires fixing the parser/runtime configuration; do not globally enable external entities to make a request pass.

Failure diagnosis

Expect bounded class/alias or parser errors rather than serialized internal throwable graphs. Retain a safe request identifier and inspect server logs. Record the response status supplied by the actual marshaller/container, since not every JSON binding failure has the same transport mapping. See Security Errors and Diagnostic Signals.

Overview of Securing Oracle Coherence REST

Choose explicit REST authentication and authorization policies and account for the active security profile.

Configure HTTP Basic, client-certificate, or combined authentication on the REST HTTP acceptor. Choose a JAAS login module or trusted certificate-to-identity mapping that creates the principal required by the application's authorization policy. Authentication remains an explicit service choice; selecting the hardened profile does not automatically create every REST identity policy.

When REST authentication is engaged, hardened policy requires a usable principal. A null/blank principal or a failing security-context accessor produces an authentication failure rather than silently falling back to anonymous access. Compatibility retains the relevant historical behavior.

Explicitly publish allowed resources and configure query/expression aliases before switching to hardened behavior. Use Constraining REST Resources and Expressions. Storage-side authorization complements any Extend-style wrappers used by the REST service; see Authorizing Access to Server-Side Operations.

Using HTTP Basic Authentication with Oracle Coherence REST

You can configure an HTTP acceptor and login module to provide authentication for Coherence REST. HTTP basic authentication provides authentication using credentials (username and password) that are encoded and sent in the HTTP authorization request header. HTTP basic authentication requires a Java Authentication and Authorization Service (JAAS) login module.

This section includes the following topics:

Specify Basic Authentication for an HTTP Acceptor

To specify basic authentication for an HTTP Acceptor:

Add an <auth-method> element, within the http-acceptor element, that is set to basic.

<proxy-scheme>
   <service-name>RestHttpProxyService</service-name>
   <acceptor-config>
      <http-acceptor>
         ...
         <auth-method>basic</auth-method>
      </http-acceptor>
   </acceptor-config>
   <autostart>true</autostart>
</proxy-scheme>

Specify a Login Module

Configure the JAAS entry used by the standard REST HTTP authentication path.

The standard Coherence HTTP server uses the CoherenceREST JAAS entry for its Basic identity asserter. Configure a real login module for that entry and deploy its dependencies on the proxy's runtime classpath/module path. A custom HTTP server/identity integration can have a different entry name; verify the actual deployed configuration.

CoherenceREST {
  com.tangosol.security.KeystoreLogin required
    keyStorePath="/run/coherence/http-users.p12"
    keyStoreType="PKCS12";
};

This example uses the provided coherence-login module and a provisioned keystore identity. Set java.security.auth.login.config to the protected JAAS configuration file, satisfy the module's credential callback contract, and verify the resulting subject. Use a supported enterprise module where that identity system is required.

Do not install libraries into a JRE lib/ext directory on current JDKs. Use the application's supported dependency/classpath mechanism. Test invalid credentials and a denied operation with valid credentials as well as a successful login.

Using SSL Authentication With Oracle Coherence REST

You can use SSL to provide authentication for Coherence REST. SSL provides an authentication mechanism that relies on digital certificates and encryption keys to establish both identity and trust. See Overview of SSL/TLS.

Client-side SSL certificates are passed to the HTTP acceptor to authenticate the client. SSL requires an SSL-based socket provider to be configured for the HTTP acceptor. The below instructions only describe how to configure SSL and define an SSL socket provider on the proxy for an HTTP acceptor. Refer to your REST client library documentation for instructions on setting up SSL on the client side.

This section includes the following topics:

Specify Basic Authentication for an HTTP Acceptor

To specify basic authentication for an HTTP Acceptor:

Add an <auth-method> element, within the http-acceptor element, that is set to basic.

<proxy-scheme>
   <service-name>RestHttpProxyService</service-name>
   <acceptor-config>
      <http-acceptor>
         ...
         <auth-method>basic</auth-method>
      </http-acceptor>
   </acceptor-config>
   <autostart>true</autostart>
</proxy-scheme>

Configure an HTTP Acceptor SSL Socket Provider

Configure an SSL socket provider for an HTTP acceptor when using SSL for authentication. To configure SSL for an HTTP acceptor, explicitly add an SSL socket provider definition or reference an SSL socket provider definition that is in the operational override file.

Explicitly Defining an SSL Socket Provider

To explicitly configure an SSL socket provider for an HTTP acceptor, add a <socket-provider> element within the <http-acceptor> element of each <proxy-scheme> definition. See socket-provider in Developing Applications with Oracle Coherence.

Example 10-1 demonstrates configuring an SSL socket provider that uses the default values for the <protocol> and <algorithm> element (TLS and SunX509, respectively). These are shown for completeness but may be left out when using the default values.

Example 10-1 configures both an identity keystore (server.jks) and a trust keystore (trust.jks). This is typical of two-way SSL authentication, in which both the client and proxy must exchange digital certificates and confirm each other's identity. For one-way SSL authentication, the proxy server configuration must include an identity keystore but need not include a trust keystore.

Example 10-1 Sample HTTP Acceptor SSL Configuration

<proxy-scheme>
   <service-name>RestHttpProxyService</service-name>
   <acceptor-config>
      <http-acceptor>
         ...
         <socket-provider>
            <ssl>
               <protocol>TLS</protocol>
               <identity-manager>
                  <algorithm>SunX509</algorithm>
                  <key-store>
                     <url>file:server.jks</url>
                     <password>password</password>
                     <type>JKS</type>
                  </key-store>
                  <password>password</password>
               </identity-manager>
               <trust-manager>
                  <algorithm>SunX509</algorithm>
                  <key-store>
                     <url>file:trust.jks</url>
                     <password>password</password>
                     <type>JKS</type>
                  </key-store>
               </trust-manager>
            </ssl>
         </socket-provider>
         ...
         <auth-method>cert</auth-method>
      </http-acceptor>
   </acceptor-config>
   <autostart>true</autostart>
</proxy-scheme>

Referencing an SSL Socket Provider Definition

The following example references an SSL socket provider configuration that is defined in the <socket-providers> element of the operational deployment descriptor by specifying the id attribute (ssl) of the configuration. See socket-providers in Developing Applications with Oracle Coherence.

Note:

A predefined SSL socket provider is included in the operational deployment descriptor and is named ssl. The predefined SSL socket provider is configured for two-way SSL connections and is based on peer trust, in which every trusted peer resides within a single JKS keystore. See Coherence PeerX509 Algorithm for details. To configure a different SSL socket provider, use an operational override file to modify the predefined SSL socket provider or to create a socket provider configuration as required.

<proxy-scheme>
   <service-name>RestHttpProxyService</service-name>
   <acceptor-config>
      <http-acceptor>
         ...
         <socket-provider>ssl</socket-provider>
         ...
         <auth-method>cert</auth-method>
      </http-acceptor>
   </acceptor-config>
   <autostart>true</autostart>
</proxy-scheme>

Access Secured REST Services

The following example demonstrates a Jersey-based client that accesses REST services that require certificate and HTTP basic authentication.

Client SSL Configuration File

The client SSL configuration file (ssl.xml) configures the client's keystore and trust keystore.

<ssl>
  <identity-manager>
    <key-store>
      <url>file:keystore.jks</url>
      <password>password</password>
    </key-store>
    <password>password</password>
  </identity-manager>
  <trust-manager>
    <key-store>
      <url>file:trust.jks</url>
      <password>password</password>
    </key-store>
  </trust-manager>
</ssl>

Sample Jersey SSL Client

package example;
import com.oracle.coherence.common.net.SSLSocketProvider;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.client.urlconnection.HTTPSProperties;
import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
import com.tangosol.internal.net.ssl.LegacyXmlSSLSocketProviderDependencies;
import com.tangosol.run.xml.XmlDocument;
import com.tangosol.run.xml.XmlHelper;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
import jakarta.ws.rs.core.MediaType;
 
public class SslExample
   {
   public static Client createHttpsClient(SSLSocketProvider provider)
      {
      DefaultClientConfig dcc = new DefaultClientConfig();
      HTTPSProperties prop = new HTTPSProperties(new HostnameVerifier()
         {
         public boolean verify(String s, SSLSession sslSession)
            {
               return true;
            }
         }, provider.getDependencies().getSSLContext());
      dcc.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, prop);
      return Client.create(dcc);
      }
 
   public static void PUT(String url, MediaType mediaType, String data)
      {
      process(url, "put", mediaType, data);
      }
 
   public static void GET(String url, MediaType mediaType)
      {
      process(url, "get", mediaType, null);
      }
 
   public static void POST(String url, MediaType mediaType, String data)
      {
      process(url, "post", mediaType, data);
      }
 
   public static void DELETE(String url, MediaType mediaType)
      {
      process(url, "delete", mediaType, null);
      }
 
   static void process(String url, String action, MediaType mediaType, String
      data)
      {
      try
         {
         XmlDocument xml = XmlHelper.loadFileOrResource("/ssl.xml", null);
         SSLSocketProvider provider = new SSLSocketProvider(new
            LegacyXmlSSLSocketProviderDependencies(xml));
         Client client = createHttpsClient(provider);
         ClientResponse response = null;
         WebResource webResource = client.resource(url);

         // If you've specified the "cert+basic" auth-method in your Proxy
         // http-acceptor configuration, initialize and add an HTTP basic
         // authentication filter by
         // uncommenting the following line and changing the username and password
         // appropriately.
         //client.addFilter(new HTTPBasicAuthFilter("username", "password"));

         if (action.equalsIgnoreCase("get"))
            {
            response = webResource.type(mediaType).get(ClientResponse.class);
            }
         else if (action.equalsIgnoreCase("post"))
            {
            response = webResource.type(mediaType).post
               (ClientResponse.class, data);
            }
         else if (action.equalsIgnoreCase("put"))
            {
            response = webResource.type(mediaType).put
               (ClientResponse.class, data);
            }
         else if (action.equalsIgnoreCase("delete"))
            {
            response = webResource.type(mediaType).delete
               (ClientResponse.class, data);
            }
         System.out.println("response status:" + response.getStatus());
         if (action.equals("get"))
            {
            System.out.println("Result: " + response.getEntity(String.class));
            }
         }
      catch (Exception e)
         {
         e.printStackTrace();
         }
      }
 
   public static void main(String args[])
      {
      PUT("https://localhost:8080/dist-http-example/1",
         MediaType.APPLICATION_JSON_TYPE, "{\"name\":\"chris\",\"age\":32}");
      PUT("https://localhost:8080/dist-http-example/2",
         MediaType.APPLICATION_XML_TYPE,
         "<person><name>admin</name><age>30</age></person>");
      DELETE("https://localhost:8080/dist-http-example/1",
         MediaType.APPLICATION_XML_TYPE);
      GET("https://localhost:8080/dist-http-example/2",
         MediaType.APPLICATION_XML_TYPE);
      }
   }

Using SSL and HTTP Basic Authentication with Oracle Coherence REST

You can use SSL together with HTTP basic authentication for added protection when securing Coherence REST. See Using HTTP Basic Authentication with Oracle Coherence REST and Using SSL Authentication With Oracle Coherence REST, respectively.

To specify the use of both HTTP basic authentication and SSL, add an <auth-method> element, within the http-acceptor element, that is set to cert+basic.

<proxy-scheme>
   <service-name>RestHttpProxyService</service-name>
   <acceptor-config>
      <http-acceptor>
         ...
         <socket-provider>
            <ssl>
            ...
            </ssl>
         </socket-provider>
         ...
         <auth-method>cert+basic</auth-method>
      </http-acceptor>
   </acceptor-config>
   <autostart>true</autostart>
</proxy-scheme>

Implementing Authorization For Oracle Coherence REST

Oracle Coherence REST relies on the Oracle Coherence*Extend authorization framework to restrict which operations a REST client performs on a cluster. For detailed instructions on implementing Oracle Coherence*Extend-style authorization, see Implementing Extend Client Authorization.

Oracle Coherence*Extend-style authorization with REST requires basic HTTP authentication or HTTP basic authentication together with SSL authentication. That is, when implementing authorization, both HTTP basic authentication and SSL can be used together for added protection. For details on using HTTP basic authentication, see Using HTTP Basic Authentication with Oracle Coherence REST. For details on using SSL with HTTP Basic Authentication, see Using SSL and HTTP Basic Authentication with Oracle Coherence REST.

Note:

When using SSL and HTTP basic authentication together, make sure that SSL is setup as shown in Using SSL Authentication With Oracle Coherence REST in addition to setting up HTTP basic authentication.