One-Time Passwords

Google Authenticator One Time Password (OTP) ApplicationUse One-Time Passwords to secure your systems.

For free.

Password-stealing trojans are commonplace, and constantly changing your password is maddening, So I decided to switch to access control via a hardware token.

The system creates a new random token (six digit password) every 30 seconds. Many vendors sell similar systems, but they’re very expensive and the license and hardware fees never end.

Being an “Open Source” kind of guy, I decided to see if there was an alternative. And there is. And it’s dead reliable, And it’s from Google. And it’s free!

There are client apps available for nearly every platform imaginable, however for Android, I chose Google Authenticator because it’s extremely reliable and well supported with a tiny footprint on the phone. Google created it to make GMail accounts un-hackable after an earlier embarrassing incident,

Geek-speak below. You may like the human-friendly explanation better. 8-)

For the server side, I chose an Apache web server authentication module called mod_authn_otp. There are a large number of server-side plugins for various purposes, but this one is easy to install and is well-supported by the author.

How To:

  • Install mod_authn_otp on your web server and Google Authenticator on your phone
  • Fill in the form below and click “Go!.”
  • Scan the generated 2-D barcode with Google authenticator
  • Add the generated config line to the mod_authn_otp config file on your web server.

You’re done!

Try It Yourself!

Google Authenticator / mod_authn_otp
Configuration Generator (demo)

Site Name
User Name


Randomness:The random number is, by default obtained from /dev/urandom, which is non-blocking and “mostly random” however for for the paranoid or careful among you, the app contains an option to switch between /dev/urandom and /dev/random as you wish.

Considerations when selecting a random number source:

  • /dev/random is truly random, but on most systems contains only enough random bits to generate a few keys at a time. If it runs out of random bits, it will wait until it has more, which may block other cryptographic functions such as SSL and HTTPS.
  • /dev/urandom is only pseudo-random, however it will never run out of bits.

The choice is yours. If you require large quantities of truly random numbers, there are companies that sell hardware random number generators.

The source code is available for download. Just rename ga.txt to ga.php after downloading.

Making it all work:

Add this to your .htaccess or a <directory> or <location> block in your apache config file.

# Force SSL.
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
SSLOptions +StrictRequire
SSLRequire %{HTTP_HOST} eq ""

# The rich, nougaty center. 8-)
AuthType Basic
AuthName "Webmail"
AuthBasicProvider OTP
Require valid-user
# The users file needs to be chmod to read/write by the web server
OTPAuthUsersFile /var/www/mod_auth_motp/users
OTPAuthMaxLinger 14400
OTPAuthLogoutOnIPChange On

Order Allow,Deny
# the line below means that you won't need the token 
# if you're coming in from a trusted network. 
# Be sure to change below to whatever your IP or CIDR is.
# Or comment it out. It's completely optional.
Allow from
Satisfy Any


9 thoughts on “One-Time Passwords

  1. thanks this worked pretty well for me … a few instructions missing here and there … one thing i’d like to ask: when i put the php script on my server, after i’d installed php and added ffiletypes to apache’s config, i keep getting only this on the ga.php:

    usage: ga.php?site=GumbyMail&user=myname
    Valid characters are: 0-9, A-Z, a-z, – and space

    any ideas?

  2. Carsten January 4, 2015 at 6:00 am

    Created a version that didn’t publish my secret to google!!!

    Why do u use chart-api instead of a qr lib?

    Aside from the Google issue, this online demo is by no means secure, since it runs on my server, not yours.

    Knowing your secret isn’t a huge risk, since there’s nothing that identifies which machine it’s used on. There’s nothing in the key that identifies the resource it grants access to, however, yes, having Google (or me) know your secret is a slight incremental list.

    You should also note that using the Google Authenticator Android application is also a risk, since Google controls it, and has access to your phone anyway, where they could simply download all your keys if they wished.

    However if you’re extremely concerned with security, I’d suggest modifying the application to use only local resources (as you’ve done) and run it on a non-networked machine, and run the authenticator app on a phone with no network or cell access. Some people like the hardware-based tokens better, however these have been known to be compromised in bulk (RSA, for example).

  3. Very nice, succinct description of how to do one-time-passwords in a stand-alone apache2 install. That was exactly what I needed for my do-it-yourself-secure-home-automation project (diysha). Thanks!

  4. I got it :) if I change otpauth://otp/ to otpauth://hotp/ everythnig works just perfect ;) Of course on the server user list:
    HOTP/T30 user – key should be changed to: HOTP user – key

  5. Hi,
    it’s a really very nice article. I have only one question :) If I want to use counter based token what I have to change in your PHP code to work with this type of token. Thank you.

  6. You’re welcome!

    All the bits and pieces had been written by others, but after spending several days trying to glue them together, I decided that I couldn’t be the only one who needed an easier way.



  7. Fantastic !

    I was playing with GAuth + LDAP with SSH using Groups etc, then I found your article looking for authn_otp + GAuth !

    Thank you very much indeed for the contribution.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>