Certificate based authentication with OpenAM 10 and Tomcat 7
Posted 11 years ago by Nemanja Lukic
Although my use case for certificate based authentication is pretty basic, the existing documentation for Access Manager/OpenSSO/OpenAM is somewhat scarce and requires gathering information from various, often unrelated sources. For that reason, I have summarised the process in this article.
The scenario is as follows:
- Access manager is used for authentication, authorisation and SSO;
- user accounts are stored in the LDAP repository;
- Certificate Authority (CA) publishes user certificates and/or certificate revocation list (CRL) to the LDAP repository, and/or at the same time providing OCSP service;
- remote users authenticate to access manager using the certificate issued by the CA (installed in their browser) – if the certificate authentication fails, access manager falls back to username and password authentication.
The software used in this setup is:
- ForgeRock OpenAM 10, for access management
- ForgeRock OpenDJ 2.4.5 LDAP directory
- Apache Tomcat 7.0.27 web container
- Sun Java Development Kit 1.6.0_31 (now Oracle)
- Red Hat Certificate System 4.3 CA
- Mozilla Firefox 12 browser
For the sake of length and clarity, I’ll focus only on the specific configuration parameters for given scenario and assume the following:
- OpenAM has been deployed on the Tomcat 7 and configured to use OpenDJ as the user store – neither of which are configured for SSL;
- PKI has been installed and configured to publish the certificates and CRL to OpenDJ and has OCSP service enabled.
If you do not have anything installed, please consult the OpenAM Installation Guide for OpenAM deployment on Tomcat, and our previous article on having RHCS CA publishing certificates to OpenDJ to install and configure a functional PKI. Operating the PKI software is out of the scope for this article, and I assume you would know how to get the CA root certificate chain and issue (user and server) certificates.
Overview of steps
The certificate based authentication requires not only OpenAM configuration to be modified but also the underlying web container in order to accept SSL connections, accept the certificate and to pass it to OpenAM. Therefore, we can divide the setup in two portions:
- web container setup, and
- OpenAM authentication configuration.
Each web container has it’s specific way how to configure SSL, but since Apache Tomcat is the most common, we’ll focus only on that one. The steps could be summarised as:
- add the CA certificate chain to $JAVA_HOME/jre/lib/security/cacerts
- create the key store for Tomcat;
- issue the server certificate for Tomcat;
- modify the $CATALINA_BASE/conf/server.xml to enable SSL
- restart the web container.
The OpenAM configuration is more simple:
- add a new authentication chain with certificate module and optional fallback module;
- configure the certificate authentication module to fit your scenario, and
- modify the realm to use the new chain for the user authentication.
By default Tomcat uses the certificate trust store provided with JDK which can be found in $JAVA_HOME/jre/lib/security/cacerts. That trust store has to contain the CA root certificate in order to trust the certificate that user sends. If you do not want to modify the default system store, you can create a new one and specify it in the Tomcat configuration. We will have to create a new key store for the server certificate anyway, so you can use the same process. For simplicity, we will use cacerts store in this example.
To install the CA certificate, you need to download it from your CA server and copy it to the server where Tomcat is running. Once you do that, you can import it via keytool:
keytool -importcert -trustcacerts -alias ExampleCA -file <path your CA cert> -keystore $JAVA_HOME/jre/lib/security/cacerts
You will need to provide the password, which is: ‘changeit’.
Next thing you need to do is to create the keynstore for Tomcat which will hold the certificate for the server, signed by your CA. We will create the key store in the Tomcat conf directory:
keytool -genkeypair -alias server-cert -keystore /opt/apache-tomcat-7.0.27/conf/keystore
This command creates the key store with the key pair, and stores them under the alias specified by the ‘-alias’ option. Make sure you use the FQDN for the common name (CN) field in the form, and put correctly the attributes that might be required by your certificate publishing configuration, for example:
Enter keystore password: password
Re-enter new password: password
What is your first and last name?
What is the name of your organizational unit?
What is the name of your organization?
[Unknown]: Example Corp
What is the name of your City or Locality?
What is the name of your State or Province?
What is the two-letter country code for this unit?
Is CN=openam.example.com, OU=Servers, O=Example Corp, L=Madrid, ST=Madrid, C=ES correct?
Enter key password for <server-cert>
(RETURN if same as keystore password):
This will create the key store with the self-signed keys for the server with FQDN ‘openam.example.com’ which belongs to the organisational unit ‘Servers’ and the organisation ‘Example Corp’. Now, if you imagine that your CA was configured to publish certificates by trying to match the attributes CN, OU and O from the certificate DN, it would try to find: cn=openam.example.com,ou=servers,o=example corp in your LDAP server. Normally you wouldn’t have the server certificate in LDAP, so only CN field as FQDN is required, the rest depends on your use case.
Once the key store has been created, you need to create a certificate signing request for your CA:
keytool -certreq -alias server-cert -file <path to your future certificate request> -keystore /opt/apache-tomcat-7.0.27/conf/keystore
The alias option has to specify the alias of the previously created self-signed certificate. After you have the certificate request, you need to pass it to your CA for signing, and once approved, download and install your new server certificate:
keytool -importcert -alias server-cert -file <path to your server certificate> -keystore /opt/apache-tomcat-7.0.27/conf/keystore
You may need to import the CA certificate chain the same way as for ‘cacerts’ but specifying the Tomcat key store instead. This might not be needed if the downloaded server certificate already includes the CA chain.
Now you are ready to configure your Tomcat for SSL. Open the server.xml file and find the commented section:
<Connector port=”8443″ protocol=”HTTP/1.1″ SSLEnabled=”true”
maxThreads=”150″ scheme=”https” secure=”true”
clientAuth=”false” sslProtocol=”TLS” />
remove the comments and modify it so you have something like this:
<Connector port=”8443″ protocol=”HTTP/1.1″ SSLEnabled=”true”
maxThreads=”150″ scheme=”https” secure=”true”
keystorePass=”password” keyAlias=”server-cert” keyPass=”password”
clientAuth=”want” sslProtocol=”TLS” />
The configuration is specifying the location and the password for the key store (keystoreFile and keystorePass) as well as which server certificate to use (keyAlias) with the certificate password (keyPass). The parameter clientAuth specifies how to handle the user certificate: ‘true’ (ask the user to provide the certificate and reject the access if the certificate is not valid or not provided), ‘want’ (ask for user certificate, but do not reject the access if not provided) and ‘false’ (do not ask the user for the certificate). ‘Want’ is a good option if you want to have the fall back option in OpenAM. Note that if no certificate is passed with the ‘want’ option, it does not affect the encryption of the communication, i.e. it would be still encrypted.
Restart the web container and you are ready to serve SSL requests.
For more information about the Tomcat server parameters, especially for the trust store, please have a look at the Tomcat reference. You might find some useful information in the OpenAM Administration Guide as well.
At this point, OpenAM still does not care about your certificates. For that to work, we need to configure a new authentication chain with the certificate authentication module.
Log in to OpenAM console as administrator, and:
- open the ‘Access Control’ tab;
- choose the realm you want to modify;
- go to the ‘Authentication’ tab and click on the ‘Module Instances’ link;
- click on ‘New’;
- name: ‘X509’ and choose ‘Certificate’ option;
- go to the ‘Authentication Chaining’ section;
- click on ‘New’;
- name: ‘X509Chain’;
- click on ‘Add’ twice to add two new lines;
- configure the first line as: instance ‘X509’ and criteria ‘SUFFICIENT’;
- configure the second line as: instance ‘DataStore’ and criteria ‘SUFFICIENT’;
- ‘Save’ and ‘Back to Authentication’;
- change the ‘Organization Authentication Configuration’ to ‘X509Chain’;
This configuration means that:
- the users would authenticate using the new authentication chain ‘X509Chain’ while the administrators would authenticate only via LDAP;
- X509Chain is configured first to validate the certificate specified by the user (X509 module)and if successful to allow the access – if not, to fall back to the username and password authentication in LDAP (DataStore module).
The only thing left is to configure the behaviour of the certificate validation. If you click on the X509 module in the ‘Module Instances’ section, you can access the validation properties:
- Match Certificate in LDAP – specifies if the certificate should be looked up in the LDAP; if enabled, OpenAM would perform a search in LDAP using as filter the attribute specified in the configuration (‘Subject DN Attribute Used to Search LDAP for Certificates’ parameter) and if found, it would extract the certificate from the ‘userCertificate’ attribute and then compare them; if the certificate is not found or it doesn’t match, the access would be rejected.
- Match Certificate to CRL – specifies if OpenAM should compare the certificate against the certificate revocation list also found in LDAP (‘Issuer DN Attribute Used to Search LDAP for CRLs’ parameter); if the certificate is revoked the access would be denied.
- OCSP Validation – specifies if OpenAM should use the Online Certificate Status Protocol to validate the certificate; normally, certificates contain the URL of the OCSP server (if enabled) which provides such information.
Typically, you would want to use only one of the three provided options. In the case of RHCS, if a certificate is published in the LDAP it would not be found in CRL (nor OCSP); once the certificate is revoked, it is deleted from LDAP user entry and published in the CRL list.
At this point, you should have a working configuration. For more details, please consult the OpenAM Administration Guide.
On the user side, you would need your personal certificate installed in the Firefox browser and once you open the OpenAM console page, it would ask you to provide the certificate. If valid, you’re good to go.
Hope it helps. Every feedback is more then welcome.
Thanks. This helped me configure ssl between OPENAM and DJ. But I having problem openam connecting to NOVEL LDAP (over ssl). Any suggestions?
Hi Jojo. Unfortunately, we haven’t dealt with Novell Directory before, so I can’t really say…
Just a slight correction to your article, when you mention:
name: ‘X.509′ and choose ‘Certificate’ option;
It should actually be X509, which you reference later. I found out that putting a dot in the name makes OpenAM treat it like a class name (I used a debugger), which is definitely not desirable!
Thank you very much for the correction! I have updated the article.
Thanks for your nice post. I am having a trouble though. I have the SSL certificate and user certificate from two different sources (CAs). When I try (after finishing configuration) I am being prompted for certificate and being displayed the user certificate. But once I choose and submit, somehow OpenAM is trying to use the SSL certificate and rejecting it as something it could not validate, or not a user certificate (mismatched source). Any clues?
Without knowing details it’s hard to guess. Do you have all CA certificates in the trust store?
when we setup the webserver for TLS (mutual cert based authetication).. if the client does not have a cert the webserver (tomcat) terminates the connection and throws a 403. So how do we ensure that the webserver does not terminate the http connection and instead forward the request to openam so that openam can then failover to the 2nd auth module in the chain ?
I do not know about the details about your setup, but a likely culprit could be the Tomcat configuration. Make sure that you have clientAuth=”want” in the Connector configuration. The behaviour you are experiencing occurs when you have clientAuth=”true”.
Hi, thank you for your publication
I installed openam and I configure X509 certificate chain but the module does not work. ? module = Certificate
Could you be more precise?
The problem I notice is that OpenAM does not seem to verify the entire certificate path (chain). It will query OCSP and verify the cert is not revoked but not for the issuing subordinate or root ca. This can be verified by a simple packet trace looking at OCSP request/response data. Do you know of any way to force OpenAM to verify the chain?