Mutual Authentication for Web Services: A Live Example

By Mark Basler and Marina Sum, October 24, 2005

Secure communications among Web services are a must for supply-chain applications. Adventure Builder is a set of applications that showcases Web services on the Java 2 Platform, Enterprise Edition (J2EE 1.4 platform). The Order Processing Center of Adventure Builder must communicate securely with external entities, for example, to exchange purchase orders and invoices. While designing Adventure Builder, the BluePrints team opted for secure, mutually authenticated Web services for such communication. Why? Because the primary goal is to achieve the most secure interoperability among the modules and the participants.

This paper describes that implementation procedure for mutual authentication, step by step, and offers debugging tips.

By way of background, Adventure Builder was first developed at Sun as a reference application and then moved to java.net as part of the open-source project blueprints.dev.java.net under the subproject adventurebuilder . That application was also a topic of a popular book, Designing Web Services With the J2EE 1.4 Platform , available for free download in PDF.

Overview of Mutual Authentication

With mutual authentication, you trust the actual entity's certificate or an entity in the certificate chain, which implies that you trust its descendant. For example, in hiring a building contractor, you'd opt for someone who previously did a commendable job for a friend. Since your friend trusted and recommended that contractor highly, you automatically trust that person, too, because you trust your friend.

Certificate and certificate chain trust work in like manner. Your friend acts as a link in the certificate chain. You trust the client certificate and directly import the certificate into your truststore, where all the trusted certificates reside. Alternatively, you trust a third-party certificate authority, such as VeriSign, which implies trust in the certificates that VeriSign distributes or signs.

For more information on Web-service security, see Chapter 7, "Security," in the book Designing Web Services with the J2EE 1.4 Platform . To learn about certificates, see the section, " Understanding Digital Certificates," in the J2EE 1.4 Tutorial.

When you send messages with mutual authentication, a connection is possible only if 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 Secure Sockets Layer (SSL) handshake. For details, see the section, " SSL Protocol Overview," in the Java Secure Socket Extension (JSSE) Reference Guide.

While creating a domain, an application server, such as Sun Java System Application Server Platform Edition 8.1 (henceforth, Application Server), generates a default, self-signed certificate. That certificate, which contains an alias of s1as, is stored in the domain's keystore at App_Server_install_dir /domains/domain_name/config/keystore.jks. Application Server also imports the s1as certificate into the domain's truststore at App_Server_install_dir /domains/domain_name/config/cacerts.jks. For interoperability, the default truststore contains numerous preinstalled VeriSign certificates.

Implementation

Follow the two procedures described in this section to implement mutual authentication for Adventure Builder.

Exchanging Digital Certificates Among Participants

When deploying Adventure Builder with the default options on Application Server, you deploy the Order Processing Center and the Supply Chain vendor modules on the same instance of Application Server. That is, you use the same s1as certificate for the client and the server certificates. Since Application Server also imports the s1as certificate into the domain's truststore, it enables the mutually authenticated connection.

In a real-world scenario, the Order Processing Center and the Supply Chain vendors would be located on different machines across the Internet. To enable the connections, Application Server must import the client and server certificates into their counterparts' truststores.

To export a certificate from a keystore and import it into the counterpart's truststore, perform the steps below. Bear in mind the following:

  • Application Server exports the certificate in domain1 from its keystore into domain2's truststore.
  • The default password for Application Server for accessing the keystore or truststore is changeit.
  1. List the keystore contents in domain1. Type (all on one line):

    $JAVA_HOME/bin/keytool -list -keystore App_Server_install_dir /domains/domain1/config/keystore.jks

  2. Type changeit at the password prompt. Here is at the password prompt. Here is the output. output.
    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
    
  3. Export the domain1 certificate from its keystore. Type (all on one line): $JAVA_HOME/bin/keytool -export -alias s1as -file /tmp/domain1_s1as.cer -keystore App_Server_install_dir /domains/domain1/config/keystore.jks
  4. Type changeit at the password prompt. Here is the output.
    Certificate stored in file <\tmp\domain1_s1as.cer>
    
    
  5. Import the exported certificate into the domain2 truststore. Type (all on one line): $JAVA_HOME/bin/keytool -import -trustcacerts -alias domain1_s1as -file /tmp/domain1_s1as.cer -keystore App_Server_install_dir /domains/domain1/config/cacerts.jks
  6. Type changeit at the password prompt. Here is the output.
    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
    
  7. List the domain2 truststore to verify the import. Type (all on one line):

    $JAVA_HOME/bin/keytool -list -keystore App_Server_install_dir /domains/domain1/config/cacerts.jks

  8. Type changeit at the password prompt. Here is the output.
    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
                        
    The domain1 certificate is now trusted by domain2. To have domain1 trust domain2, rerun the procedure, that is, export from domain2 and import into domain1. For details on the Java 5 Standard Edition Key and Certificate Management Tool ( keytool), see its documentation.

