We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.

This lesson's interactive features are locked, please to keep using them

TOTP

TOTP (Time-Based One-Time Password) generates short-lived codes from a shared secret and the current time. The codes are usually six digits and rotate on a 30-second time step.

Its appeal is low friction: it works offline in an authenticator app and doesn't require a separate hardware security key.

How TOTP Works

TOTP is built on a unique shared secret known to both the server and the user's authenticator. Both sides independently compute the expected code for the current time step. Here's some pseudocode. Assume that sharedSecret is stored on the server and in the user's authenticator app, and userSuppliedCode is the code the user entered during login:

timeStep = floor((unixTime - T0) / 30);
serverComputedCode = HOTP(sharedSecret, timeStep);

if (serverComputedCode === userSuppliedCode) {
  // TOTP code accepted
} else {
  // TOTP code rejected
}

The shared secret is not sent during login, but the generated code is. If both clocks and algorithm settings agree, the server computes the same value and checks whether they match.

Because codes are so short, servers need to be careful to rate-limit guesses so an attacker can't brute-force them.

Enrollment

You're probably familiar with this process, but the way users get the shared secret on their device during setup is typically:

  1. The server generates a secure random secret and stores it for the user.
  2. The server encodes the secret in a QR code and displays it on the enrollment page.
  3. The user scans the QR code with an authenticator app (or enters the secret manually) to save the secret on their device.

Backup Codes

Devices get lost, so recovery codes are often provided as a fallback. They're one-time secrets that can be used in place of a TOTP code. The user is expected to download and store them in a safe place, like a password manager.

TOTP codes can be phished. A six-digit code can be typed into a fake login page and relayed to the real site. TOTP is stronger than a password alone, but it isn't phishing-resistant like a FIDO2/WebAuthn authenticator.

Assignment

Bearly Secure's TOTP flow is working, but it accepts the same authenticator code more than once during its 30-second time step.

Prevent TOTP-code replay. In src/auth/totp.ts, fix the verifyAndConsumeTotpCode function:

With Bearly Secure still running, run and submit the CLI tests from the project root.