[MQ 10.0.0 Jun 2026]

Configuring a customized SSLSocketFactory instance for JWT retrieval

You can supply a customized SSLSocketFactory instance to control how your application securely retrieves JWT tokens from HTTPS endpoints. This customized SSLSocketFactory can also specify the level of validation that the IBM® MQ classes for JMS client library runs when it retrieves JWT from an HTTPS connection. You can choose whether the client needs full validation, or can ignore hostname checks, or not perform the certificate validation.

About this task

If an IBM MQ classes for JMS client relies on JVM SSL settings to retrieve tokens from an HTTPS token endpoint, this prevents you from isolating certificate handling for the token endpoint. If a customized SSLSocketFactory instance is supplied, it overrides the default behavior of the JVM SSL settings. By using the TOKEN_SSL_SOCKET_FACTORY property to supply a separate, customized SSLSocketFactory instance in the IBM MQ classes for JMS library for JWT retrieval from an HTTPS endpoint, you can define the truststore that is used by your JMS application, avoid relying on default JVM SSL settings, and customize the HTTPS handling without affecting the other applications that are running in the same JVM.

The SSLSocketFactory instance that you want the JWT token server connection to use can be different from the one that you use for your queue manager or your CCDT connections.

Certificate validation is handled according to the logic defined within the customized factory. Applications can specify the level of validation that is applied during HTTPS connection by using the TOKEN_HTTPS_CERT_VALIDATION_POLICY certificate validation policy property and specifying the required option, which can be ANY, HOSTNAMECN (default), or NONE. For more information, see Configuring certificate validation policies in IBM MQ.

If the certificate validation policy is set to NONE, the application uses the handler implementation that is provided by HttpsSSLHandler in the IBM MQ classes for JMS library, which trusts all certificates. This handler implementation is overridden by supplying a customized SSLSocketFactory that applies to all JWT HTTPS connections.

If no customized SSLSocketFactory instance is provided, the system defaults to the Java Secure Socket Extension's (JSSE) built-in certificate validation mechanism.

Procedure

  1. Create and customize the stores.
    The application begins by creating a SSLContext and then obtaining a SSLSocketFactory from it.
    This factory will later be assigned to the JWT HTTPS connection.
  2. Create the IBM MQ classes for JMS connection factory.
    This JmsConnectionFactory is configured with authentication and SSL properties.
  3. Set the queue manager.
    This identifies which queue manager the client will ultimately connect to after the token retrieval.
  4. Configure the JWT parameters.
    These properties instruct the client how to obtain a JWT token.
    TOKEN_CLIENT_ID and TOKEN_CLIENT_SECRET define the OAuth credentials.
    TOKEN_ENDPOINT specifies the HTTPS endpoint that is used for token retrieval.
  5. Assign the customized SSLSocketFactory specifically for JWT HTTPS retrieval.
    Check that only the HTTPS connection to the TOKEN_ENDPOINT uses this SSLSocketFactory and it does not affect JVM-wide SSL settings.
  6. Configure the certificate validation policies.
    If the policy value is NONE, this controls hostname and certificate checking for the HTTPS connections when a customized SSLSocketFactory does not override certification behavior. For ANY and HOSTNAMECN, the policy applies irrespective of the customized SSLSocketFactory's presence.
  7. Create the JMS objects and start the connection.
    The application is now authenticated and ready to send or receive messages.

Example

The following example shows how to configure a customized SSLSocketFactory instance for the JWT token HTTPS endpoints.
Note: This example demonstrates a basic implementation of SSLSocketFactory with keystore and truststore locations, modify it according to your production environment needs.
public static void main(String[] args) {
  Connection connection = null;
  Session session = null;
  Destination destination = null;
  MessageProducer producer = null;

  // Construct and customize stores 
  SSLContext sslContext = createSimpleSSLContext(); // Check method definition below
  SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

  // Create a connection factory
  JmsFactoryFactory ff = JmsFactoryFactory.getInstance(WMQConstants.WMQ_PROVIDER);
  JmsConnectionFactory cf = ff.createConnectionFactory();

  // Set the queue manager name
  cf.setStringProperty(WMQConstants.WMQ_QUEUE_MANAGER, "QM1");
  
  // Set properties to get tokens
  cf.setStringProperty(WMQConstants.TOKEN_CLIENT_ID, "mykeycloakclient");
  cf.setStringProperty(WMQConstants.TOKEN_CLIENT_SECRET, "mykeycloaksecret");
  cf.setStringProperty(WMQConstants.TOKEN_ENDPOINT, "https://mykeycloak.server/oidc/token");

  // Set a custom sslSocketFactory instance for the https endpoint set in TOKEN_ENDPOINT property above
  cf.setObjectProperty(WMQConstants.TOKEN_SSL_SOCKET_FACTORY, sslSocketFactory);

  // Set a level of certificate validation
  cf.setIntProperty(WMQConstants.TOKEN_HTTPS_CERT_VALIDATION_POLICY, MQConstants.MQ_HTTPSCERTVAL_ANY);

  // Create JMS objects
  connection = cf.createConnection();
  session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
  destination = session.createQueue("dev.queue.1");
  producer = session.createProducer(destination);

  // Start the connection
  connection.start();
}

// Sample method that constructs keystore and truststore
public static SSLContext createSimpleSSLContext() {
    try {
      KeyStore keyStore = KeyStore.getInstance("JKS");
      try (FileInputStream keyStoreStream = new FileInputStream("clientkey.jks")) {  // Path to keystore jks
        keyStore.load(keyStoreStream, "keystorepassword".toCharArray()); // Hardcoded password just for the sample
      }
      KeyStore trustStore = KeyStore.getInstance("JKS");
      try (FileInputStream trustStoreStream = new FileInputStream("clientkey.jks")) { // Path to truststore jks
        trustStore.load(trustStoreStream, "truststorepassword".toCharArray()); // Hardcoded password just for the sample
      }

      KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
      kmf.init(keyStore, "keystorepassword".toCharArray()); // Hardcoded password just for the sample

      TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
      tmf.init(trustStore);

      SSLContext context = SSLContext.getInstance("TLS"); // set protocol name 
      context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
      return context;
    } catch (Exception e) {
      // handle exception
    }
    return null;
  }