5 Using SSL Authentication in Java Clients

The Java Secure Socket Extension (JSSE) is a set of packages that support and implement the SSL and TLS protocols. Oracle WebLogic Server provides Secure Sockets Layer (SSL) support for encrypting data transmitted between WebLogic Server clients and servers, Java clients, Web browsers, and other servers. Learn how to implement SSL and digital certificate authentication in Java clients.

The sections refer to sample code which is optionally included in the WebLogic Server distribution at:

EXAMPLES_HOME\src\examples\security\sslclient

The EXAMPLES_HOME directory can be found at ORACLE_HOME\wlserver\samples\server\examples.

The sslclient directory contains an instructions.html file, ant build files, and the following Java and JavaServer Pages (.jsp) files:

  • MyListener.java

  • NulledHostnameVerifier.java

  • NulledTrustManager.java

  • SSLClient.java

  • SSLClientServlet.java

  • SSLSocketClient.java

  • SnoopServlet.jsp

You will need to look at the examples when reading the information in the following sections.

JSSE and WebLogic Server

There are certain restrictions when using SSL in WebLogic server-side applications.

The JSSE implementation of WebLogic Server can be used by WebLogic clients, but is not required. Other JSSE implementations can be used for their client-side code outside the server as well.

Note:

JSSE is the only SSL implementation that is supported. The Certicom-based SSL implementation is removed and is no longer supported in WebLogic Server.

The following restrictions apply when using SSL in WebLogic server-side applications:

  • The use of other (third-party) JSSE implementations to develop WebLogic Server applications is not supported. The SSL implementation that WebLogic Server uses is static to the server configuration and is not replaceable by customer applications.

  • The WebLogic implementation of JSSE does support JCE Cryptographic Service Providers (CSPs); however, due to the inconsistent provider support for JCE, Oracle cannot guarantee that untested providers will work out of the box. Oracle has tested WebLogic Server with the following providers:

    Other providers may work with WebLogic Server, but an untested provider is not likely to work out of the box. For more information on using the JCE providers supported by WebLogic Server, see Using JCE Providers with WebLogic Server in Administering Security for Oracle WebLogic Server.

WebLogic Server uses the HTTPS port for Secure Sockets Layer (SSL) encrypted communication; only SSL can be used on that port.

Note:

In order to implement security in a WebLogic client, you must install the WebLogic Server software distribution kit on the Java client.

Note:

Although JSSE supports Server Name Indication (SNI) in its SSL implementation, WebLogic Server does not support SNI.

Using JNDI Authentication

Java clients use the Java Naming and Directory Interface (JNDI) to pass credentials to WebLogic Server. A Java client establishes a connection with Oracle WebLogic Server by getting a JNDI InitialContext. The Java client then uses the InitialContext to look up the resources it needs in the Oracle WebLogic Server JNDI tree.

Note:

JAAS is the preferred method of authentication; however, the Authentication provider's LoginModule supports only username and password authentication. Thus, for client certificate authentication (also referred to as two-way SSL authentication), you should use JNDI. To use JAAS for client certificate authentication, you must write a custom Authentication provider whose LoginModule does certificate authentication.

To specify a user and the user's credentials, set the JNDI properties listed in Table 5-1.

Table 5-1 JNDI Properties Used for Authentication

Property Meaning
INITIAL_CONTEXT_FACTORY 

Provides an entry point into the Oracle WebLogic Server environment. The class weblogic.jndi.WLInitialContextFactory is the JNDI SPI for Oracle WebLogic Server.

PROVIDER_URL 

Specifies the host and port of the WebLogic Server that provides the name service. For example: t3s://weblogic:7002.

(t3s is a WebLogic Server proprietary version of SSL.)

SECURITY_PRINCIPAL 

Specifies the identity of the user when that user authenticates to the default (active) security realm.

SECURITY_CREDENTIALS 

Specifies the credentials of the user when that user authenticates to the default (active) security realm.

These properties are stored in a hash table which is passed to the InitialContext constructor.

Example 5-1 demonstrates how to use one-way SSL certificate authentication in a Java client. For a two-SSL authentication code example, see Example 5-4.

Note:

For information on JNDI contexts and threads and how to avoid potential JNDI context problems, see JNDI Contexts and Threads and How to Avoid Potential JNDI Context Problems in Developing JNDI Applications for Oracle WebLogic Server.

Example 5-1 Example One-Way SSL Authentication Using JNDI

...
Hashtable env = new Hashtable();
      env.put(Context.INITIAL_CONTEXT_FACTORY,
              "weblogic.jndi.WLInitialContextFactory");
      env.put(Context.PROVIDER_URL, "t3s://weblogic:7002");
      env.put(Context.SECURITY_PRINCIPAL, "javaclient");
      env.put(Context.SECURITY_CREDENTIALS, "javaclientpassword");
      Context ctx = new InitialContext(env);

SSL Certificate Authentication Development Environment

To implement SSL authentication in WebLogic Server, you can use a combination of Java application programming interfaces (APIs) and WebLogic APIs. There are certain components of SSL client application such as, HostnameVerifier and TrustManager, that facilitate the implementation of SSL in WebLogic Server.

The following topics are covered in this section:

SSL Authentication APIs

To implement Java clients that use SSL authentication on WebLogic Server, use a combination of Java application programming interfaces (APIs) and WebLogic APIs.

Table 5-2 lists and describes the Java APIs packages used to implement certificate authentication. The information in this table is taken from the Java API documentation and annotated to add WebLogic Server specific information. For more information on the Java APIs, see the Javadocs at http://docs.oracle.com/javase/8/docs/api/index.html and https://javaee.github.io/javaee-spec/javadocs/index.html?overview-summary.html.

Table 5-3 lists and describes the WebLogic APIs used to implement certificate authentication. See Java API Reference for Oracle WebLogic Server.

Table 5-2 Java Certificate APIs

Java Certificate APIs Description

