rustdesk / rustdesk/rustdesk-server-pro
[BUG] 2FA TOTP setup fails with "Can't verify the code" - verify endpoint returns {"success":false} despite correct code
Nobody has claimed this yet.
- Dominant language
- Shell
- Stars
- 317
- Forks
- 119
- PR merge metrics
- No merged PRs in 30d
Description
Bug Description
Environment
- RustDesk Server Pro version: 3.46.0 (image tag
latest, digestd9af4e3774a4) - Deployment: Docker Compose (non-host networking, behind Traefik reverse proxy)
- Database: SQLite (migrations all completed successfully, verified via
_sqlx_migrations) - Host OS: (debian 13)
- Browser: Firefox (tested), Brave (tested)
Bug Description
After updating from an earlier version to 1.8.2 / 3.46.0, no user on this instance can successfully enable 2FA (TOTP) anymore.
- Pre-update 2FA setups (users created and verified before the update) are unaffected in the database.
- ALL new 2FA setup attempts fail with the UI error: "Can't verify the code. Check that code and local time settings are correct!"
- Tested with newly created users (same problem), so the issue is not tied to a specific user record.
Critically: I run an identical second instance (same image digest, same compose structure, same schema, same migrations) where 2FA setup works perfectly — also for newly created users.
How to Reproduce
- Log in as admin (no 2FA active)
- Go to Account Settings → Enable 2FA
- Scan QR code with an authenticator app (tested with Aegis, Google Authenticator, IT-Tools TOTP generator — all produce identical codes)
- Enter the generated 6-digit code
- Server rejects:
POST /api/user/tfa/totp/verify→{"success":false}
Expected Behavior
- 2FA is accepted
Operating system(s) on local (controlling) side and remote (controlled) side
debian 13
RustDesk Version(s) on local (controlling) side and remote (controlled) side
1.8.1 -> 1.8.2
Screenshots
Additional Context
What I've Verified
- Host time perfectly in sync via chronyd (
timedatectlclean) - Container time matches host time exactly (
date --utcidentical in both) - TOTP secret shown in QR is identical to the
otpauth://URI returned by/enable - Multiple TOTP apps generate identical codes → code is mathematically correct
_sqlx_migrationsshows all 21 migrations completed successfully, identical to working instance- Schema of
usertable identical to working instance (includingtfa blob nullcolumn) - Image digest identical to working instance (
d9af4e3774a4) - Accessing the web console directly on port 21114 (bypassing Traefik reverse proxy entirely) produces the same failure → not a proxy/header issue
- Tested in fresh incognito session, multiple browsers, cleared all cookies
- Ran
reset_2fa_verificationvia rustdesk-utils between attempts
Debug Log Observations (RUST_LOG=debug)
With debug logging enabled, during the setup flow I see:
POST /api/user/tfa/totp/enable → 200, latency=0ms, response 268 bytes
POST /api/user/tfa/totp/verify → 200, latency=0ms, response 125 bytes, body {"success":false}
Notable: Between enable and verify, there are no SQL queries logged at all. No UPDATE user SET tfa=..., no read from a pending-setup table. The setup state appears to be held in-memory only. The user_data table is empty. The user.tfa field remains NULL after failed verify attempts.
Database State
SELECT name, tfa FROM user WHERE name='admin';
→ admin | (empty/NULL)
Pre-update user from the same database:
SELECT name, hex(tfa) FROM user WHERE name='olli';
→ valid tfa blob with verified:1 JSON payload (setup done before 1.8.2 update)
What I think:
The in-memory pending-TOTP-setup state appears to not be retained or not be retrievable between the /enable and /verify request on this instance. Possibly related to session handling, JWT secret, or a state-loss during a specific upgrade path. The working instance was upgraded from an older version with a backup_db.sqlite3 artifact present — the failing instance has no such backup file, suggesting a slightly different upgrade history.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing the /api/user/tfa/totp/enable and /api/user/tfa/totp/verify entry points, using the debug logs and the failing and working instances for comparison. Determine why pending setup state is unavailable between requests, then verify that a correct TOTP code succeeds and persists the expected user.tfa value without regressing existing 2FA.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker-compose, sqlite
- Domain
- api, authentication, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 42/100