NginxProxyManager / NginxProxyManager/nginx-proxy-manager
TOTP verification consistently rejects correctly-computed codes after initial 2FA setup (v2.15.1)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 34.2k
- Forks
- 3.9k
- Avg merge
- 21h 12m
- Merged PRs (30d)
- 20
Description
NPM version: 2.15.1 (self-hosted via Docker, image jc21/nginx-proxy-manager:latest)
Summary: After enabling 2FA, TOTP codes computed with the exact secret stored in the database (standard SHA1, 6 digits, 30s step) are rejected — both for "Regenerate Backup Codes" and for normal login — even though the same method produced a code that was accepted during the initial setup/verify step.
Steps taken to rule out common causes:
Host and container clocks verified in sync (checked twice, <1s difference).
Confirmed via direct SQLite inspection that the secret is unchanged between auth.meta.totp_pending_secret (during setup) and auth.meta.totp_secret (after activation) — only the JSON key name changes, value identical.
A code computed independently with standard TOTP parameters (HMAC-SHA1, 6 digits, 30s period, current Unix time // 30) against this exact secret was accepted once, completing 2FA setup successfully.
Multiple subsequent freshly-computed correct codes (verified against the same unchanged secret, at the moment of submission) were rejected with "Invalid verification code" — both on the "Regenerate Backup Codes" dialog and on a fresh login attempt after logging out.
This resulted in a full account lockout; recovery required manually clearing auth.meta in the SQLite database via docker cp (container has no sqlite3 binary).
This looks related to #5142 but with more detailed reproduction steps. Happy to provide more details/logs if useful.
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 with the 2FA setup verification, normal login, and Regenerate Backup Codes flows described in the issue, then inspect how auth.meta.totp_pending_secret becomes auth.meta.totp_secret in SQLite. Reproduce the setup and subsequent verification attempts with the stated SHA1, six-digit, 30-second parameters; done means correctly computed codes are accepted after activation without requiring manual auth.meta recovery.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker, sqlite, typescript
- Domain
- authentication, backend, database
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 45/100