How can I get client certificate authentication working in JBoss 5.1.0.GA when I'm using APR, and not all web deployments use CLIENT-CERT auth?

dkeen picture dkeen · Oct 30, 2011 · Viewed 9.6k times · Source

Note: I will be answering my own question... just wanted to add this tidbit to the collective wisdom of The Internets.

I've successfully configured certificate authentication on my JBoss 5.1.0.GA server, largely with the help of the information on this page: http://docs.jboss.org/jbossas/jboss4guide/r1/html/ch8.chapter.html

I have one context (let's call it /openContext) that doesn't require any authentication, and another context (let's call it /securedContext) that requires client certificate authentication (i.e., it's configured to use CLIENT-CERT in web.xml). When using JBoss's default web connector, this works splendidly. I can hit http://myhost/openContext and I'm not prompted for a certificate, but when I hit http://myhost/securedContext, I'm prompted for a client certificate as I'd expect.

However, when I install JBossWeb Native and use APR as my web connector, I'm no longer prompted for a certificate when I hit http://myhost/securedContext.

My APR connector config in server.xml looks like:

<Connector protocol="HTTP/1.1" SSLEnabled="true"
    port="8443" address="${jboss.bind.address}"
    scheme="https" secure="true" clientAuth="false"
    SSLProtocol="SSLv3+TLSv1"
    SSLCipherSuite="ALL:!ADH:!SSLv2:!EXPORT40:!EXP:!LOW"
    SSLRandomSeed="/dev/urandom"
    SSLCertificateFile="/etc/pki/tls/certs/mycert.crt"
    SSLCertificateKeyFile="/etc/pki/tls/private/mycert.key"
    SSLPassword="mypasswordwhichiassureyouisbetterthanthisone"
    SSLCACertificateFile="/etc/pki/tls/certs/clientCAs.crt"
/>

I've also tried adding the SSLVerifyClient parameter to that configuration and setting it to optional, but that prompts for a certificate in both /openContext and /securedContext, which isn't the behavior I want.

How can I get JBoss with APR to require certificate authentication for one web context, but not another web context?

Answer

dkeen picture dkeen · Oct 31, 2011

What worked for me was to just add a whole new web connector, and have clients use that alternate port for the secured web context. My connectors config now looks like:

<Connector protocol="HTTP/1.1" SSLEnabled="true"
    port="8443" address="${jboss.bind.address}"
    scheme="https" secure="true" clientAuth="false"
    SSLProtocol="SSLv3+TLSv1"
    SSLCipherSuite="ALL:!ADH:!SSLv2:!EXPORT40:!EXP:!LOW"
    SSLRandomSeed="/dev/urandom"
    SSLCertificateFile="/etc/pki/tls/certs/mycert.crt"
    SSLCertificateKeyFile="/etc/pki/tls/private/mycert.key"
    SSLPassword="mypasswordwhichiassureyouisbetterthanthisone"
/>
<Connector protocol="HTTP/1.1" SSLEnabled="true"
    port="8543" address="${jboss.bind.address}"
    scheme="https" secure="true" clientAuth="true"
    SSLProtocol="SSLv3+TLSv1"
    SSLCipherSuite="ALL:!ADH:!SSLv2:!EXPORT40:!EXP:!LOW"
    SSLRandomSeed="/dev/urandom"
    SSLCertificateFile="/etc/pki/tls/certs/mycert.crt"
    SSLCertificateKeyFile="/etc/pki/tls/private/mycert.key"
    SSLPassword="mypasswordwhichiassureyouisbetterthanthisone"
    SSLCACertificateFile="/etc/pki/tls/certs/clientCAs.crt"
    SSLVerifyClient="require"
/>

Now, if I hit http://myhost:8443/openContext, I'm not prompted for a certificate, but when I hit http://myhost:8543/securedContext, I am prompted for a certificate. Of course, I can still access either web app with the "wrong" port, but the consequences are negligible for my purposes. If a client hits http://myhost:8443/securedContext, they simply get an HTTP authentication error. If a client hits http://myhost:8543/openContext, they're prompted for a client certificate. If they provide one, great (though I don't care who you are), and if they don't provide one or provide an invalid one, they get an HTTP auth error (they should have used the correct port in the first place).

I'm pretty sure there's an alternative way to get this working without requiring a second connector by putting httpd in front of JBoss and doing some clever configuration there, but this worked well enough for my purposes.