Mutual Authentication for Web Services



To discuss the topic of this paper, we decided to use the Java Blueprints Adventure Builder application.  Adventure Builder is a set of applications that showcases web services on the J2EE 1.4 platform.  This application is developed as part of the blueprints.dev.java.net project under the sub-project title adventurebuilder with full source code available here.  The Adventure Builder application was also a topic of a popular book titled "Designing Web Services with the J2EE 1.4 Platform".  The book is available for free download in PDF format.

When designing Adventure Builder, we chose to use secure mutually authenticated web services as the technology for communication between the order processing center and entities external to the order processing center, such as for the exchange of purchase orders and invoices with the bank and suppliers.  We made this choice because we are primarily interested in achieving the greatest degree of secure interoperability among all modules and among all types of participants.  The Adventure Builder application already has implemented mutual authentication.  This document describes how mutual authentication was implemented broken down into the following steps:

  1. Exchanging Digital Certificates between Participants
  2. Configuring Endpoint Deployment Descriptors to Enable Mutual Authentication
  3. Debugging the Configuration

Mutual Authentication Summary

When using mutual authentication, either the actual entity's certificate is trusted or an entity in the certificate chain is trusted which implies trust to its descendant.  For example, you want to use a contractor to build a room, you call the contractor that worked on a friend's house that the friend said did a great job.  Since your friend trusts this contractor and said he did a great job, you trust the contractor, because you trust your friend.  Certificate and certificate chain trust works in the same manner.  Your friend acts as a link in the Certificate chain.  You either trust the client certificate directly and import the certificate into your truststore where all the trusted certificates reside or you trust a third party certificate authority like VeriSign which implies trust to the certificates that VeriSign distributes (signs).  More information on web service security can be found in the security chapter of the "Designing Web Services with the J2EE™ 1.4 Platform" book located here.  More information on certificates can be found in the security section of the J2EE 1.4 tutorial located here.

When messages are sent using mutual authentication, a connection can only be completed when the client trusts the server's certificate and the server trusts the client's certificate.  The process of exchanging certificates and setting up connection properties is called the "SSL Handshake".   More information on the SSL Handshake and JSSE in located here.  When using an application server like the Sun Java System Application Server 8.1 Platform Edition (SJSAS8.1PE) a default self-signed certificate is generated upon creation of the domain.  The certificate has an alias of "s1as" and is stored in the domain's keystore located at SJSAS8.1PE_INSTALL/domains/DOMAIN_NAME/config/keystore.jks.  The "s1as" certificate is also  imported into the domain's truststore located at SJSAS8.1PE_INSTALL/domains/DOMAIN_NAME/config/cacerts.jks.   The default truststore also has numerous VeriSign certificates pre-install to facilitate interoperability.


1) Exchanging Digital Certificates between Participants

When you deploy Adventure Builder with the default deployment options on SJSAS8.1PE, the Order Processing Center and the Supply Chain vendor modules are deployed on the same instance of the application server.  This being the case, the same "s1as" certificate is used for the client and the server certificates, since the "s1as" certificate is also imported into the domain's truststore, the mutual authenticated connection is allowed to be made.  In a real world scenario the Order Processing Center and the Supply Chain vendors would be located on different machines across the Internet.  To make this configuration allow connections to be made, the client and server certificates have to be imported into their counter-parts truststore.  In the examples below domain1's certificate will be exported from its keystore and imported into domain2's truststore. When the keystore/truststore is accessed a password is required, the default password for SJSAS8.1PE is "changeit".  To export a certificate from a keystore and import it into the counter-parts truststore, perform the following steps:

1a) List domain1's keystore contents:

$JAVA_HOME/bin/keytool -list -keystore SJSAS8.1PE_INSTALL/domains/domain1/config/keystore.jks
Enter keystore password:  changeit

Keystore type: jks
Keystore provider: SUN
Your keystore contains 1 entry
s1as, Aug 9, 2005, keyEntry,
Certificate fingerprint (MD5): 9F:A1:F1:F9:3C:CB:60:B0:64:F1:35:F7:01:57:3B:0A

1b) Export the domain1's certificate from its keystore:

$JAVA_HOME/bin/keytool -export -alias s1as -file /tmp/domain1_s1as.cer -keystore SJSAS8.1PE_INSTALL/domains/domain1/config/keystore.jks
Enter keystore password:  changeit
Certificate stored in file <\tmp\domain1_s1as.cer>

