Problem/Motivation

Period: last_verified_step is stored in units of the code period that was active when the code was checked. TotpService::verifyAndGetStep() calculates the step with the current period, and UserTotpManager::matchesTotpCode() rejects any step <= last_verified_step. If the period is raised (for example from 30 to 60 seconds), the current step number roughly halves, so every TOTP code is rejected, practically forever.

Length: changing otp_digits breaks every existing enrollment, because authenticator apps keep generating codes of the old length.

The settings form allows both changes without any warning.

Steps to reproduce

  1. Enroll a user with the default settings and log in once with a code.
  2. Change "Code validity period" to 60.
  3. Log out, then log in with a correct code: "Invalid verification code".

Proposed resolution

  • Store the period and the number of digits per user at enrollment, and use those values for that user's verification. Alternatively, store the last verified timestamp instead of the step number.
  • Warn in the settings form, or block the change, while enrollments exist.

Remaining tasks

  • Merge request
  • Test coverage

Code references

Generated with the help of an LLM.

Comments

jurgenhaas created an issue.