CLIENT-CERT authentication transmits the login information in an extremely secure form, using Public Key Certificates(PKC). A certificate is a digital document that at a minimum includes a Distinguished Name (DN) and an associated public key. The certificate is digitally signed by a trusted third party known as Certificate Authority (CA). CA vouches for authenticity of the certificate holder. Each principal in the transaction presents a certificate as its credentials. The recipient then validates the certificate's signature against its cache of known and trusted CA certificates. Two kinds of certificates associated in mutual authentication, a "personal certificate" identifies an end user in transaction and a "server certificate" identifies the service provider ie. server.
In this article, I will discuss the steps to create digital certificate for client, storing it in server truststore, and storing it in browser certificates list. Also will discuss the steps require to enable certificate based client authentication in IBM Websphere Application Server and deploying the sample web application on server.
Creating Self-Signed Certificates
We can create self-signed certificates with little effort using the keytool utility included with the Java Development Kit. Generating a self-signed certificate can be accomplished by typing the following command in the command line:
keytool -genkey -v -alias {aliasname} -keyalg RSA -storetype PKCS12 -keystore client_keystore.p12 -storepass {anypassword} -keypass {anypassword}
The above command assumes that the keytool utility is in system PATH. This tool can be found under the bin directory, under the directory where Java Development Kit is installed.
Substitute the values for the {anypassword} with your own password; both of these passwords must be same in order to successfully use the certificate to authenticate the client. You may choose any value for the {aliasname} parameter. You may also choose any value for the -keystore parameter; however, the value must end with .p12 , as this command generates a file that needs to be imported into web browser, and this file won't be recognized unless it has the .p12 extension.
After entering this command from the command line, keytool will prompt for some information.
What is your first and last name?
[Unknown]: Mohit
What is the name of your organizational unit?
[Unknown]: ISL
What is the name of your organization?
[Unknown]: IBM
What is the name of your City or Locality?
[Unknown]: Pune
What is the name of your State or Province?
[Unknown]: Mah
What is the two-letter country code for this unit?
[Unknown]: IN
Is CN=Mohit Agrawal, OU=ISL, O=IBM, L=Pune, ST=Mah, C=IN correct? (type "yes" or "no")
[no]: yes
Generating 1,024 bit RSA key pair and self-signed certificate (MD5WithRSA)
for: CN=Mohit Agrawal, OU=ISL, O=IBM, L=Pune, ST=Mah, C=IN
[Storing client_keystore.p12]
After you enter the data for each prompt, keytool will generate the certificate; it will be stored in the current directory. The name of the file will be value we used for the -keystore parameter (client_keystore.p12 in this example).
To be able to use this certificate to authenticate ourselves, we need to import it into the browser. The procedure, although similar, varies from browser to browser. In Firefox, this can be accomplished by going to Tools->Options->Encryption->View Certificates , click import and give the path of the PKCS12 keystore and corresponding password.
Importing Certificate in GlassFish trust store
The certificate we created in the previous step needs to be exported into a format that GlassFish can understand:
keytool -export -alias myselfsigned -keystore client_keystore.p12 -storetype PKCS12 -storepass changeit -rfc -file selfsigned.cer
The values for the -alias,-keystore, and -storepass parameters must match the values used in the previous command. You may choose any value for the -file parameter, but it is recommended for the value to end in the .cer extension.
As our certificate was not issued by a certificate authority, GlassFish by default will not recognize it as a valid certificate. GlassFish knows what certificates to trust based on the certificate authority that created them. The way this is implemented is that certificates for these various authorities are stored in a keystore names cacerts.jks. The keystore can be found in the following location:
[glassfish installation directory]/glassfish/domains/domain1/config/cacerts.jks
In order for GlassFish to accept our certificate, we need to import it into the cacerts keytsore. This can be accomplished by issuing the following command from the command line:
keytool -import -file selfsigned.cer -keystore "C:\Program Files\glassfish-3.1.1\glassfish\domains\domain1\config\cacerts.jks" -alias myselfsigned -storepass changeit
At this point, keytool will display the certificate information in the command line and ask us if we want to trust it:
Owner: CN=Mohit, OU=IBM, O=IBM India, L=Pune, ST=Mah, C=IN
Issuer: CN=Mohit, OU=IBM, O=IBM India, L=Pune, ST=Mah, C=IN
Serial number: 4f2a86ca
Valid from: 2/2/12 6:21 PM until: 5/2/12 6:21 PM
Certificate fingerprints:
MD5: 3B:83:AF:7F:58:EC:D9:89:03:F7:FE:38:EF:C6:3A:73
SHA1: 6C:CD:02:78:0B:78:CB:0B:DD:C2:D3:DF:CA:85:49:79:52:0C:2A:38
Trust this certificate? [no]: yes
Certificate was added to keystore
Once we add the certificate to the cacerts.jks keystore, we need to restart the domain for the change to take effect.
Configuring Applications to Use the Certificate Realm
As we are taking advantage of Java EE 5 security features, we don't need to modify any code at all in order to use the certificate realm. All we need to do is modify the application's configuration in its deployment descriptors, web.xml and sun-web.xml .
<security-constraint>
<display-name>Constraint1</display-name>
<web-resource-collection>
<web-resource-name>ClientCertWebApp</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>master</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>CLIENT-CERT</auth-method>
<realm-name>certificate</realm-name>
</login-config>
<security-role>
<role-name>master</role-name>
</security-role>
In this case, we declared CLIENT-CERT as the authorization method and certificate as the realm to use to authenticate. This will have effect of GlassFish asking the browser for a client certificate before allowing user into the application.
When using client-certificate authentication, the request must always be done via HTTPS, therefore; it is a good idea to add the
Notice that we declared that only users in the role of master can access any page in the system; we did this by adding the role of master to the
<sun-web-app>
<context-root>/ClientCertWebApp</context-root>
<security-role-mapping>
<role-name>master</role-name>
<principal-name>CN=Mohit,OU=ISL,O=IBM,L=Pune,ST=Mah,C=IN</principal-name>
</security-role-mapping>
</sun-web-app>
We are now ready to test our application; after we deploy it on GlassFish server and point the browser to any page in the application we should see a pop-up screen which will ask to select certificate from the available certificates in browser.