Why Passwords Alone Are Not Enough
Passwords are the oldest form of digital authentication, and they are fundamentally broken. According to Verizon's Data Breach Investigations Report, over 80% of hacking-related breaches involve stolen or weak passwords. People reuse passwords across services, choose predictable combinations, and fall for phishing attacks that harvest credentials. Even strong, unique passwords can be stolen through database breaches, keyloggers, or man-in-the-middle attacks.
Two-factor authentication (2FA) addresses this by requiring a second proof of identity in addition to the password. Even if an attacker steals your password, they cannot log in without the second factor. It is one of the most effective security measures available, and yet it remains underutilized — most estimates suggest that fewer than 30% of users enable 2FA when it is offered.
This guide covers implementing 2FA across your infrastructure: SSH servers, web applications, and control panels. We will look at TOTP (time-based one-time passwords), hardware security keys, backup codes, and recovery strategies.
Types of Two-Factor Authentication
Not all 2FA methods are created equal. They fall into three categories based on the authentication factor they use:
| Method | Factor Type | Security Level | Convenience |
|---|---|---|---|
| TOTP (Google Authenticator, Authy) | Something you have (phone) | High | Good |
| FIDO2/WebAuthn (YubiKey, passkeys) | Something you have (hardware key) | Highest | Good |
| SMS codes | Something you have (phone number) | Moderate | Good |
| Email codes | Something you have (email access) | Moderate | Fair |
| Push notifications | Something you have (phone) | High | Excellent |
How TOTP Works
TOTP (Time-based One-Time Password) is the most widely used 2FA method. Understanding how it works helps you implement it correctly and troubleshoot issues.
The process works like this: the server generates a random secret key and shares it with the user (usually via a QR code). Both the server and the authenticator app know the secret. Every 30 seconds, both sides independently compute a 6-digit code by running HMAC-SHA1 on the secret key combined with the current Unix timestamp divided by 30. Because they share the same secret and the same clock, they produce the same code. The server accepts codes within a small time window (typically plus or minus one 30-second interval) to account for clock drift.
Setting Up 2FA for SSH with Google Authenticator
Securing SSH with TOTP is one of the highest-impact security improvements you can make. Here is the complete setup process:
Scan the QR code (displayed in the terminal) with your authenticator app. Save the emergency scratch codes in a secure location — they are your lifeline if you lose your phone.
/etc/pam.d/sshd and add the Google Authenticator module:
The nullok flag allows users who have not set up 2FA to still log in with just their password. Remove nullok once all users have configured their authenticator apps to enforce 2FA for everyone.
/etc/ssh/sshd_config:
SSH Key + TOTP (Most Secure)
For maximum security, require both an SSH key and a TOTP code:
This requires users to first authenticate with their SSH key, then enter their TOTP code. Even if an attacker steals the private key, they still need the TOTP code to log in.
Implementing TOTP in Web Applications
Adding TOTP to your web application involves four steps: generating a secret, displaying a QR code, verifying codes, and managing backup codes.
Step 1: Generate a Secret Key
Step 2: Display Setup Page
Show the user a QR code and the secret key (for manual entry) along with a verification input. The user scans the QR code with their authenticator app and enters the current code to verify the setup is working before you enable 2FA on their account.
Step 3: Verify TOTP Codes
Step 4: Generate Backup Codes
PHP Implementation
Hardware Security Keys (FIDO2/WebAuthn)
Hardware security keys like YubiKey provide the strongest form of 2FA. They are phishing-resistant because the key is cryptographically bound to the specific website domain — a phishing site on a different domain cannot trigger the key.
Advantages
- Phishing-resistant (domain-bound)
- No codes to type (touch-to-authenticate)
- Cannot be remotely intercepted
- No batteries or connectivity needed
- Works offline
Considerations
- Hardware cost (~$25-$50 per key)
- Users need physical key present
- Should have a backup key or alternative method
- Limited browser/platform support for some features
- Risk of losing the key
WebAuthn Implementation
WebAuthn is the browser API for FIDO2 hardware keys and platform authenticators (fingerprint, Face ID). Here is a simplified registration flow:
Recovery Strategies: What If You Lose Your 2FA Device?
The biggest practical challenge with 2FA is account recovery. If a user loses their phone, their authenticator app, or their hardware key, they need a way back in. Here are the recommended recovery strategies:
| Strategy | Security | Usability | Notes |
|---|---|---|---|
| Backup codes | High | Good | 10 single-use codes, stored securely by user |
| Second hardware key | Highest | Fair | Register two keys, keep one in a safe place |
| Recovery email | Moderate | Good | Send a recovery link to a secondary email |
| Admin reset | Moderate | Fair | Contact support with identity verification |
| No recovery | Highest | Poor | Account is permanently locked (some crypto wallets) |
2FA for Database Access
Database servers can also benefit from 2FA. While direct database 2FA is not common, you can implement it through the connection path:
Approach: SSH Tunnel with 2FA
Instead of exposing database ports to the network, require all database connections to go through an SSH tunnel. Since SSH already has 2FA configured (as we set up earlier), database access automatically requires two factors.
Common 2FA Mistakes to Avoid
SMS as the only 2FA method
SMS is vulnerable to SIM swapping and interception. Always offer TOTP or hardware keys as primary options and use SMS only as a fallback.
No backup codes provided
If users lose their device and have no backup codes, they are permanently locked out. Always generate and display backup codes during 2FA setup.
Storing TOTP secrets in plain text
TOTP secrets must be encrypted at rest in your database. If an attacker gains database access and secrets are in plain text, they can generate valid codes for every user.
No rate limiting on code entry
TOTP codes are only 6 digits (1 million combinations). Without rate limiting, an attacker could brute-force the current code within the 30-second window. Limit attempts to 3-5 per minute.
2FA Implementation Checklist
- TOTP secret generated with sufficient entropy (minimum 160 bits)
- QR code and manual entry key displayed during setup
- User verifies a code before 2FA is activated
- Backup codes generated and shown (10 codes minimum)
- Backup codes stored as hashed values in database
- TOTP secrets encrypted at rest in database
- Rate limiting on code verification (max 5 attempts per minute)
- Time window tolerance set (1 step = 30 seconds before/after)
- Recovery flow documented and tested
- SSH 2FA tested before closing current session
- Users educated about saving backup codes securely
- Admin override available for locked-out users (with identity verification)
Wrapping Up
Two-factor authentication is the single most impactful security improvement you can make to any system. A stolen password alone becomes useless, phishing attacks are largely neutralized (especially with hardware keys), and brute force attacks become practically impossible.
The implementation priority should be: SSH access first (it is the keys to the kingdom), then admin/panel accounts, then user accounts on web applications. Use TOTP as the standard method — it is free, widely supported, and does not depend on phone service. Offer hardware keys as an option for high-security accounts. Always provide backup codes, always encrypt secrets at rest, and always rate-limit verification attempts.
The hardest part of 2FA is not the technology — it is getting users to actually enable it. Make the setup process as smooth as possible, explain the risks of password-only authentication, and consider making 2FA mandatory for all administrative accounts. The small inconvenience of entering a 6-digit code is trivial compared to the devastating consequences of a compromised account.