Learn Authelia - TOTP (Time-based One-Time Password)
Episode 9 of 31

Learn Authelia - TOTP (Time-based One-Time Password)

Understanding TOTP as Authelia's second method: how the time-based six-digit code works per RFC 6238, issuer and period configuration, the QR code enrollment process, the role of backup, up to generating TOTP keys via the CLI.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Introduction

In episode 8, your storage was ready to hold permanent data — including the TOTP secret that will be the star of this episode. In episode 6, you promised users that sensitive services are protected by two_factor. Time to keep that promise: enabling the most universal second method, TOTP.

TOTP is a second method that doesn't require special hardware, just an app on a phone — Google Authenticator, Authy, FreeOTP, or Aegis. That's why TOTP is the baseline almost every user already knows. In this episode you'll understand how it works from the cryptographic side, configure its behavior, run the enrollment process, and design a recovery strategy for when a user loses their device.

How TOTP Works: A Code That Breathes With Time

TOTP is the RFC 6238 standard, a time-based extension of HOTP (RFC 4226). The principle is elegant: both parties — Authelia and the authenticator app — share the same secret. The code is generated from that secret combined with a time counter: the current epoch value divided by the period length (usually 30 seconds).

Simple TOTP formula
code = HMAC(secret, floor(unix_time / period)) -> 6 digits

Because both sides use the same secret and time, they produce identical codes within the same time window. It's like a combination lock where the numbers change every 30 seconds, and both the guard and you hold the exact same clock and seed.

The important consequence: clocks must be in sync. If your device drifts far from the server time, the generated code won't match. That's why phone and Authelia server clocks must use NTP. This time dependence is what makes TOTP more fragile than methods that don't rely on time synchronization.

TOTP Configuration

TOTP behavior is controlled through the totp section:

TOTP configuration
totp:
  issuer: "example.com"
  algorithm: "sha1"
  digits: 6
  period: 30
  skew: 1
  secret_size: 32
  • issuer: the name shown by the authenticator app to distinguish the Authelia entry from others.
  • algorithm: the hash function used. The sha1 default is chosen for compatibility with almost all apps.
  • digits: the number of code digits. Default 6; only 6 or 8 are supported.
  • period: the time window length in seconds. Default 30.
  • skew: the number of windows before and after the current window that are still considered valid.
  • secret_size: the length of the random secret generated at enrollment.

Tip

Don't rush to change algorithm, digits, or period. Many authenticator apps only support SHA1 with 6 digits and a 30-second period. Authelia's defaults were chosen for compatibility; changing them risks some users not being able to register devices.

skew: Time Tolerance Window

skew is the tolerance window. With the default value of 1, Authelia accepts codes from three time windows: before, current, and after. The effectiveness formula is period + (period x skew x 2) — with a period of 30 and skew of 1, that's a total of 90 seconds of validity. A large skew is certainly convenient, but it extends the lifetime of codes an attacker could intercept.

Enrollment: QR Code and Manual Entry

The TOTP enrollment flow starts from the Authelia portal: the user logs in with a password (first factor), selects the TOTP method, then clicks "register device". Authelia displays a QR code containing an otpauth URL — holding the issuer, username, and secret. The user scans it with an authenticator app:

  1. Open the authenticator app on the phone.
  2. Choose scan QR code, point it at the Authelia screen.
  3. The app stores the secret and starts generating 6-digit codes.
  4. Enter the first code at the portal to verify; enrollment is complete.

For users who can't scan a QR code, Authelia also provides manual entry: the secret is shown as base32 text to type directly into the app. Both paths produce the same result — a secret stored in the app and in Authelia's storage.

The Role of Backup: Why One Device Isn't Enough

A TOTP secret lives on a single phone. If the phone is lost, broken, or reset, the user loses their only way in — unless there's a recovery path. Two common strategies:

  • Enroll more than one device: several authenticator apps, or one on the phone and one on a backup device.
  • Keep a copy of the secret: at enrollment, store the base32 secret in a safe location (for example a vault) as a manual recovery path.

Warning

Authelia doesn't provide one-time backup codes like those commonly found in other services. Don't mislead users by promising a feature that doesn't exist. Instead, encourage them to register two devices or keep a copy of the secret somewhere safe — that's Authelia's version of backup codes.

Enrollment via CLI

It doesn't always have to be through the portal. Authelia provides CLI commands to create TOTP configuration for a specific user, even directly producing a QR code image file:

Generate TOTP for a user
authelia storage user totp generate john
authelia storage user totp generate john --path john-qr.png
authelia storage user totp generate john --digits 8 --period 60
  • generate john: creates a new TOTP configuration for the john user and shows its URI.
  • --path john-qr.png: saves the QR code to a file so it can be sent to the user.
  • --digits 8 --period 60: changes the parameters if you want a non-default configuration.

This command is also useful for restore: if you have a secret backup, the --secret parameter can restore a previous configuration.

TOTP Secret Security

The TOTP secret is the digital equivalent of your house key — whoever holds it can produce valid codes. Several principles keep the secret safe:

  • Encryption at storage: enable encryption_key on MySQL or PostgreSQL storage as covered in episode 8, so secrets are stored encrypted in the database.
  • Don't spread QR codes: a QR code leaked in a screenshot or chat log is the same as leaking the secret. Have users scan directly from the screen.
  • Rotate the secret when suspicious: if there's any sign of compromise, regenerate the user's TOTP configuration and ask them to re-register their device.
  • Sync the clocks: a device with a drifting clock makes TOTP fail repeatedly. Make sure NTP is active on the phone and server.

Authelia also has the disable_reuse_security_policy setting: by default, a code that's already been used can't be reused, closing the small gap where an attacker exploits a leaked but not-yet-expired code.

Closing

Key points of this episode:

  • TOTP is RFC 6238: an HMAC of a shared secret and a time counter, producing a 6-digit code valid for one period.
  • Core configuration: issuer, algorithm, digits, period, and skew.
  • Enrollment happens via QR code or manual entry; the secret lives in the app and in Authelia's storage.
  • Authelia has no built-in backup codes; instead, register multiple devices or keep a copy of the secret.
  • The authelia storage user totp generate CLI enables enrollment and restore without the portal.

TOTP already protects you from leaked passwords, but there's still one fundamental weakness: a 6-digit code can be tricked by a phishing site that clones the login page. In episode 10, you'll level up with WebAuthn/FIDO2 — credentials bound to the real domain, so phishing is nearly useless — from the passkey concept to YubiKey enrollment.