Skip to content

fix(auth): allow recovery codes at 2FA login#19

Merged
SiteRelEnby merged 1 commit into
mainfrom
fix/totp-recovery-login
Jul 7, 2026
Merged

fix(auth): allow recovery codes at 2FA login#19
SiteRelEnby merged 1 commit into
mainfrom
fix/totp-recovery-login

Conversation

@SiteRelEnby

Copy link
Copy Markdown
Collaborator

Problem

The 2FA login field filtered input to 6 digits (code.filter { it.isDigit() }.take(6)) with a numeric keyboard, so recovery codes (16 hex chars, issued as two hyphenated groups xxxxxxxx-xxxxxxxx) were untypeable. That locks out exactly the users recovery codes exist for: a lost or wiped authenticator, which correlates strongly with a changed phone, i.e. mobile-first users. There was no alternate path in the UI.

Fix

Add a "Use a recovery code instead" toggle to the login TOTP step:

  • Default stays numeric-keypad TOTP (the common case, easier to type on mobile).
  • Toggling switches to a hex-friendly field that accepts the code bare or hyphenated, then normalises it (lowercase, hyphen re-inserted) to the stored format on submit.
  • Mode-aware label / placeholder / helper text; refocuses the field on toggle and clears it so a half-typed code doesn't carry over.

Client-only change: the login endpoint already tries the authenticator code then falls back to a recovery code on the same totp_code parameter, so the server accepted recovery codes all along.

One subtlety: recovery codes are stored hashed in their hyphenated form, so the hyphen must be present at submit. Web sends the raw field (the user types the hyphen); on mobile we re-insert it client-side so people can type it bare. That is a deliberate, strictly-more-permissive divergence from web.

Also

Refreshed a stale README line that claimed store builds were "not yet available", contradicting the status line right above it (stable v* tags are on GitHub Releases; Play Store is in beta; F-Droid pending).

Scope note

Other TOTP prompts (member/tag/file/journal delete, orphan-file cleanup, revision pinning, System Safety, data export) are intentionally left digit-only. That matches web, which only offers recovery codes at login (and change-email); those are step-up auth while already signed in, not a lockout.

Testing

  • :app:testPlayReleaseUnitTest green
  • :app:assemblePlayRelease green (through R8)
  • Not device-tested here; worth a manual pass that a recovery code signs in and the toggle swaps the keyboard.

The TOTP login field filtered input to 6 digits and used a numeric
keyboard, so recovery codes (16 hex chars, two hyphenated groups) were
untypeable. That locks out exactly the users recovery codes are for:
lost or replaced authenticator, which correlates with a changed phone.

Add a "Use a recovery code instead" toggle that swaps the field to a
hex-friendly keyboard and accepts the code bare or hyphenated, then
normalises it (lowercase, hyphen re-inserted) to the stored format on
submit. The default stays numeric-keypad TOTP, which is the common case
and easier to type. The login endpoint already accepts a recovery code
on the same parameter, so this is a client-only change.

Also refresh a stale README line that claimed store builds were not yet
available, which contradicted the status line right above it.
@SiteRelEnby SiteRelEnby enabled auto-merge July 7, 2026 00:20
@SiteRelEnby SiteRelEnby merged commit 904e19f into main Jul 7, 2026
1 check passed
@SiteRelEnby SiteRelEnby deleted the fix/totp-recovery-login branch July 7, 2026 00:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant