Two-factor TOTP codes

3 minute read

Two-Factor authentication is a good way of increasing login security in systems, and is now quite widespread: it’s the six digit number that rolls over every 30 seconds. It’s designed to be very simple to operate as a user, but how much effort is involved as a developer?

How 2FA works

There’s a couple of different methods for multi-factor authentication; I’ll be looking at the Time-based One-Time Password algorithm (TOTP).

As it turns out, it’s quite straight-forward to get started with. On the server side, a secret key is generated and stored, then sent to the user (typically as a QR code or a hex string). This is a shared secret.

When the user wants to login, the server asks for their code. The user generates this from the shared secret we gave them earlier and the current time. Concurrently, the server generates a code in the same way. If both system clocks are in sync, the codes match and the user is validated.

It’s quite common for clocks to be slightly out (potentially up to a minute each way), so the server can compensate by generating additional codes that have been shifted in time; if one of these codes lines up with the user, we can still validate them.

This is just an overview — in practice, you’ll need to deal with more complexities (such as not allowing the same 2FA code to be submitted multiple times).

Developer implementation

In Python

Python has the very handy PyOTP library, which takes care of pretty much everything for us.

import pyotp

# Generate a new shared secret (or load one made previously)
shared_secret = pyotp.random_base32()
print("The TOTP seed is: %s" % shared_secret)

# Make a TOTP object and get the current verification code
totp = pyotp.TOTP(shared_secret)
print("The TOTP code is: %s" % totp.now())

We can also generate a QR code to send to the user through the pyqrcode library.

import pyqrcode
uri = totp.provisioning_url("user@example.com", "Cool App")
qr = pyqrcode.create(uri)
qr.png("output.png", scale=5)

In JavaScript

I’m using this in a Browser context, so you’ll need to make changes if you’re using it inside Node.

JavaScript is the same: nothing built-in, but the otplib library supports everything we need. I’m also using the node-qrcode library to make the QR code you’ll see below. Both of these libraries are loaded into the page using the unpkg CDN. With that done, we can generate OTP codes:

// Create a shared secret
var seed = window.otplib.authenticator.generateSecret(10);
document.getElementById('totp_seed').value = seed;

// Get the current token for the secret
var otp = window.otplib.authenticator.generate(seed);
document.getElementById('totp_token').value = otp;

// Show the QR code in the 'totp_qr' <canvas> tag.
var uri = window.otplib.authenticator.keyuri(
    'user@example.com', 'sigsec', seed);
QRCode.toCanvas(document.getElementById('totp_qr'), uri);

My examples

I’ve written a couple of example implementations: if you’ve got any feedback or commentary, please tweet at me or drop me an email!

Python script

I’ve written a handy little Python TOTP tool that you can grab from my Github here. It should be a good starting point to see how to work with the two libraries I described above. It’s also fully functional, so feel free to put it through it’s paces!

A Linux terminal showing command help output A Linux terminal showing command QR code output
My TOTP tool in action

Live JavaScript demo

Here’s a live demo, using JavaScript. This is only for fun and to play around with; please don’t try using this code in a production environment!

TOTP seed:
Code:
Generated at: