Requiring SSL client authentication in a user friendly way in Apache

Web browsers don’t display very friendly error messages to users when SSL client authentication fails. What most people understand from the error message displayed is “This site doesn’t work for me”. This is a usability failure. Your site should always display useful error messages to your users.

Another common usability failure is to allow users to present multiple client certificates when your site only trusts a certain type of certificate. The user has no idea which certificate they need to present, and they shouldn’t need to. The common solution to this problem is to provide documentation as to which certificate should be used. This is a poor solution.

In this article, I’ll describe how to configure Apache to require SSL client authentication in a polite, usable way.

[toc title=”Table of Contents”]

Politely requiring SSL client authentication

I’m using “require” somewhat loosely here, as that’s the first thing we are going to change in our configuration. When you use the SSLVerifyClient directive with the require value, it really means require. So, how do we get around this?

We change the SSLVerifyClient directive to the optional value. The key is making optional still mean require. Our goal is to redirect users to help documentation when SSL client authentication fails. We can do this by using mod_rewrite and environment variables from mod_ssl. Here’s how to configure this in Apache:

SSLOptions +StdEnvVars
SSLVerifyClient optional
SSLVerifyDepth 3
RewriteEngine On
RewriteCond %{SSL:SSL_CLIENT_VERIFY} !^SUCCESS$
RewriteRule .* /help/ssl-client-auth-required.html [L]

In this configuration, any request that doesn’t have a valid client certificate will be redirected to a help file. Optional, yet required politely. Don’t forget to be polite internationally, if that is a requirement! You should configure Apache to serve the help document based on the user’s language. I’m going to avoid this portion of the topic for now. I’ll go into this in a future article.

Selectively accepting client certificates

If your users have multiple types of client certificates; for email, client authentication, and encryption from different intermediate CAs; for instance; and your application needs a specific type of certificate; then you shouldn’t force your users to guess which certificate is required. There are a few options here:

  1. Provide documentation to educate users on which certificate to choose prior to them accessing the site
  2. Use the above method to educate users when they fail to choose the correct certificate
  3. Use both options 1 and 2
  4. Only allow users to choose the correct certificate by limiting which certificates your site will accept

The obvious choice from a usability perspective is option 4. It is less confusing, requires less documentation to be written and read, and is fairly easy to configure.

The first step is to identify which certificate authorities (CA)s you wish to trust. The next step is to append all of the public CA certificates into a single file. The final step is to configure Apache to use this file to restrict certificates. To configure this in Apache, use the following directive:

SSLCADNRequestFile /etc/pki/tls/certs/client-trust-bundle.cer

Unfortunately, option 4 will only be a viable option if the different certificate types were created by different CAs (which, hopefully, you are doing for security reasons). If you are unable to use option 4, you should use option 3.

  • Cat Mucius

    Thanks, Ryan!

    You just saved me a lot of trouble. :-)

  • Pingback: Apache SSL in htaccess examples()

  • Suat

    This was very helpful. Thank you!

  • Suat

    Ok, one problem – I wonder if you have solution for this.

    If there is no client certificate installed then everything works magically and redirects to the user friendly page.

    If there is valid client certificate installed then web application work as expected.

    If installed client certificate is expired or revoked then RewriteRule doesn’t work. I don’t think execution even reaches the ReWriteEngine section.

    Any idea that will make this already great information perfect?

    Thank you, once again.

    • Hm. I haven’t dealt with this in a while, but I’d imagine that at some point in the chain you have the ability to examine the CN portion of the cert, which should let you send back a message.

      • Suat

        I think once certificate is revoked, mod_ssl ignores ‘SSLVerifyClient optional’. It is actually a bit strange but it looks I have to live with it as I couldn’t have found any solution since yesterday.

        Thank you for replying.