What Is 2FA and How Does TOTP Work? A Plain-English Guide
Learn what two-factor authentication really does, how time-based one-time passwords (TOTP) work, why codes change every 30 seconds, and how to inspect your own codes without an authenticator app.
Two-factor authentication (2FA) adds a second piece of evidence to your login: something you know (your password) plus something you have (a code from your phone). TOTP — time-based one-time password — generates those codes every 30 seconds from a shared secret and the current time. The same algorithm runs on the server, so if both sides agree on the secret and the time, the codes match.
Two-factor authentication is the single most effective thing you can do to protect an account. It blocks the vast majority of automated credential-stuffing attacks, even when your password is in a leaked database. The problem: most explanations of how it works are either too vague ("it uses your phone to verify it's you") or too dense (a 30-page academic paper on HOTP and TOTP). This is the middle ground — what is actually happening when you type that 6-digit code, and why it is secure.
What problem 2FA solves
A password is a single factor: something you know. If someone else learns it, they can log in as you, and there is no way for the server to tell the difference. This happens constantly — passwords leak from data breaches, get phished, get guessed, get reused across sites where one of them has already been compromised.
Two-factor authentication requires a second, independent factor: usually something you have (a phone, a hardware token) or something you are (a fingerprint, face scan). Even if your password leaks, the attacker would also need the second factor to log in. That is a much higher bar.
There are several flavors of 2FA, in roughly increasing order of security:
- SMS codes — the server texts you a 6-digit code. Better than nothing, but vulnerable to SIM-swapping attacks and SMS interception. Avoid for high-value accounts.
- Email codes — same idea, but over email. Convenient, but if your email is compromised, the attacker gets the codes too.
- Authenticator app codes (TOTP) — a 6-digit code generated by an app on your phone, changing every 30 seconds. This is the sweet spot for most people: secure, free, and works offline.
- Push notifications — the app asks "are you logging in?" and you tap yes/no. Convenient, but depends on phone connectivity and adds a phishing vector (an attacker can spam you with login requests hoping you tap "yes" by mistake).
- Hardware security keys (FIDO2 / WebAuthn) — a physical USB or NFC device that proves possession cryptographically. The strongest option, but requires buying a key and isn't free.
For most people, TOTP is the right default. Secure, free, works on any phone, and you only need one app to handle codes for hundreds of sites.
What TOTP actually is
TOTP stands for Time-based One-Time Password, defined in RFC 6238. The algorithm is delightfully simple:
- You and the server agree on a shared secret — a random string of 16–32 characters, usually encoded in Base32. This happens once, when you first set up 2FA. The server shows it as a QR code; your app scans it.
- To generate a code, both sides run the same formula: take the current Unix time, divide by 30 (the period), and use that as a counter.
- Feed the counter and the shared secret into HMAC-SHA1 (a standard hash function with a key).
- Truncate the hash to 6 digits, in a way that varies based on the hash's own last byte. The result is the code.
- Do this every 30 seconds.
That is it. The server runs the same algorithm, gets the same code, and grants access. Because both sides use the same secret and the same time, they always agree — as long as their clocks are within about 30 seconds of each other.
Why the codes change every 30 seconds
If a code was valid forever, capturing one would be as bad as capturing the password. The 30-second window means a stolen code is useless within half a minute. The trade-off is usability: 30 seconds is enough time to read the code, type it in, and submit it, but short enough that an attacker who intercepts the code has almost no time to use it.
Some apps use 60-second windows (more forgiving for slow typists) or 6/7/8-digit codes (more combinations, harder to guess). The math scales accordingly: more digits = more possible codes = harder to brute force, but more annoying to type. 6 digits, 30 seconds, is the sweet spot for most people.
Why a code sometimes doesn't work
When a TOTP code is rejected, the cause is almost always one of these:
- Clock drift. Your phone thinks it is 12:00:15; the server thinks it is 12:00:45. The code you generated for the 12:00:00 window is the one the server expected for 12:00:30, and you have already moved on. The server typically accepts the previous, current, and next window to allow some drift, but if the gap is larger, the code is rejected. The fix: enable automatic time on your phone (set it to "use network-provided time", not manual).
- Wrong secret. You scanned the QR code twice (with two different apps) and one of them wrote a slightly different secret, or the QR code encoded extra parameters your app didn't capture (issuer, account name, digits, period). Re-scan and confirm the issuer matches.
- Reusing a code. Some servers mark a code as used and reject it the second time. If you typed the code, got a network error, and retried, you may need to wait for the next code.
If the codes never line up, you can confirm the secret is correct by running a TOTP generator locally with the same Base32 secret and comparing the codes to what your authenticator app shows. If the codes match, the secret is fine and the problem is on the server side.
How the secret gets shared (and why it matters)
The shared secret is the only thing the server and your app need to agree on. It is set once, when you first turn on 2FA, and the server usually shows it to you in three ways:
- A QR code that you scan with your authenticator app. The QR code contains a URI like
otpauth://totp/GitHub:alice?secret=JBSWY3DPEHPK3PXP&issuer=GitHub. - The raw Base32 string, so you can type it in if you can't scan.
- A set of one-time recovery codes — single-use backup codes that work if you lose your phone.
Treat the secret like a password. Anyone who has it can generate valid codes until you revoke that secret on the server. Save the recovery codes somewhere offline (printed in a drawer, in a password manager's secure notes) — they are the only way back into your account if your phone dies.
What TOTP doesn't protect against
TOTP secures the login, but it is not a complete authentication system. It does not, on its own, protect against:
- Phishing. A sophisticated phishing site can proxy your TOTP code to the real site in real time and log in as you. The window is small (30 seconds), but not zero. FIDO2 keys are the only common 2FA method that is genuinely phishing-resistant, because the key verifies the domain.
- Session hijacking. Once you are logged in, the server gives your browser a session cookie. TOTP doesn't touch that — if an attacker steals the cookie, they don't need a new code.
- Malware on your device. If your authenticator app itself is compromised, the attacker can read the shared secret from the app and generate codes forever.
Combine TOTP with a strong, unique password (use a password generator and check it with a password strength checker), a reputable password manager, and basic device hygiene, and you have closed off the realistic attack paths for almost any consumer account.
2FA is one of those rare security features where the cost is small and the upside is large. Turn it on for every account that offers it, and especially for the ones that can ruin your week if compromised: email, banking, cloud storage, and password manager.