javax.crypto (http://docs.oracle.com/javase/8/docs/api/index.html)

This package provides the classes and interfaces for cryptographic operations. The cryptographic operations defined in this package include encryption, key generation and key agreement, and Message Authentication Code (MAC) generation.

Support for encryption includes symmetric, asymmetric, block, and stream ciphers. This package also supports secure streams and sealed objects.

Many classes provided in this package are provider-based (see the java.security.Provider class). The class itself defines a programming interface to which applications may be written. The implementations themselves may then be written by independent third-party vendors and plugged in seamlessly as needed. Therefore, application developers can take advantage of any number of provider-based implementations without having to add or rewrite code.

javax.net (http://docs.oracle.com/javase/8/docs/api/index.html)

This package provides classes for networking applications. These classes include factories for creating sockets. Using socket factories you can encapsulate socket creation and configuration behavior.

javax.net.SSL (http://docs.oracle.com/javase/8/docs/api/index.html)

While the classes and interfaces in this package are supported by WebLogic Server, Oracle recommends that you use the weblogic.security.SSL package when you use SSL with WebLogic Server.

java.security.cert (http://docs.oracle.com/javase/8/docs/api/index.html)

This package provides classes and interfaces for parsing and managing certificates, certificate revocation lists (CRLs), and certification paths. It contains support for X.509 v3 certificates and X.509 v2 CRLs.

java.security.KeyStore (http://docs.oracle.com/javase/8/docs/api/index.html)

This class represents an in-memory collection of keys and certificates. It is used to manage two types of keystore entries:

  • Key Entry

    This type of keystore entry holds cryptographic key information, which is stored in a protected format to prevent unauthorized access.

    Typically, a key stored in this type of entry is a secret key, or a private key accompanied by the certificate chain for the corresponding public key.

    Private keys and certificate chains are used by a given entity for self-authentication. Applications for this authentication include software distribution organizations that sign JAR files as part of releasing and/or licensing software.

  • Trusted Certificate Entry

    This type of entry contains a single public key certificate belonging to another party. It is called a trusted certificate because the keystore owner trusts that the public key in the certificate indeed belongs to the identity identified by the subject (owner) of the certificate.

    This type of entry can be used to authenticate other parties.

java.security.PrivateKey (http://docs.oracle.com/javase/8/docs/api/index.html)

A private key. This interface contains no methods or constants. It merely serves to group (and provide type safety for) all private key interfaces.

Note: The specialized private key interfaces extend this interface. For example, see the DSAPrivateKey interface in java.security.interfaces.

java.security.Provider (http://docs.oracle.com/javase/8/docs/api/index.html)

This class represents a "Cryptographic Service Provider" for the Java Security API, where a provider implements some or all parts of Java Security, including:

  • Algorithms (such as DSA, RSA, MD5 or SHA-1).

  • Key generation, conversion, and management facilities (such as for algorithm-specific keys).

Each provider has a name and a version number, and is configured in each runtime it is installed in.

To supply implementations of cryptographic services, a team of developers or a third-party vendor writes the implementation code and creates a subclass of the Provider class.

javax.servlet.http.HttpServletRequest (https://javaee.github.io/javaee-spec/javadocs/javax/servlet/http/package-summary.html)

This interface extends the ServletRequest interface to provide request information for HTTP servlets.

The servlet container creates an HttpServletRequest object and passes it as an argument to the servlet's service methods (doGet, doPost, and so on.).

javax.servlet.http.HttpServletResponse (https://javaee.github.io/javaee-spec/javadocs/javax/servlet/http/package-summary.html)

This interface extends the ServletResponse interface to provide HTTP-specific functionality in sending a response. For example, it has methods to access HTTP headers and cookies.

The servlet container creates an HttpServletRequest object and passes it as an argument to the servlet's service methods (doGet, doPost, and so on.).

javax.servlet.ServletOutputStream (https://javaee.github.io/javaee-spec/javadocs/javax/servlet/package-summary.html)

This class provides an output stream for sending binary data to the client. A ServletOutputStream object is normally retrieved via the ServletResponse.getOutputStream() method.

This is an abstract class that the servlet container implements. Subclasses of this class must implement the java.io.OutputStream.write(int) method.

javax.servlet.ServletResponse (https://javaee.github.io/javaee-spec/javadocs/javax/servlet/package-summary.html)

This class defines an object to assist a servlet in sending a response to the client. The servlet container creates a ServletResponse object and passes it as an argument to the servlet's service methods (doGet, doPost, and so on.).

Table 5-3 WebLogic Certificate APIs

WebLogic Certificate APIs Description

weblogic.net.http.HttpsURLConnection

This class is used to represent a HTTP with SSL (HTTPS) connection to a remote object. Use this class to make an outbound SSL connection from a WebLogic Server acting as a client to another WebLogic Server.

weblogic.security.SSL.HostnameVerifier

During an SSL handshake, hostname verification establishes that the hostname in the URL matches the hostname in the server's identification; this verification is necessary to prevent man-in-the-middle attacks.

WebLogic Server provides a certificate-based implementation of HostnameVerifier which is used by default, and which verifies that the URL hostname matches the CN field value of the server certificate.

You can replace this default hostname verifier with a custom hostname verifier by using the Advanced Options pane under the WebLogic Server Administration Console SSL tab; this will affect the default for SSL clients running on the server using the WebLogic SSL APIs. In addition, WebLogic SSL APIs such as HttpsURLConnection, and SSLContext allow the explicit setting of a custom HostnameVerifier.

weblogic.security.SSL.TrustManager

This interface permits the user to override certain validation errors in the peer's certificate chain and allow the handshake to continue. This interface also permits the user to perform additional validation on the peer certificate chain and interrupt the handshake if need be.

weblogic.security.SSL.CertPathTrustManager

This class makes use of the configured CertPathValidation providers to perform extra validation; for example, revocation checking.

By default, CertPathTrustManager is installed but configured not to call the CertPathValidators (controlled by the SSLMBean attributes InboundCertificateValidation and OutboundCertificateValidation).

Applications that install a custom TrustManager will replace CertPathTrustManager. An application that wants to use a custom TrustManager, and call the CertPathProviders at the same time, can delegate to a CertPathTrustManager from its custom TrustManager.

weblogic.security.SSL.SSLContext

This class holds all of the state information shared across all sockets created under that context.

weblogic.security.SSL.SSLSocketFactory

This class provides the API for creating SSL sockets.

weblogic.security.SSL.SSLValidationConstants

This class defines context element names. SSL performs some built-in validation before it calls one or more CertPathValidator objects to perform additional validation. A validator can reduce the amount of validation it must do by discovering what validation has already been done.

SSL Client Application Components

At a minimum, an SSL client application includes the following components:

  • Java client

    Typically, a Java client performs these functions:

    • Initializes an SSLContext with client identity, trust, a HostnameVerifier, and a TrustManager.

    • Loads a keystore and retrieves the private key and certificate chain

    • Uses an SSLSocketFactory

    • Uses HTTPS to connect to a JSP served by an instance of WebLogic Server

  • HostnameVerifier

    The HostnameVerifier implements the weblogic.security.SSL.HostnameVerifier interface.

  • HandshakeCompletedListener

    The HandshakeCompletedListener implements the javax.net.ssl.HandshakeCompletedListener interface. It is used by the SSL client to receive notifications about the completion of an SSL handshake on a given SSL connection.

  • TrustManager

    The TrustManager implements the weblogic.security.SSL.TrustManager interface.

For a complete working SSL authentication client that implements the components described here, see the SSLClient sample application in EXAMPLES_HOME\src\examples\security\sslclient, where EXAMPLES_HOME represents the directory in which the WebLogic Server code examples are configured and can be found at ORACLE_HOME\wlserver\samples\server.

For more information on JSSE authentication, see Java Secure Socket Extension (JSSE) Reference Guide available at http://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html.

Writing Applications that Use SSL

When you write an application that uses SSL, consider how the application will be used and the special requirements it has for secure communication, such as whether the application is hosted on a WebLogic Server instance acting as a client to another WebLogic Server instance. Other considerations include whether you need to use two-way SSL, a custom host name verifier, a Trust Manager, or other security artifacts.

Communicating Securely From WebLogic Server to Other WebLogic Servers

You can use a URL object to make an outbound SSL connection from a WebLogic Server instance acting as a client to another WebLogic Server instance. The weblogic.net.http.HttpsURLConnection class provides a way to specify the security context information for a client, including the digital certificate and private key of the client.

The weblogic.net.http.HttpsURLConnection class provides methods for determining the negotiated cipher suite, getting/setting a hostname verifier, getting the server's certificate chain, and getting/setting an SSLSocketFactory in order to create new SSL sockets.

The SSLClient code example uses the weblogic.net.http.HttpsURLConnection class to make an outbound SSL connection. The SSLClient code example is available in the examples.security.sslclient package in EXAMPLES_HOME\src\examples\security\sslclient, where EXAMPLES_HOME represents the directory in which the WebLogic Server code examples are configured and can be found at ORACLE_HOME\wlserver\samples\server.

Writing SSL Clients

This section uses examples to show how to write various types of SSL clients. Examples of the following types of SSL clients are provided:

SSLClient Sample

The SSLClient sample demonstrates how to use the WebLogic SSL library to make outgoing SSL connections using URL and URLConnection objects. It shows both how to do this from a stand-alone application as well as from a servlet in WebLogic Server.

Note:

WebLogic Server acting as an SSL client uses the server's identity certificate for outgoing SSL connections. Applications running on WebLogic Server and using the previously described SSL APIs do not share the server's identity certificates by default, only the trust.

Example 5-2 shows code fragments from the SSLClient example; the complete example is located in the EXAMPLES_HOME\src\examples\security\sslclient directory in the SSLClient.java file.

The EXAMPLES_HOME directory can be found at ORACLE_HOME\wlserver\samples\server.

Example 5-2 SSLClient Sample Code Fragments

package examples.security.sslclient;

import java.io.*;
import java.net.URL;
import java.security.Provider;
import javax.servlet.ServletOutputStream;
...
  /*
   * This method contains an example of how to use the URL and
   *  URLConnection objects to create a new SSL connection, using
   *  WebLogic SSL client classes.
   */
  public void wlsURLConnect(String host, String port,
                            String sport, String query,
                            OutputStream out)
      throws Exception {
...
      URL wlsUrl = null;
      try {
        wlsUrl = new URL("http", host, Integer.valueOf(port).intValue(),
                               query);
        weblogic.net.http.HttpURLConnection connection =
            new weblogic.net.http.HttpURLConnection(wlsUrl);
        tryConnection(connection, out);
      } 
...
      wlsUrl = new URL("https", host, Integer.valueOf(sport).intValue(),
                             query);
      weblogic.net.http.HttpsURLConnection sconnection =
          new weblogic.net.http.HttpsURLConnection(wlsUrl);
...
SSLSocketClient Sample

The SSLSocketClient sample demonstrates how to use SSL sockets to go directly to the secure port to connect to a JSP served by an instance of WebLogic Server and display the results of that connection. It shows how to implement the following functions:

  • Initializing an SSLContext with client identity, a HostnameVerifier, and a TrustManager

  • Loading a keystore and retrieving the private key and certificate chain

  • Using an SSLSocketFactory

  • Using HTTPS to connect to a JSP served by WebLogic Server

  • Implementing the javax.net.ssl.HandshakeCompletedListener interface

  • Creating a dummy implementation of the weblogic.security.SSL.HostnameVerifier class to verify that the server the example connects to is running on the desired host

Example 5-3 shows code fragments from the SSLSocketClient example; the complete example is located in the EXAMPLES_HOME\src\examples\security\sslclient directory in the SSLSocketClient.java file. (The SSLClientServlet example in the sslclient directory is a simple servlet wrapper of the SSLClient example.) The EXAMPLES_HOME directory can be found at ORACLE_HOME\wlserver\samples\server.

Example 5-3 SSLSocketClient Sample Code Fragments

package examples.security.sslclient;

import java.io.*;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import javax.net.ssl.HandshakeCompletedListener;
import javax.net.ssl.SSLSocket;
import weblogic.security.SSL.HostnameVerifier;
import weblogic.security.SSL.SSLContext;
import weblogic.security.SSL.SSLSocketFactory;
import weblogic.security.SSL.TrustManager;
...
      SSLContext sslCtx = SSLContext.getInstance("https");
      File KeyStoreFile  = new File ("mykeystore");
...
    // Open the keystore, retrieve the private key, and certificate chain
      KeyStore ks = KeyStore.getInstance("jks");
      ks.load(new FileInputStream("mykeystore"), null);
      PrivateKey key = (PrivateKey)ks.getKey("mykey",
                            "testkey".toCharArray());
      Certificate [] certChain = ks.getCertificateChain("mykey");
      sslCtx.loadLocalIdentity(certChain, key);
      HostnameVerifier hVerifier = null;
      if (argv.length < 3)
        hVerifier = new NulledHostnameVerifier();
      else
         hVerifier = (HostnameVerifier)
                         Class.forName(argv[2]).newInstance();

      sslCtx.setHostnameVerifier(hVerifier);
      TrustManager tManager = new NulledTrustManager();
      sslCtx.setTrustManager(tManager);
       System.out.println(" Creating new SSLSocketFactory with SSLContext");
      SSLSocketFactory sslSF = (SSLSocketFactory)
                                      sslCtx.getSocketFactory();
      System.out.println(" Creating and opening new SSLSocket with
                           SSLSocketFactory");
      // using createSocket(String hostname, int port)
      SSLSocket sslSock = (SSLSocket) sslSF.createSocket(argv[0],
                           new Integer(argv[1]).intValue());
      System.out.println(" SSLSocket created");
       HandshakeCompletedListener mListener = null;
        mListener = new MyListener();
       sslSock.addHandshakeCompletedListener(new MyListener());
      ...

Using Two-Way SSL Authentication

When using certificate authentication, Oracle WebLogic Server sends a digital certificate to the requesting client. The client examines the digital certificate to ensure that it is authentic, has not expired, and matches the Oracle WebLogic Server instance that presented it.

With two-way SSL authentication (a form of mutual authentication), the requesting client also presents a digital certificate to Oracle WebLogic Server. When the instance of WebLogic Server is configured for two-way SSL authentication, requesting clients are required to present digital certificates from a specified set of certificate authorities. Oracle WebLogic Server accepts only digital certificates that are signed by trusted certificate authorities.

For information on how to configure WebLogic Server for two-way SSL authentication, see the Configuring SSL in Administering Security for Oracle WebLogic Server.

The following sections describe the different ways two-way SSL authentication can be implemented in WebLogic Server.

Two-Way SSL Authentication with JNDI

When using JNDI for two-way SSL authentication in a Java client, use the setSSLContext() method in the WebLogic JNDI Environment class to set the SSLContext onto the current thread for client authentication.

To use setSSLContext(SSLContext sslctx), you pass an SSLContext, with a client certificate created from trustManager and keyManager, to the server using JNDI when the server is configured for two-way SSL. See Class SSLContext in Java™ Platform, Standard Edition 8 API Specification.

Note:

Invoking the setSSLContext method requires the WebLogic thin T3 client (wlthint3client.jar).

setSSLClientCertificate() and setSSLClientKeyPassword() have been deprecated in this release.

Example 5-4 demonstrates how to use the setSSLContext() method for two-way SSL authentication in a Java client.

Example 5-4 Example of a Two-Way SSL Authentication Client That Uses JNDI Environment setSSLContext Method

import weblogic.jndi.Environment;

import javax.naming.Context;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.SecureRandom;

public class JNDISSLContextClient {
  public static void main(String[] args) throws Exception {
    Context jndiContext = null;
    SSLContext sslContext = null;

    try {
      String identityKeyStore = "path_to_the_identity_keystore";
      String identityKeyStoreType = "type of the identity keystore, e.g. JKS";
      String identityKSPwd = "password_of_the_identity_keystore";
      String alias = "alias_of_identity_certificate_entry";
      String aliasPwd = "pass_word_of_the_alias";
      String trustKeyStore = "path_to_the_identity_keystore";
      String trustKeyStoreType = "type of the trust keystore, e.g. JKS";
      String trustKSPwd = "password_of_the_identity_keystore";

      sslContext = createSSLContext(identityKeyStore, identityKeyStoreType, identityKSPwd, alias, aliasPwd, trustKeyStore, trustKeyStoreType, trustKSPwd);

      Environment env = new Environment();
      String url = "t3s://localhost:7002";
      env.setProviderUrl(url);  
      // The next two set methods are optional if you are using
      // a UserNameMapper interface.
      env.setSecurityPrincipal("system");
      env.setSecurityCredentials("weblogic");

      env.setSSLContext(sslContext);
      env.setInitialContextFactory(Environment.DEFAULT_INITIAL_CONTEXT_FACTORY);

      jndiContext = env.getInitialContext();
      Object ejbObj = jndiContext.lookup("ejb");
      // ...
    } finally {
      if (jndiContext != null) jndiContext.close();
    }
  }

  /**
   *
   * @param identityKeyStore the identity keystore, which might contain more than one entry
   * @param identityKeyStoreType
   * @param identityKeyStorePassword
   * @param identityAlias
   * @param identityAliasPassword
   * @param trustKeyStore
   * @param trustKeyStoreType
   * @param trustKeyStorePassword
   * @param trustKeyStorePassword
   * @return an SSLContext created from the input parameters
   */
  private static SSLContext createSSLContext(String identityKeyStore, String identityKeyStoreType, String identityKeyStorePassword, String identityAlias, String identityAliasPassword,
                                      String trustKeyStore, String trustKeyStoreType, String trustKeyStorePassword) throws Exception {
    //Read the private key and certificate entry under the given alias
    KeyStore identityKS = KeyStore.getInstance(identityKeyStoreType);
    identityKS.load(new java.io.FileInputStream(identityKeyStore), identityKeyStorePassword.toCharArray());
    KeyStore.Entry entry = identityKS.getEntry(identityAlias, new KeyStore.PasswordProtection(identityAliasPassword.toCharArray()));

    //KeyStore instance used for the ssl context
    KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
    keystore.load(null, null);

    PrivateKey key = ((KeyStore.PrivateKeyEntry)entry).getPrivateKey();
    java.security.cert.Certificate[] cert = ((KeyStore.PrivateKeyEntry)entry).getCertificateChain();
    byte[] pwd = new byte[10];
    new SecureRandom().nextBytes(pwd);
    char[] entryPassword = new String(pwd).toCharArray();
    byte[] alias = new byte[10];
    new SecureRandom().nextBytes(alias);
    keystore.setKeyEntry(new String(alias), key, entryPassword, cert);
    KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    kmf.init(keystore, entryPassword);
    KeyManager[] keyManagers = kmf.getKeyManagers();

    KeyStore truststore;
    truststore = KeyStore.getInstance(trustKeyStoreType);
    truststore.load(new java.io.FileInputStream(trustKeyStore), trustKeyStorePassword.toCharArray());
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmf.init(truststore);
    TrustManager[] trustManagers = tmf.getTrustManagers();

    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(keyManagers, trustManagers, null);

    return sslContext;
  }
}

Note:

Security provider plug-ins are loaded from the system classpath. The system classpath must specify the implementation of a custom weblogic.security.providers.authentication.UserNameMapper interface.

If you have not configured an Identity Assertion provider that performs certificate-based authentication, a Java client running in a JVM with an SSL connection can change the Oracle WebLogic Server user identity by creating a new JNDI InitialContext and supplying a new user name and password in the JNDI SECURITY_PRINCIPAL and SECURITY_CREDENTIALS properties. Any digital certificates passed by the Java client after the SSL connection is made are not used. The new Oracle WebLogic Server user continues to use the SSL connection negotiated with the initial user's digital certificate.

If you have configured an Identity Assertion provider that performs certificate-based authentication, Oracle WebLogic Server passes the digital certificate from the Java client to the class that implements the UserNameMapper interface and the UserNameMapper class maps the digital certificate to a Oracle WebLogic Server user name. Therefore, if you want to set a new user identity when you use the certificate-based identity assertion, you cannot change the identity. This is because the digital certificate is processed only at the time of the first connection request from the JVM for each Environment.

Note:

Multiple, concurrent, user logins to WebLogic Server from a single client JVM when using two-way SSL and JNDI is not supported. If multiple logins are executed on different threads, the results are undeterminable and might result in one user's requests being executed on another user's login, thereby allowing one user to access another user's data. WebLogic Server does not support multiple, concurrent, certificate-based logins from a single client JVM. For information on JNDI contexts and threads and how to avoid potential JNDI context problems, see JNDI Contexts and Threads and How to Avoid Potential JNDI Context Problems in Developing JNDI Applications for Oracle WebLogic Server.

When the JNDI getInitialContext() method is called, the Java client and Oracle WebLogic Server execute mutual authentication in the same way that a Web browser performs mutual authentication to get a secure Web server connection. An exception is thrown if the digital certificates cannot be validated or if the Java client's digital certificate cannot be authenticated in the default (active) security realm. The authenticated user object is stored on the Java client's server thread and is used for checking the permissions governing the Java client's access to any protected WebLogic resources.

When you use the WebLogic JNDI Environment class, you must create a new Environment object for each call to the getInitialContext() method. Once you specify a User object and security credentials, both the user and their associated credentials remain set in the Environment object. If you try to reset them and then call the JNDI getInitialContext() method, the original user and credentials are used.

When you use two-way SSL authentication from a Java client, Oracle WebLogic Server gets a unique Java Virtual Machine (JVM) ID for each client JVM so that the connection between the Java client and Oracle WebLogic Server is constant. Unless the connection times out from lack of activity, it persists as long as the JVM for the Java client continues to execute. The only way a Java client can negotiate a new SSL connection reliably is by stopping its JVM and running another instance of the JVM.

The code in Example 5-4 generates a call to the WebLogic Identity Assertion provider that implements the weblogic.security.providers.authentication.UserNameMapper interface. The class that implements the UserNameMapper interface returns a user object if the digital certificate is valid. Oracle WebLogic Server stores this authenticated user object on the Java client's thread in Oracle WebLogic Server and uses it for subsequent authorization requests when the thread attempts to use WebLogic resources protected by the default (active) security realm.

Writing a User Name Mapper

When using two-way SSL, WebLogic Server verifies the digital certificate of the Web browser or Java client when establishing an SSL connection. However, the digital certificate does not identify the Web browser or Java client as a user in the WebLogic Server security realm. If the Web browser or Java client requests a WebLogic Server resource protected by a security policy, WebLogic Server requires the Web browser or Java client to have an identity. To handle this requirement, the WebLogic Identity Assertion provider allows you to enable a user name mapper that maps the digital certificate of a Web browser or Java client to a user in a WebLogic Server security realm. The user name mapper must be an implementation the weblogic.security.providers.authentication.UserNameMapper interface.

You have the option of the using the default implementation of the weblogic.security.providers.authentication.UserNameMapper interface, DefaultUserNameMapperImpl, or developing your own implementation.

The WebLogic Identity Assertion provider can call the implementation of the UserNameMapper interface for the following types of identity assertion token types:

  • X.509 digital certificates passed via the SSL handshake

  • X.509 digital certificates passed via CSIv2

  • X.501 distinguished names passed via CSIv2

If you need to map different types of certificates, write your own implementation of the UserNameMapper interface.

To implement a UserNameMapper interface that maps a digital certificate to a user name, write a UserNameMapper class that performs the following operations:

  1. Instantiates the UserNameMapper implementation class.

  2. Creates the UserNameMapper interface implementation.

  3. Uses the mapCertificateToUserName() method to map a certificate to a user name based on a certificate chain presented by the client.

  4. Maps a string attribute type to the corresponding Attribute Value Assertion field type.

Security provider plug-ins are loaded from the system classpath. The system classpath must specify the implementation of the weblogic.security.providers.authentication.UserNameMapper interface.

Using Two-Way SSL Authentication Between WebLogic Server Instances

You can use two-way SSL authentication in server-to-server communication in which one WebLogic Server instance is acting as the client of another WebLogic Server instance. Using two-way SSL authentication in server-to-server communication enables you to have dependable, highly-secure connections, even without the more common client/server environment.

Example 5-5 shows an example of how to establish a secure connection from a servlet running in one instance of WebLogic Server to a second WebLogic Server instance called server2.weblogic.com.

  • setProviderURL—specifies the URL of the Oracle WebLogic Server instance acting as the SSL server. The WebLogic Server instance acting as SSL client calls this method. The URL specifies the t3s protocol which is a WebLogic Server proprietary protocol built on the SSL protocol. The SSL protocol protects the connection and communication between the two WebLogic Servers instances.

  • setSSLClientCertificate—specifies the private key and certificate chain to use for the SSL connection. You use this method to specify an input stream array that consists of a private key (which is the first input stream in the array) and a chain of X.509 certificates (which make up the remaining input streams in the array). Each certificate in the chain of certificates is the issuer of the certificate preceding it in the chain.

    Note:

    setSSLClientCertificate(InputStream[] chain) is deprecated in this release
  • setSSLServerName—specifies the name of the Oracle WebLogic Server instance acting as the SSL server. When the SSL server presents its digital certificate to the WebLogic Server acting as the SSL client, the name specified using the setSSLServerName method is compared to the common name field in the digital certificate. In order for hostname verification to succeed, the names must match. This parameter is used to prevent man-in-the-middle attacks.

  • setSSLRootCAFingerprint—specifies digital codes that represent a set of trusted certificate authorities, thus specifying trust based on a trusted certificate fingerprint. The root certificate in the certificate chain received from the WebLogic Server instance acting as the SSL server has to match one of the fingerprints specified with this method in order to be trusted. This parameter is used to prevent man-in-the-middle attacks. It provides an addition to the default level of trust, which for clients running on WebLogic Server is that specified by the WebLogic Server trust configuration.

    Note:

    For information on JNDI contexts and threads and how to avoid potential JNDI context problems, see JNDI Contexts and Threads and How to Avoid Potential JNDI Context Problems in Developing JNDI Applications for Oracle WebLogic Server.

Example 5-5 Establishing a Secure Connection to Another WebLogic Server Instance

FileInputStream [] f = new FileInputStream[3]; 
   f[0]= new FileInputStream("demokey.pem");
   f[1]= new FileInputStream("democert.pem");
   f[2]= new FileInputStream("ca.pem");
Environment e = new Environment ();
e.setProviderURL("t3s://server2.weblogic.com:443");
e.setSSLClientCertificate(f);
e.setSSLServerName("server2.weblogic.com");
e.setSSLRootCAFingerprints("ac45e2d1ce492252acc27ee5c345ef26");

e.setInitialContextFactory
("weblogic.jndi.WLInitialContextFactory");
Context ctx = new InitialContext(e.getProperties())

In Example 5-5, the WebLogic JNDI Environment class creates a hash table to store the following parameters:

Using Two-Way SSL Authentication with Servlets

To authenticate Java clients in a servlet (or any other server-side Java class), you must check whether the client presented a digital certificate and if so, whether the certificate was issued by a trusted certificate authority. The servlet developer is responsible for asking whether the Java client has a valid digital certificate. When developing servlets with the WebLogic Servlet API, you must access information about the SSL connection through the getAttribute() method of the HTTPServletRequest object.

The following attributes are supported in WebLogic Server servlets:

  • javax.servlet.request.X509Certificate

  • java.security.cert.X509Certificate []—returns an array of the X.509 certificate.

  • javax.servlet.request.cipher_suite—returns a string representing the cipher suite used by HTTPS.

  • javax.servlet.request.key_size— returns an integer (0, 40, 56, 128, 168) representing the bit size of the symmetric (bulk encryption) key algorithm.

  • weblogic.servlet.request.SSLSession

  • javax.net.ssl.SSLSession—returns the SSL session object that contains the cipher suite and the dates on which the object was created and last used.

You have access to the user information defined in the digital certificates. When you get the javax.servlet.request.X509Certificate attribute, it is an array of type java.security.cert.X509Certificate. You simply cast the array to that type and examine the certificates.

A digital certificate includes information, such as the following:

  • The name of the subject (holder, owner) and other identification information required to verify the unique identity of the subject.

  • The subject's public key

  • The name of the certificate authority that issued the digital certificate

  • A serial number

  • The validity period (or lifetime) of the digital certificate (as defined by a start date and an end date)

Using a Custom Host Name Verifier

A host name verifier validates that the host to which an SSL connection is made is the intended or authorized party. A host name verifier is useful when a WebLogic client or a WebLogic Server instance is acting as an SSL client to another application server. It helps prevent man-in-the-middle attacks.

Note:

Demonstration digital certificates are generated during installation so they do contain the host name of the system on which the WebLogic Server software installed. Therefore, you should leave host name verification on when using the demonstration certificates for development or testing purposes.

By default, WebLogic Server, as a function of the SSL handshake, compares the CN field of the SSL server certificate Subject DN with the host name in the URL used to connect to the server. If these names do not match, the SSL connection is dropped.

The dropping of the SSL connection is caused by the SSL client, which validates the host name of the server against the digital certificate of the server. If anything but the default behavior is desired, you can either turn off host name verification or register a custom host name verifier. Turning off host name verification leaves the SSL connections vulnerable to man-in-the-middle attacks.

You can turn off host name verification in the following ways:

  • In the WebLogic Server Administration Console, specify None in the Hostname Verification field that is located on the Advanced Options pane under the Keystore & SSL tab for the server (for example, myserver).

  • On the command line of the SSL client, enter the following argument:

-Dweblogic.security.SSL.ignoreHostnameVerification=true
 

You can write a custom host name verifier. The weblogic.security.SSL.HostnameVerifier interface provides a callback mechanism so that implementers of this interface can supply a policy on whether the connection to the URL's host name should be allowed. The policy can be certificate-based or can depend on other authentication schemes.

To use a custom host name verifier, create a class that implements the weblogic.security.SSL.HostnameVerifier interface and define the methods that capture information about the server's security identity.

Note:

This interface takes new style certificates and replaces the weblogic.security.SSL.HostnameVerifierJSSE interface, which is deprecated.

Before you can use a custom host name verifier, you need to specify the class for your implementation in the following ways:

  • In the WebLogic Server Administration Console, set the SSL.HostName Verifier field on the SSL tab under Server Configuration to the name of a class that implements this interface. The specified class must have a public no-arg constructor.

  • On the command line, enter the following argument:

-Dweblogic.security.SSL.hostnameVerifier=hostnameverifier 

The value for hostnameverifier is the name of the class that implements the custom host name verifier.

Example 5-6 shows code fragments from the NulledHostnameVerifier example; the complete example is located in the EXAMPLES_HOME\src\examples\security\sslclient directory in the NulledHostnameVerifier.java file. The EXAMPLES_HOME directory can be found at ORACLE_HOME\wlserver\samples\server. This code example contains a NulledHostnameVerifier class which always returns true for the comparison. The sample allows the WebLogic SSL client to connect to any SSL server regardless of the server's host name and digital certificate SubjectDN comparison.

Example 5-6 Hostname Verifier Sample Code Fragment

public class NulledHostnameVerifier implements
                     weblogic.security.SSL.HostnameVerifier {
  public boolean verify(String urlHostname, javax.net.ssl.SSLSession session) {
    return true;
  }
}

Using a Trust Manager

The weblogic.security.SSL.TrustManager interface provides the ability to:

  • Ignore specific certificate validation errors

  • Perform additional validation on the peer certificate chain

    Note:

    This interface takes new style certificates and replaces the weblogic.security.SSL.TrustManagerJSSE interface, which is deprecated.

When an SSL client connects to an instance of WebLogic Server, the server presents its digital certificate chain to the client for authentication. That chain could contain an invalid digital certificate. The SSL specification says that the client should drop the SSL connection upon discovery of an invalid certificate. You can use a custom implementation of the TrustManager interface to control when to continue or discontinue an SSL handshake. Using a trust manager, you can ignore certain validation errors, optionally perform custom validation checks, and then decide whether or not to continue the handshake.

Use the weblogic.security.SSL.TrustManager interface to create a trust manager. The interface contains a set of error codes for certificate verification. You can also perform additional validation on the peer certificate and interrupt the SSL handshake if need be. After a digital certificate has been verified, the weblogic.security.SSL.TrustManager interface uses a callback function to override the result of verifying the digital certificate. You can associate an instance of a trust manager with an SSL context through the setTrustManager() method.

You can only set up a trust manger programmatically; its use cannot be defined through the WebLogic Server Administration Console or on the command-line.

Note:

Depending on the checks performed, use of a trust manager may potentially impact performance.

Example 5-7 shows code fragments from the NulledTrustManager example; the complete example is located in the EXAMPLES_HOME\src\examples\security\sslclient directory in the NulledTrustManager.java file. The EXAMPLES_HOME directory can be found at ORACLE_HOME\wlserver\samples\server. The SSLSocketClient example uses the custom trust manager. The SSLSocketClient shows how to set up a new SSL connection by using an SSL context with the trust manager.

Example 5-7 NulledTrustManager Sample Code Fragments

package examples.security.sslclient;

import weblogic.security.SSL.TrustManager;
import java.security.cert.X509Certificate;
...
public class NulledTrustManager implements TrustManager{ 
  public boolean certificateCallback(X509Certificate[] o, int validateErr) {
   System.out.println(" --- Do Not Use In Production ---\n" + 
                          " By using this NulledTrustManager, the trust in" +
                            " the server's identity is completely lost.\n" +                           " --------------------------------");
   for (int i=0; i<o.length; i++)
     System.out.println(" certificate " + i + " -- " + o[i].toString());
   return true;
  }
}

Using the CertPath Trust Manager

The CertPathTrustManager, weblogic.security.SSL.CertPathTrustManager, makes use of the default security realm's configured CertPath validation providers to perform extra validation such as revocation checking.

By default, application code using outbound SSL in the server has access only to the built-in SSL certificate validation. However, application code can specify the CertPathTrustManager in order to access any additional certificate validation that the administrator has configured for the server. If you want your application code to also run the CertPath validators, the application code should use the CertPathTrustManager.

There are three ways to use this class:

  • The Trust Manager calls the configured CertPathValidators only if the administrator has set a switch on the SSLMBean stating that outbound SSL should use the validators. That is, the application completely delegates validation to whatever the administrator configures. You use the setUseConfiguredSSLValidation() method for this purpose. This is the default.

  • The Trust Manager always calls any configured CertPathValidators. You use the setBuiltinSSLValidationAndCertPathValidators() method for this purpose.

  • The Trust Manager never calls any configured CertPathValidators. You use the setBuiltinSSLValidationOnly() method for this purpose.

Using a Handshake Completed Listener

The javax.net.ssl.HandshakeCompletedListener interface defines how an SSL client receives notifications about the completion of an SSL protocol handshake on a given SSL connection. Example 5-8 shows code fragments from the MyListener example; the complete example is located in the EXAMPLES_HOME\src\examples\security\sslclient directory in the MyListener.java file. The EXAMPLES_HOME directory can be found at ORACLE_HOME\wlserver\samples\server.

Example 5-8 MyListener (HandshakeCompletedListener) Sample Code Fragments

package examples.security.sslclient;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileInputStream;
import javax.net.ssl.HandshakeCompletedListener;
import java.util.Hashtable;
import javax.net.ssl.SSLSession;
...
  public class MyListener implements HandshakeCompletedListener
  {
    public void handshakeCompleted(javax.net.ssl.HandshakeCompletedEvent
                                          event)
    {
      SSLSession session = event.getSession();
      System.out.println("Handshake Completed with peer " +
                               session.getPeerHost());
      System.out.println("   cipher: " + session.getCipherSuite());
      Certificate[] certs = null;
      try
      {
        certs = session.getPeerCertificates();
      }
      catch (SSLPeerUnverifiedException puv)
      {
        certs = null;
      }
      if  (certs != null)
      {
        System.out.println("   peer certificates:");
        for (int z=0; z<certs.length; z++) 
                 System.out.println("      certs["+z+"]: " + certs[z]);
      }
      else
      {
        System.out.println("No peer certificates presented");
      }
    }
  }

Using an SSLContext

The SSLContext class is used to programmatically configure SSL and to retain SSL session information. Each instance can be configured with the keys, certificate chains, and trusted CA certificates that will be used to perform authentication. SSL sockets created with the same SSLContext and used to connect to the same SSL server could potentially reuse SSL session information. Whether the session information is actually reused depends on the SSL server.

For more information on session caching see SSL Session Behavior in Administering Security for Oracle WebLogic Server. To associate an instance of a trust manager class with its SSL context, use the weblogic.security.SSL.SSLContext.setTrustManager() method.

You can only set up an SSL context programmatically; not by using the WebLogic Server Administration Console or the command line. A Java new expression or the getInstance() method of the SSLContext class can create an SSLContext object. The getInstance() method is static and it generates a new SSLContext object that implements the specified secure socket protocol. An example of using the SSLContext class is provided in the SSLSocketClient.java sample in EXAMPLES_HOME\src\examples\security\sslclient, where EXAMPLES_HOME represents the directory in which the WebLogic Server code examples are configured and can be found at ORACLE_HOME\wlserver\samples\server. The SSLSocketClient example shows how to create a new SSL socket factory that will create a new SSL socket using SSLContext.

Example 5-9 shows a sample instantiation using the getInstance() method.

Example 5-9 SSL Context Code Example

import weblogic.security.SSL.SSLContext;
  SSLcontext sslctx = SSLContext.getInstance ("https")

Using URLs to Make Outbound SSL Connections

You can use a URL object to make an outbound SSL connection from a WebLogic Server instance acting as a client to another WebLogic Server instance. WebLogic Server supports both one-way and two-way SSL authentication for outbound SSL connections.

For one-way SSL authentication, you use the java.net.URL, java.net.URLConnection, and java.net.HTTPURLConnection classes to make outbound SSL connections using URL objects. Example 5-10 shows a simpleURL class that supports both HTTP and HTTPS URLs and that only uses these Java classes (that is, no WebLogic classes are required). To use the simpleURL class for one-way SSL authentication (HTTPS) on WebLogic Server, all that is required is that "weblogic.net" be defined in the system property for java.protocols.handler.pkgs.

Note:

Because the simpleURL sample shown in Example 5-10 defaults trust and hostname checking, this sample requires that you connect to a real Web server that is trusted and that passes hostname checking by default. Otherwise, you must override trust and hostname checking on the command line.

Example 5-10 One-Way SSL Authentication URL Outbound SSL Connection Class That Uses Java Classes Only

import java.net.URL;
import java.net.URLConnection;
import java.net.HttpURLConnection;
import java.io.IOException;
public class simpleURL
{
   public static void main (String [] argv)
   {
     if (argv.length != 1)
     {
       System.out.println("Please provide a URL to connect to");
       System.exit(-1);
     }
     setupHandler();
     connectToURL(argv[0]);
   }
   private static void setupHandler()
   {
     java.util.Properties p = System.getProperties();
     String s = p.getProperty("java.protocol.handler.pkgs");
     if (s == null)
       s = "weblogic.net";
     else if (s.indexOf("weblogic.net") == -1)
       s += "|weblogic.net";
     p.put("java.protocol.handler.pkgs", s);
     System.setProperties(p);
   }
   private static void connectToURL(String theURLSpec)
   {
     try
     {
       URL theURL = new URL(theURLSpec);
       URLConnection urlConnection = theURL.openConnection();
       HttpURLConnection connection = null;
       if (!(urlConnection instanceof HttpURLConnection))
       {
         System.out.println("The URL is not using HTTP/HTTPS: " +
                              theURLSpec);
         return;
       }
       connection = (HttpURLConnection) urlConnection;
       connection.connect();
       String responseStr = "\t\t" +
              connection.getResponseCode() + " -- " +
              connection.getResponseMessage() + "\n\t\t" +
                   connection.getContent().getClass().getName() + "\n";
       connection.disconnect();
       System.out.println(responseStr);
     }
     catch (IOException ioe)
     {
       System.out.println("Failure processing URL: " + theURLSpec);
       ioe.printStackTrace();
     }
   }
}

For two-way SSL authentication, the weblogic.net.http.HttpsURLConnection class provides a way to specify the security context information for a client, including the digital certificate and private key of the client. Instances of this class represent an HTTPS connection to a remote object.

The SSLClient sample code demonstrates using the WebLogic URL object to make an outbound SSL connection (see Example 5-11). The code example shown in Example 5-11 is excerpted from the SSLClient.java file in the EXAMPLES_HOME\src\examples\security\sslclient directory. The EXAMPLES_HOME directory can be found at ORACLE_HOME\wlserver\samples\server.

Note:

loadLocalIdentity(InputStream certStream, InputStream keyStream, char[] password) is deprecated in this release.

Example 5-11 WebLogic Two-Way SSL Authentication URL Outbound SSL Connection Code Example

wlsUrl = new URL("https", host, Integer.valueOf(sport).intValue(),
                 query);
weblogic.net.http.HttpsURLConnection sconnection =
         new weblogic.net.http.HttpsURLConnection(wlsUrl);
...
InputStream [] ins = new InputStream[2];
      ins[0] = new FileInputStream("clientkey.pem");
      ins[1] = new FileInputStream("client2certs.pem");
       String pwd = "clientkey";
      sconnection.loadLocalIdentity(ins[0], ins[1], pwd.toCharArray());

SSL Client Code Examples

The WebLogic Server product provides a complete working SSL authentication sample.The sample provided by WebLogic Server is located in EXAMPLES_HOME\src\examples\security\sslclient, where EXAMPLES_HOME represents the directory in which the WebLogic Server code examples are configured and can be found at ORACLE_HOME\wlserver\samples\server. For a description of the sample and instructions on how to build, configure, and run this sample, see the package.html file in the sample directory. You can modify this code example and reuse it.