Two-factor-authentication (2FA) in Django

Why talk about this?

2FA uses an open standard, defined in this RFC and can be easily implemented on a website for free.

We will be using PyTOTP (Time-Based One-Time Password) to generate the 2FA tokens in our app.

Since the standard is open, we can use any authenticator app to handle token generation - eg. Google Authenticator, Authy, Microsoft Authenticator etc.

How does it work?

The core mechanism uses TOTP (RFC 6238): - Both your device and the server have the same secret key - Both use the current Unix timestamp (divided by 30 seconds) - Both apply the HMAC-SHA1 algorithm to generate a 6-digit code - Since they use the same inputs, they generate the same code

Simplified pseudocode:

def create_2fa_auth(user):
    secret_key = generate_random_secret()

    # Store on backend
    user.secret_key = secret_key

    # Supply secret to user via QR code
    return generate_qr_code(secret_key)

def generate_2fa_code(secret_key, time_offset=0):
    # Simplified algorithm on Backend and Auth app
    current_time = floor((unix_timestamp() + time_offset) / 30)
    secret_bytes = base32_decode(secret_key)

    result = generate_code_bytes(secret_bytes, current_time)
    six_digit_code = get_code_from_bytes(result)

    return format(six_digit_code, "06d")

def verify_2fa_code(user, user_entered_code):
    secret_key = user.secret_key
    expected_code = generate_2fa_code(secret_key)

    # Allow for time drift (±1 time window = ±30 seconds)
    previous_code = generate_2fa_code(secret_key, -30)
    next_code = generate_2fa_code(secret_key, +30)

    return (user_entered_code == expected_code or 
            user_entered_code == previous_code or 
            user_entered_code == next_code)

Why is it secure?

  • Time synchronization: Both your device and the server must have roughly synchronized clocks (usually within ±30 seconds)
  • Secret key security: The secret is never transmitted again after initial setup - it's stored locally on your device
  • One-time use: Each code is only valid for 30 seconds, then a new one is generated
  • Offline capability: Your authenticator app works without internet because it only needs the secret and current time

Potential issues

  • If you lose your device you're locked out (an administrator can easily fix this by just disabling 2FA for that user)
  • Device clock must be accurate