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:
- Exchanging Digital Certificates between
Participants
- Configuring Endpoint Deployment Descriptors to
Enable Mutual Authentication
- 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:
- transport-guarantee - This element specifies the kind of
transport to use between the client and the server. The case
sensitive values
that can be used are as follows:
- NONE - No transport guarantee is required.
- INTEGRAL - The data must be sent between the client and the
server in a manner to ensure the data can't be changed.
- CONFIDENTIAL - The data must be sent between the client and
server in a manner to ensure that its true contents can't be
read.
- auth-method - This element is used to identify the
authentication mechanism for the web module. The case
sensitive values
that can be used are as follows:
- BASIC - Uses basic authentication which consists of a user
&
password.
- DIGEST - Uses basic authentication which consists of a user
& password, but sends the password in encrypted format.
- FORM - Uses a web page to perform authentication.
- CLIENT-CERT - Uses a client certificate for authentication.
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:
- auth-method - This element is used to identify the
authentication mechanism for the EJB webservice-endpoint. The
case
sensitive values
that can be used are as follows:
- BASIC - Uses basic authentication with consists of a user &
password.
- CLIENT-CERT - Uses a client certificate for validation.
- transport-guarantee - This element specifies the kind of
transport to use between the client and the server. The case
sensitive values
that can be used are as follows:
- NONE - No transport guarantee is required.
- INTEGRAL - The data must be sent between the client and the
server in a manner to ensure the data can't be changed.
- CONFIDENTIAL - The data must be sent between the client and
server in a manner to ensure that its true contents can't be
read.
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>
...
- integrity - This element indicates if the EJB enforces that
the message contents can't be changed. The acceptable values for
this constraint
are NONE, SUPPORTED or REQUIRED
- confidentiality - This element indicates if the EJB enforces that
the message contents can't be
read. The acceptable values for this constraint are NONE,
SUPPORTED or REQUIRED
- establish-trust-in-target - This element indicates if the server
should authenticate itself to the client for this EJB. The
acceptable values for this constraint are NONE or SUPPORTED.
- establish-trust-in-client - This element indicates if the client
should authenticate itself to the server for this EJB. The
acceptable values for this constraint are NONE, SUPPORTED or REQUIRED.
All the allowable values have the same meaning in the constraints
listed above. They are as follows:
- NONE - The constraint is not used.
- SUPPORTED - The constraint is supported by not required
- REQUIRED - The constraint is required.
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