Docs / Security / How to Set Up TOTP Two-Factor Auth for Web Applications

How to Set Up TOTP Two-Factor Auth for Web Applications

By Admin · Mar 15, 2026 · Updated Apr 24, 2026 · 251 views · 2 min read

Time-based One-Time Passwords (TOTP) add a second authentication factor to your web applications. Even if a password is compromised, an attacker cannot log in without the TOTP code from the user's authenticator app.

How TOTP Works

# 1. Server generates a secret key and shares it with the user (QR code)
# 2. Both server and authenticator app know the secret
# 3. Every 30 seconds, a new 6-digit code is generated using:
#    TOTP = HMAC-SHA1(secret, floor(time / 30))
# 4. User enters the code, server verifies it matches

Server-Side Implementation (PHP)

# Using the pragmarx/google2fa library
composer require pragmarx/google2fa
composer require bacon/bacon-qr-code

# Generate a secret for a user
use PragmaRX\Google2FA\Google2FA;
$google2fa = new Google2FA();
$secret = $google2fa->generateSecretKey();
// Store $secret in the database for this user

# Generate QR code URL
$qrUrl = $google2fa->getQRCodeUrl(
    "MyApp",
    $user->email,
    $secret
);

# Verify a TOTP code
$valid = $google2fa->verifyKey($secret, $userInputCode);
if ($valid) {
    // 2FA verification passed
} else {
    // Invalid code
}

Server-Side Implementation (Node.js)

// Using the otpauth library
const OTPAuth = require("otpauth");

// Generate secret
const totp = new OTPAuth.TOTP({
  issuer: "MyApp",
  label: user.email,
  algorithm: "SHA1",
  digits: 6,
  period: 30,
  secret: OTPAuth.Secret.generate()
});

// Get provisioning URI for QR code
const uri = totp.toString();
// Generate QR code from this URI

// Verify a code
const isValid = totp.validate({ token: userCode, window: 1 });
// window: 1 allows codes from previous and next 30-second window

User Experience Best Practices

  • Recovery codes — Generate 8-10 one-time backup codes when 2FA is enabled
  • Remember device — Optionally allow skipping 2FA for 30 days on trusted devices
  • Grace period — Allow the previous and next TOTP code (window=1) to account for clock skew
  • Clear instructions — Show recommended authenticator apps (Authy, Google Authenticator, 1Password)
  • Disable option — Allow users to disable 2FA (require current TOTP code to disable)

Security Considerations

  1. Store secrets encrypted in the database (not plaintext)
  2. Rate-limit verification attempts to prevent brute force (6-digit code = 1M possibilities)
  3. Use HTTPS only — TOTP setup must happen over encrypted connections
  4. Invalidate recovery codes after use
  5. Log 2FA events — Track when 2FA is enabled, disabled, or used

Was this article helpful?