1c) Import the exported certificate into domain2's truststore:

$JAVA_HOME/bin/keytool -import -trustcacerts -alias domain1_s1as -file /tmp/domain1_s1as.cer -keystore SJSAS8.1PE_INSTALL/domains/domain1/config/cacerts.jks
Enter keystore password:  changeit
Owner: CN=baslerxp.sfbay.sun.com, OU=Sun Java System Application Server, O=Sun Microsystems, L=Santa Clara, ST=California, C=US
Issuer: CN=baslerxp.sfbay.sun.com, OU=Sun Java System Application Server, O=Sun Microsystems, L=Santa Clara, ST=California, C=US
Serial number: 42f9160f
Valid from: Tue Aug 09 13:46:07 PDT 2005 until: Fri Aug 07 13:46:07 PDT 2015
Certificate fingerprints:
         MD5:  9F:A1:F1:F9:3C:CB:60:B0:64:F1:35:F7:01:57:3B:0A
         SHA1: B6:1E:6C:CC:20:B0:2E:CB:87:F2:3C:DE:53:FD:08:E9:92:BC:69:90
Trust this certificate? [no]:  y
Certificate was added to keystore

1d) List domain2's truststore to verify the import:

$JAVA_HOME/bin/keytool -list -keystore SJSAS8.1PE_INSTALL/domains/domain1/config/cacerts.jks
Enter keystore password:  changeit

Keystore type: jks
Keystore provider: SUN
Your keystore contains 14 entries
verisignc1g3, Apr 8, 2004, trustedCertEntry,
Certificate fingerprint (MD5): B1:47:BC:18:57:D1:18:A0:78:2D:EC:71:E8:2A:95:73
verisignc1g2, Apr 8, 2004, trustedCertEntry,
Certificate fingerprint (MD5): DB:23:3D:F9:69:FA:4B:B9:95:80:44:73:5E:7D:41:83
verisignc1g1, Apr 8, 2004, trustedCertEntry,
Certificate fingerprint (MD5): 97:60:E8:57:5F:D3:50:47:E5:43:0C:94:36:8A:B0:62
verisignc2g3, Apr 8, 2004, trustedCertEntry,
Certificate fingerprint (MD5): F8:BE:C4:63:22:C9:A8:46:74:8B:B8:1D:1E:4A:2B:F6
verisignc2g2, Apr 8, 2004, trustedCertEntry,
Certificate fingerprint (MD5): 2D:BB:E5:25:D3:D1:65:82:3A:B7:0E:FA:E6:EB:E2:E1
domain1_s1as, Aug 16, 2005, trustedCertEntry,
Certificate fingerprint (MD5): 9F:A1:F1:F9:3C:CB:60:B0:64:F1:35:F7:01:57:3B:0A
verisignc2g1, Apr 8, 2004, trustedCertEntry,
Certificate fingerprint (MD5): B3:9C:25:B1:C3:2E:32:53:80:15:30:9D:4D:02:77:3E
verisignc3g3, Apr 8, 2004, trustedCertEntry,
Certificate fingerprint (MD5): CD:68:B6:A7:C7:C4:CE:75:E0:1D:4F:57:44:61:92:09
verisignc3g2, Apr 8, 2004, trustedCertEntry,
Certificate fingerprint (MD5): A2:33:9B:4C:74:78:73:D4:6C:E7:C1:F3:8D:CB:5C:E9
domain2, Aug 10, 2005, trustedCertEntry,
Certificate fingerprint (MD5): 23:47:42:EF:48:CB:29:FA:09:DC:C6:C3:C0:D4:D3:59
verisignc3g1, Apr 8, 2004, trustedCertEntry,
Certificate fingerprint (MD5): 10:FC:63:5D:F6:26:3E:0D:F3:25:BE:5F:79:CD:67:67
mykey, Aug 9, 2005, trustedCertEntry,
Certificate fingerprint (MD5): A0:AF:EC:4A:4F:4A:54:FA:AE:7C:D9:3C:7F:2F:FE:3A
s1as, Aug 5, 2005, trustedCertEntry,
Certificate fingerprint (MD5): 9F:A1:F1:F9:3C:CB:60:B0:64:F1:35:F7:01:57:5C:3D
verisignsecureserver, Apr 8, 2004, trustedCertEntry,
Certificate fingerprint (MD5): 74:7B:82:03:43:F0:00:9E:6B:B3:EC:47:BF:85:A5:93