Configuring Endpoint Deployment Descriptors

The method for configuring the components depends on how you implemented the Web service, as follows:

  • If you implemented the Web service with a Web module, you must revise the web.xml deployment descriptor.
  • If you implemented the Web service with an EJB component, you must revise the sun-ejb-jar.xml deployment descriptor for that specific component.

This section describes the changes required for the deployment descriptors for both implementations.

Web Module Implementation

To enable mutual authentication for a Web module, add a security constraint to the web.xml deployment descriptor to target the URL pattern and the manner in which the constraint applies. The code snippet below, which originates from the J2EE 1.4 Tutorial, targets the /hello URL pattern and requires a CONFIDENTIAL transport with a CLIENT-CERT authentication mechanism.

<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>
                

For details, see the section, " Example: Client-Certificate Authentication over HTTP/SSL with JAX-RPC," in the J2EE 1.4 Tutorial.

The values for the boldfaced elements are as follows:

  • transport-guarantee Identifies the type of transport between the client and the server. You specify one of three case-sensitive values:
    • NONE Requires no transport guarantees.
    • INTEGRAL Sends the data between the client and the server in such a manner as to ensure that the data are uneditable.
    • CONFIDENTIAL Sends the data between the client and server in such a manner as to ensure that the true contents are unreadable.
  • auth-method Identifies the authentication mechanism for the Web module. You specify one of four case-sensitive values:
    • BASIC Uses basic authentication, that is, a user ID and password.
    • DIGEST Uses basic authentication (a user ID and password) but sends the password in encrypted format.
    • FORM Authenticates by presenting a Web Page for input.
    • CLIENT-CERT Authenticates with a client certificate.

EJB Module Implementation

To enable mutual authentication for an EJB module that exposes only a Web-service endpoint, you must set the auth-method element to CLIENT-CERT and the transport-guarantee element to CONFIDENTIAL. The code snippet below is an example from Adventure Builder. The full text of the deployment descriptor is 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</endpointaddress-uri>
<login-config>         
<auth-method>CLIENT-CERT</auth-method>   
</login-config>      
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</webservice-endpoint>
</ejb>

The values for the boldfaced elements are as follows:

  • auth-method Identifies the authentication mechanism for the EJB Webservice endpoint. You specify one of two case-sensitive values:
    • BASIC Uses basic authentication, that is, a user ID and password.
    • CLIENT-CERT Authenticates with a client certificate.
  • transport-guarantee Identifies the type of transport to use between the client and the server. You specify one of three case-sensitive values:
    • NONE Requires no transport guarantees.
    • INTEGRAL Sends the data between the client and the server in such a manner as to ensure that the data are uneditable.
    • CONFIDENTIAL Sends the data between the client and server in such a manner as to ensure that the true contents are unreadable.

Mutual authentication for an EJB module that also exposes the EJB component through remote or local interfaces requires one more level of security: the ior-security-constraint element. Add that element to the sun-ejb-jar.xml deployment descriptor to specify that confidentiality and client trust are required, as follows.

...

<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>
...
                

Note: If the EJB module is exposed only through a Web-service endpoint or if you do not desire this constraint for the EJB module's remote or local interfaces, omit this step.

Here are what the constraint elements mean:

  • integrity Determines whether the EJB module enforces that the message contents are editable. You specify one of three values: NONE, SUPPORTED, or REQUIRED.
  • confidentiality Determines whether the EJB module enforces that the message contents are readable. You specify one of three values: NONE, SUPPORTED, or REQUIRED.
  • establish-trust-in-target Determines whether the server should authenticate itself to the client for this EJB module. You specify one of two values: NONE or SUPPORTED.
  • establish-trust-in-client Determines whether the client should authenticate itself to the server for this EJB module. You specify one of three values: NONE, SUPPORTED, or REQUIRED.

Here are what the values mean:

  • NONE The constraint is not used.
  • SUPPORTED The constraint is supported but not required.
  • REQUIRED The constraint is required.

Debugging Tips

To ease the debugging process, from the administration GUI, update the Java virtual machine options for the server's configuration and set a system property to display different levels of logging. The most common level is -Djavax.net.debug=ssl:handshake. For details on the procedure and on the java.net.debug system property, see the section, " Debugging Utilities," in the Java Secure Socket Extension (JSSE) Reference Guide.

Also, if the client's keystore contains multiple private keys, the private key's certificate with the latest timestamp serves as the client certificate that authenticates to the server. In that case, it might be problematic to pinpoint the correct client certificate to import into the server's truststore. As a resolution, import all the certificates into the client's keystore. The keystore in the normal production configuration contains only one private key that represents the client, however.

References