Tuesday, February 21, 2012

Getting Google Authenticator and Apache to Cooperate on CentOS

I love the idea of using two factor authentication to harden a web app. Recently, I discovered Google Authentication for Android, which together with the Google Authenticator platform, brings two factor authentication to The Rest Of Us.

In theory, leveraging Google Authenticator and .htpasswd should be as easy as installing the Google Authenticator Apache Module. Alas, that turns out to be much easier said then do. So, to help others out there, here's the steps I went through to lock down a directory in Apache with a one time use password from Google.

These instructions should be thought of as general road map - I'm still figuring out how the whole system works, so I apologize if I've included optional steps, or left out required ones. Where possible, I've favored specific Linux commands over explanations. If the commands bother you, you shouldn't be installing this module.

  1. Grab the tools needed to compile the Apache module: yum install httpd-devel
  2. Grab the Google Authenticator command line tool: yum install google-authenticator
  3. Grab the source code for the Apache module: wget http://google-authenticator-apache-module.googlecode.com/files/GoogleAuthApacheModule_v01.bz2
  4. CRITICAL: Grab mod_authn_google.c from this discussion. Use it replace the file found in the above download. Failing to do this will install a version of the module which prompts you for a password after a minute.
  5. Update line 7 of the Makefile to have the correct install path. I changed mine to read:
    install: all
             sudo cp .libs/mod_authn_google.so /etc/httpd/modules
  6. sudo make install
  7. Create the appropriate user-dir: sudo mkdir /etc/httpd/ga_auth
  8. Install Google Authenticator on your Android device and start it up.
  9. Generate the Google Authenticator configuration for the user: google-authenticator
  10. Notice that the first line of the Google Authenticator output is a URL that looks like: https://www.google.com/chart?chs=200x200&chld=M|.... Copy and paste that URL into a browser.
  11. In the Android app, select: Menu > Scan a barcode. Point it to the QR code image shown on the screen in the previous step.
  12. Store the generated Google Authenticator file where the Apache module can see it: cp ~/.google_authenticator /etc/httpd/ga_auth/foo, where foo is the user who will be logging in. Make sure the permissions are correct so the webserver can access it.
  13. Update your Apache config to have a block like so:
       <Directory />
         Options FollowSymLinks ExecCGI
         AllowOverride All
         Order deny,allow
         Allow from all
         AuthType Basic
         AuthName "Shhhhh, secret."
         AuthBasicProvider "google_authenticator"
         Require valid-user
         GoogleAuthUserPath ga_auth
         GoogleAuthCookieLife 3600
         GoogleAuthEntryWindow 2
  14. /etc/rc.d/init.d/httpd restart
  15. Watch the error log for debugging info: tail -f /var/log/htttpd/error_log
  16. Point your browser to a protected directory

If all went exceedingly well, you'll be asked for a username and password. Enter the username you created in /etc/httpd/ga_auth, and use the Android app to enter the current 6 digit password.

If it doesn't work, and you see mention of "(null)" in the error log, check out this discussion.

Don't forget to run this all over SSL, or you'll be leaving a gaping security hole open.

Good luck!


  1. Anonymous1:20 PM

    Greetings Ben -

    I set up the Apache2 + Google Authenticator and it works just fine as an OTP (One Time Password) authenticated system. The problem is that this is not really 2-factor authentication. I have spent considerable time researching the web for papers and other offerings that discuss both 2-factor authentication and specifically adding Google Authenticator to Apache. These all call the addition of Google Authenticator a 2-factor solution. They are wrong and here is why:

    True 2-factor must use 2 separate forms of authentication that are not directly discoverable from either factor alone. Traditionally "something you know" like your password and "something you have" like your OTP generator. In order to use these you would normally need 3 fields to enter information: Username, Password and OTP code.

    The Apache setup simply asks for a Username and the OTP code. This is single factor authentication. Sure it is better than a static password - but it is not 2-factor.

    I have tried to find a way to force Apache to ask for both factors (my password and the OTP code) but it seems that you can only specify one form of authentication at any one time for Apache. Either it uses a password provider like Google Authenticator OR it uses a password file like .httaccess. It does not seem possible to get it to use both forms of authentication.

    If I am missing something I would very much appreciate your help with underrstanding how to get Apache to require both an account password AND a second factor like an OTP code.

    Hoping to hear from you -


    Joel Lieberman


    1. Anonymous3:02 AM

      You would (unfortunately) have to run two jailed Apache instances, with re-directions to emulate this as far as I can tell.

      You would then need to specify a cookie to maintain the session and prevent "authentication hopping"

      The other method would be to build a ruby or perl interface to the API of the webpage and handle your authentication in-app.

      As far as I can see this is just a limitation of Apache, and so realistically it's not the smartest way to implement this, although it is a convenient quick and dirty solution to password staticity.

      I would be glad to be proven incorrect though.

  2. Joel -

    You're absolutely right. And that annoys me. Add to that, I can't believe that a 6 digit password is really that secure.

    Still, I'm happier using this arrangement than manually changing my password frequently.

    If you figure out how to offer true 2 factor encryption, I'd totally be on board with trying it.

  3. That is really an awesome point. Perhaps we should allow for a "static" password to be used *in conjunction with* the generated code. I need to think about that.

    Also - the newest release on the web site now has fixes, so the patches you discussed are no longer required. You can just download and use the source (or provided binary) as-is.

  4. Brad -

    Thanks for the heads up about the newest release not needing patches.

    A static password combined with the 6 digit password would be great.

    Though, I really do love this module. It may not be true 2 factor encryption (yet), but it's way better than I'd normally get.

  5. Build r22 now supports true "two-factor" - i.e. includes the ability to add a static password in conjunction with the one-time code.