Using Google Authenticator (TOTP) On Your Site

Let’s say you want to use two-factor authentication on your site. (Blog entries to follow…). How do you do it?

Time-based One-Time Passwords (TOTP)

An increasingly popular approach is Time-based One-Time Passwords (TOTP) (RFC6238). This is a straightforward algorithm that only requires an accurate clock and a shared secret.

Accurate times have been a pain in the past – computers did not include particularly good real time clock chips – but any server should now be using NTP. I think the major distributions set it up by default but could be mistaken about that.

Modern cell phones also have the accurate time since they include GPS receivers.

Finally dongles with LCD displays can include accurate clocks, esp. if you’re able to periodically synchronize them to a PC.

Put it together and we can have reasonable confidence that we’ll have matching clocks on the client and server so TOTP becomes a good option.

Jumping straight to the code – this is the reference implementation from the RFC. The RFC also includes test vectors to verify implementations.

Google Authenticator

Enter Google. Or more precisely, Google Accounts. This is a popular hosting platform for small businesses, non-profits and groups. Even individuals with vanity domains.

Many of these users require better security than you get with just a password. Some users REQUIRE better security due to regulatory or contractual obligations.

Google saw the problem and came up with a solution: Google Authenticator. It is an open source implementation of the TOTP algorithm that has been implemented on smart phones and as a Linux PAM module. Not everyone has a smart phone but enough do for this to be a good solution. Hardware dongles are also available if you prefer them.

(IMPORTANT: the security of the Linux PAM module is debatable since it includes the user’s secret key, unencrypted, in the user’s home directory.)

The code to generate the code produced by Google Authenticator implementations is:

(Sidenote: it goes without saying that the googlecode project includes similar code. I’m using the RFC reference implementation since it’s much more flexible – I might want to use different parameters in other situations.)

Server-side Implementation

The server-side implementation is fairly straightforward.

Registration

Create a random 8-byte secret key. Be sure to use a cryptographically strong random number generator (SecureRandom), not the standard random number generator.

Save the key in the database. ENCRYPT IT.

Create a unique label, e.g., the username @ the site’s domain name. You don’t want to use anything that can change, e.g., the user’s email address, or something that might be used at other sites, e.g., nothing but his username. Remember that this is what is used to remind the user to use this key – you don’t want to use random strings.

Provide the user with a QR code that he can scan using his smart phone. You can also provide the secret key in a string for he user to enter manually.

There is a standard URI for providing secret keys.

The URI for a TOTP key is otpauth://totp/LABEL?secret=SECRET where LABEL is the unique identifier you created above and SECRET is the base32-encoded shared secret.

Base32 uses the case-insensitive letters A-Z and the digits 2-7 to encode a value and corrects for several common errors, e.g., using ‘0’ instead of ‘O’. An encoder is available in the Apache commons-codec project.

You can get QR image for this URI at google.com, e.g., for otpauth://totp/alice@google.com?secret=JBSWY3DPEHPK3PXP it is
<img src=”https://www.google.com/chart?chs=200×200&chld=M|0&cht=qr&chl=otpauth://totp/alice@google.com?secret=JBSWY3DPEHPK3PXP”/>

With the QR code the user can simply point his smartphone at his monitor to load his key.

Verification

The user is prompted for his username, password, and TOTP code

When the login form is received three codes are generated – for the current time, 30 seconds ago, and 30 seconds from now. This gives you a bit of buffer to allow for unsynchronized clocks or the time required by the user to enter the data and submit the form.

Check the codes and respond accordingly.

Lost or Compromised Keys

People lose the phones. Local policy may require access credentials to be changed periodically. You have to be prepared.

The user authenticates himself using the current TOTP code (if it’s a a periodic change) or via some other mechanism. (Do not ask the common easy to guess questions!)

A new secret key is created and provided to the user as described above.

The old secret key is either deleted (low security) or retained to capture attempted uses in the future (high security).

As always you never provide current credentials to the user.

Crash Codes

Sometimes people do not have access to their phone (e.g., they’re in a secured environment) or are otherwise unable to use the TOTP code. We must provide a fallback mechanism.

Fortunately this is very easy – provide the user with the eight digit code for the first few values, say counter = 0 to counter = 5. Strictly speaking these are now Hash-based One-Time Passwords (HOTP).

The user should treat these codes in the same way as passwords.

The authentication process now checks the current time for 6 digit codes, or the first few counters for 8 digit codes.

Oracles

I mentioned that the secret key should be encrypted but we can make this design much more robust by using an oracle. These are stored procedures that encapsulate all of the logic and the application is provided the absolute minimum amount of information.

Many databases support SHA1 HMAC computations, e.g., in the pgcrypto package for PostgreSQL. The trick to remember is that the last nybble of the hash is used as the offset into the hash before converting the hash into an integer – that’s not a common approach yet.

Implementation is left as an exercise for the reader. (Hint: you can always be lazy and ask the database crypto provider to add this function!)