After performing the steps above domain1's  certificate will be a trusted by domain2.  To have domain1 trust domain2, the steps have to be re-run exporting from domain2 and importing into domain1.  More information on the JavaSE 5 keytool is location here.


2) Configuring Endpoint Deployment Descriptors to Enable Mutual Authentication

When using mutual authentication for web services the method used to configure the components depends on how the web service is implemented.  If the web service is implemented using a web module then the web.xml deployment descriptor needs to be modified.  If the web service is implemented using an EJB then the sun-ejb-jar.xml deployment descriptor needs to be modified for that specific EJB.  Described below are the specific changes required to the deployment descriptors based on implementation.

Web Tier Implementation

When adding mutual authentication to a web module a security-constraint needs to be added to the web.xml deployment descriptor to target the URL pattern and the the manner in which the constraint applies.  The excerpt below targets the "/hello" URL pattern and requires a "CONFIDENTIAL" transport with the authentication mechanism being "CLIENT-CERT".  This snippet is an example given in the J2EE 1.4 tutorial with more information located here.

  <security-constraint>
    <display-name>SecurityConstraint</display-name>
    <web-resource-collection>
      <web-resource-name>WRCollection</web-resource-name>
      <url-pattern>/hello</url-pattern>
      <http-method>POST</http-method>
      <http-method>GET</http-method>
    </web-resource-collection>
    <user-data-constraint>
      <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
  </security-constraint>
  <login-config>
    <auth-method>CLIENT-CERT</auth-method>
  </login-config>


The different values for the bolded elements are as follows:

EJB Tier Implementation

When adding mutual authentication to an EJB module that only exposes a webservice-endpoint the auth-method and the transport-guarantee elements are needed to specify that a "CONFIDENTIAL" transport is required with the authentication mechanism of "CLIENT-CERT".  This snippet is an example taken from the Adventure Builder application with the full text of the deployment descriptor located in the ADVENTURE_BUILDER_INSTALL/project/apps/activitysupplier/activitysupplier-ejb/src/conf/sun-ejb-jar.xml file.

    <ejb>
      <ejb-name>ActivityPOEndpointBean</ejb-name>
       ...
      <webservice-endpoint>
        <port-component-name>ActivityPOIntfPort</port-component-name>
        <endpoint-address-uri>webservice/ActivityPOService</endpoint-address-uri>
        <login-config>
            <auth-method>CLIENT-CERT</auth-method>
        </login-config>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
      </webservice-endpoint>
    </ejb>


The different values for the bold elements are as follows:

When adding mutual authentication to an EJB module that also exposes the EJB through remote and/or local interface(s), one more level of security is required.   Anior-security-constraint needs to be added to the sun-ejb-jar.xml deployment descriptor to specify that confidentiality and client trust is required.  This will ensure that that the EJB client meets the mutual authentication requirements when the remote and/or local interface(s) are used.  This step isn't required if the EJB is only exposed via a webservice-endpoint or the developer doesn't require this constraint implemented when the EJB's remote and/or local interface(s) are used.

       ...
      <ior-security-config>
        <transport-config>
            <integrity>REQUIRED</integrity>
            <confidentiality>REQUIRED</confidentiality>
            <establish-trust-in-target>SUPPORTED</establish-trust-in-target>
            <establish-trust-in-client>REQUIRED</establish-trust-in-client>
        </transport-config>
      </ior-security-config>
      ...

All the allowable values have the same meaning in the constraints listed above.  They are as follows:


3) Debugging the Configuration

When debugging mutual authentication a system property can be set to display different levels of logging.  The most common for debugging mutual authentication would be -Djavax.net.debug=ssl:handshake.  To add this system property to the server's configuration use the Administration GUI to update the JVM Options for the server's configuration.  The procedure is described here.  More information about the java.net.debug system property can be found here.

One other point to note would be that if the client is using a keystore with multiple private keys, the private key's certificate with the latest timestamp will be used as the client certificate to authenticate to the server.  This can cause problems when it comes to importing the correct client certificate into the server's truststore.  One method to resolve this problem could be to import all the certificates in the client's keystore.  The normal production configuration should only have one private key in its keystore representing the client.




References

Java Blueprints Adventure Builder java.net site
JavaTM Secure Socket Extension (JSSE) Reference Guide
Sun Java System Application Server product site
J2EE 1.4 Tutorial
Java Web Services Tutorial