Two Guys Arguing

Mutual Authentication with CLIENT-CERT, Tomcat 6, and HttpClient

Posted in java by benjaminplee on 11.03.09

M is for Mutual Authentication:

How “it must be simple” turned into “god that was annoying”.

I spent most of today wrestling with getting a JEE webapp running in Tomcat 6 to enforce mutual authentication by using the rarely used CLIENT-CERT authentication.  If you love spending your days translating poor error messages and frustrations into Google queries as much as I do, read on for some notes I took along the way.  If not, check out this amazing chart over at XKCD.

The mission: lock down a particular action on our web application so that only a single other system could authenticate and invoke it.  Also provide an example client application which can access the webapp.

Back story: I have worked with certificates and various forms of authentication before, but never this combination.  We want a small subset of the application to only be accessed via SSL with both server and client providing trusted certificates for mutual authentication.  The portion of the application will only be accessed by a single other system inside the company intranet.

How it went down:  The following are the basic steps to get everything setup in Tomcat 6 and a fairly standard JEE webapp.

  • First we need to know who we are, who they are, and make sure we ONLY trust them and no one else
    • To do this we need a certificate to identify ourselves.  Java’s provided keytool.exe provides an easy way to create a self signed certificate within a keystore.  Keytool can also help us export our public certificate out of our keystore.  This should also be done for the client.
    • Next import the public certificates into a new truststore for the opposite system (A only trusts B and B only trusts A).  Keytool to the rescue again.
    • Note: Java keystore files and certs of in a different format than the PKCS12 files that can be created by OpenSSL
  • Next configure a Tomcat to support SSL communication
    • Add a new connector to thees server.xml configuration specifying HTTPS, the SSL protocol, where the webapp’s keystore and truststores are, etc
    • <Connector className=”org.apache.coyote.tomcat4.CoyoteConnector”
      port=”8443″ enableLookups=”true”
      acceptCount=”100″ connectionTimeout=”20000″
      useURIValidationHack=”false” disableUploadTimeout=”true”
      scheme=”https” secure=”true” SSLEnabled=”true”
      keystoreFile=”ourApp.keystore” keystorePass=”changeit”
      truststoreFile=”ourApp.truststore” truststorePass=”changeit”
      clientAuth=”false” sslProtocol=”TLS”
      />
    • Note: clientAuth can have 3 values
      • True – all connections through this connector require client authentication
      • Want – the web app will ask for authentication but not require it
      • False – connections do not require client authentication UNLESS the web app specifies it is required via a security constraint with CLIENT-CERT chosen (this is the one we want)
  • Configure a new user with the required security role in the tomcat-users.xml if the in-memory realm is used
    • <role rolename=”secureconn”/>
    • <user username=”CN=TheirApp, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown” password=”null” roles=”secureconn”/>
  • Configure out web.xml to use a CLIENT-CERT authentication constraint for our action
    • <security-constraint>
      <web-resource-collection>
      <web-resource-name>Demo App</web-resource-name>
      <url-pattern>/secure/*</url-pattern>
      </web-resource-collection>
      <auth-constraint>
      <role-name>secureconn</role-name>
      </auth-constraint>
      </security-constraint><login-config>
      <auth-method>CLIENT-CERT</auth-method>
      <realm-name>Demo App</realm-name>
      </login-config>

      <security-role>
      <role-name>secureconn</role-name>
      </security-role>

  • Create a client to hit the application
    • Here we used the Apache Commons HttpClient (3.x b/c of client restrictions)
    • Several pages talk about various ways to add security protocols to HttpClient code but the examples are left lacking and most point to the AuthSSLProtocolSocketFactory class which for some reason is not present int he 3.x binaries but IS present in the 3.x SRC bundles.
    • ** I will include some sample code tomorrow ….
  • Test things using Firefo
    • You can add a personal certificate to identify yourself through Firefox’s preferences -> Advanced -> Exncryption
    • Firefox uses PKCS12 certificates which can be created easily from scratch through a few OpenSSL commands or from an existing keystore certificate through one hairy keytool command
    • ** I will include the commands and a couple links tomorrow …..

Hopefully these notes will help someone in the future with getting things setup correctly.  When I started this morning I couldn’t find an end to end example to build on.

Edit: Huge thanks to Matt Todd for helping me with this.  You can check out his blog at: http://emergentdevelopment.blogspot.com/ .

About these ads

24 Responses

Subscribe to comments with RSS.

  1. benjaminplee said, on 11.04.09 at 9:34 am

    I forgot to include a large Thank You to fellow Asynchronian Matt Todd for his help figuring all of this out. You can check out his blog over at http://emergentdevelopment.blogspot.com/

  2. Carlos said, on 01.29.10 at 7:20 am

    Hi, thanks for the post!

    I`m working with CLIENT-CERT login but I have troubles with the tomcat-users.xml configuration.

    Please, can you explain how can I map the tomcat`s users and the certificates?? Its the subject?

    Thanks

  3. Selena Rodriguez said, on 02.12.10 at 3:57 pm

    While I agree with the OP regarding the method, I have to argue its application and whether it was actually necessary in this situation…

  4. gerrycharliebillysomeonesusanwillstevewendygerrybradlysomeonesusanstevensteviestevenstanleyrichardryanwilliamsteviestephengerrykimsusan said, on 04.05.10 at 11:02 am

    Excellent post, I like these posts most of all.
    Practical information that everyone can use

  5. zetxek said, on 08.09.10 at 7:54 am

    Any chance you can include the code that you mention? I’m having some trouble making mutual authentication work on tomcat (v 5,6,7, does not mind…). I’d be very grateful!

  6. benjaminplee said, on 08.10.10 at 7:37 am

    zetxek,

    Sure; if I can find it. I will take a look around today and see if I still have a copy of the code.

  7. zetxek said, on 08.10.10 at 7:40 am

    Thank you so much. At the moment I’m having some weird problems with my truststore, I think, with the result of a “ssl_error_handshake_unexpected_alert” error on firefox that does not allow me to display the page. IE simply does not load it…

    • kris said, on 03.26.13 at 2:17 am

      Zetxek, I have got a similar requirement and followed the instructions posted by benjaminplee and got exactly the same error in firefox and IE as posted by you. just wondering if you were able to resolve it and if yes, it would be great if you could share the resolution.

      P.S: benjaminplee, thanks for the wonderful post

      • kris said, on 03.27.13 at 3:17 am

        the error is resolved..posted the resolution in comment below..thanks

  8. Streben said, on 04.04.11 at 3:33 pm

    I have a question about this tuto ,what is the command to create truststore, thks

  9. Doug said, on 05.15.11 at 8:10 am

    “…or from an existing keystore certificate through one hairy keytool command.”

    This command is:
    keytool -importkeystore
    -srckeystore source.p12
    -srcstoretype PKCS12
    -destkeystore destination.jks
    -deststoretype JKS
    -destalias foo

  10. MIdnightJava said, on 05.27.11 at 4:57 pm

    I tried this approach exactly, and it does not work with the . If I leacve that out, I can connect to my web app, with clientAuth = true; so I know my certs and truststore are setup properly. But when I include the with a rolename that matches a rolenam in tomcat-suers.xml, to which is mapped a user whose username is equal to my DN, the browser tells me it could not authenticate with the provided credentials.

    I re-checked all my configurations a dozen times, and I have it all entered correctly. I’m using tomcat 6.0.29.

    Can anyone think of what I might be missing? Is this really working for everyone else?

  11. MIdnightJava said, on 05.27.11 at 5:00 pm

    I had some angle brackets in my post that caused some words to be dropped. Here is my post again without the angle brackets.

    I tried this approach exactly, and it does not work with the auth-constrain . If I leave that out, I can connect to my web app, with clientAuth = true; so I know my certs and truststore are setup properly. But when I include the auth-constraint with a rolename that matches a rolename in tomcat-users.xml, to which is mapped a user whose username is equal to the DN from my cert, the browser tells me it could not authenticate with the provided credentials.

    I re-checked all my configurations a dozen times, and I have it all entered correctly. I’m using tomcat 6.0.29.

    Can anyone think of what I might be missing? Is this really working for everyone else?

  12. MidnightJava said, on 05.27.11 at 9:37 pm

    Turning on SSL debugging (-Djavax.net.debug=ssl) showed me what the problem was. When I saw the cert coming across, I saw that there were spaces between each comma-separated part of the DN. When I copied the precise characters from the debug output to the username attribute in tomcat-users.xml, it worked.

  13. Michel said, on 11.20.12 at 6:04 pm

    I’m having the following problem:
    HTTP Status 401 – Cannot authenticate with the provided credentials

  14. [...] on the web on how to configure SSL in Tomcat. Tomcat Server/Client Self-Signed SSL Certificate and Mutual Authentication with CLIENT-CERT, Tomcat 6, and HttpClient stand out. But there no simple example, where we can demonstrate Enabling SSL in Tomcat, I spent [...]

  15. Grateful said, on 01.09.13 at 10:08 am

    Thank you very much, I would NEVER thought of putting “CN=TheirApp, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown” as an username…

  16. aldo said, on 01.15.13 at 7:50 am

    Hi quick question, do you know how to add the client certs on runtime, i mean without restarting tomcat

  17. Warner Piñero said, on 01.31.13 at 3:00 am

    benjaminplee, when I tried navigating to the secured/protected page, it didn’t show me a popup dialog to select a certificate. How do we show that popup dialog with the clientAuth set to false in tomcat’s server.xml?

    • kris said, on 03.26.13 at 11:59 pm

      Hi Warner, I am struck up with a similar situation, everything works as expected when clientAuth is set to true or want, but it doesn’t work when it is set to false inspite of setting auth constraint in web.xml. Did it work for you?

      • kris said, on 03.27.13 at 3:16 am

        finally it worked for me. the problem was with jdk version 1.6.0_20 which was giving me this error
        WARNING: SSL server initiated renegotiation is disabled, closing connection

        I upgraded to jdk 1.6.0_35 which has fix for this bug. apparantly the bug has been fixed in jdk 1.6.0_22.

        Apart from this bug, i had done everything as said by benjaminplee.. thanks a ton for this wonderful post.

  18. Akilah said, on 01.31.14 at 3:16 am

    WOW just what I was searching for. Camee here by searching for attorneys criminal law

  19. I don’t even kno the way I stopped up right here, but I believed
    this put up was once great. I do noot recognise
    who you are however definitely you’re going to a well-known blogger if
    you are not already. Cheers!

  20. Rebecca said, on 10.08.14 at 1:23 pm

    You share interesting things here. I think that your blog can go
    viral easily, but you must give it initial boost and
    i know how to do it, just type in google for – mundillo traffic
    increase go viral


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.