{"record":{"id":"f980c36de1e568f7","repo":"TechnitiumSoftware/DnsServer","slug":"time-based-one-time-password-totp-is-already-ena","errorCode":null,"errorMessage":"Time-based one-time password (TOTP) is already enabled for user: ","messagePattern":"Time-based one-time password \\(TOTP\\) is already enabled for user: ","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"warning","filePath":"DnsServerCore/Auth/User.cs","lineNumber":287,"sourceCode":"            _passwordHash = GetPasswordHashFor(newPassword);\n        }\n\n        public void LoadOldSchemeCredentials(string passwordHash)\n        {\n            if (_isSsoUser)\n                throw new InvalidOperationException();\n\n            _passwordHashType = UserPasswordHashType.OldScheme;\n            _passwordHash = passwordHash;\n        }\n\n        public AuthenticatorKeyUri InitializedTOTP(string issuer)\n        {\n            if (_isSsoUser)\n                throw new InvalidOperationException(\"Time-based one-time password (TOTP) feature is not available for SSO users.\");\n\n            if (_totpEnabled)\n                throw new InvalidOperationException(\"Time-based one-time password (TOTP) is already enabled for user: \" + _username);\n\n            _totpKeyUri = AuthenticatorKeyUri.Generate(issuer, _username);\n\n            return _totpKeyUri;\n        }\n\n        public void EnableTOTP(string totp)\n        {\n            if (_isSsoUser)\n                throw new InvalidOperationException(\"Time-based one-time password (TOTP) feature is not available for SSO users.\");\n\n            if (_totpKeyUri is null)\n                throw new InvalidOperationException(\"Time-based one-time password (TOTP) was not initialized for user: \" + _username);\n\n            if (_totpEnabled)\n                throw new InvalidOperationException(\"Time-based one-time password (TOTP) is already enabled for user: \" + _username);\n\n            Authenticator authenticator = new Authenticator(_totpKeyUri);","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Auth/User.cs#L269-L305","documentation":"Thrown by User.InitializedTOTP(issuer) when _totpEnabled is already true, meaning TOTP was previously initialized and confirmed via EnableTOTP. Re-initializing would generate a new AuthenticatorKeyUri and orphan the old secret, breaking already-configured authenticator apps, so the library refuses the call. The state check comes after the SSO guard but before any key generation.","triggerScenarios":"Calling InitializedTOTP a second time on the same user after EnableTOTP has already completed (i.e. _totpEnabled flipped to true). Common from a UI that lets the user click 'set up TOTP' again, or from a retry loop that does not check current state.","commonSituations":"User clicks 'reconfigure TOTP' instead of using the dedicated disable-then-re-enable path; a provisioning script runs twice; the authenticator app was lost but the correct recovery flow (DisableTOTP first) was not followed.","solutions":["Call DisableTOTP() before calling InitializedTOTP() to rotate the TOTP secret on an already-enabled account.","Check the user's TOTP state via the session/API before offering the 'initialize' action.","Build the UI so re-configuration goes through a single 'reset TOTP' flow that disables then re-initializes."],"exampleFix":"// before\nvar keyUri = user.InitializedTOTP(issuer);\n\n// after\nif (user.TotpEnabled)\n    user.DisableTOTP();\nvar keyUri = user.InitializedTOTP(issuer);","handlingStrategy":"validation","validationCode":"if (user.TotpEnabled)\n    return Conflict(\"TOTP is already enabled; disable it first to reconfigure.\");\nvar keyUri = user.InitializedTOTP(issuer);","typeGuard":"static bool CanInitializeTotp(User user) => !user.IsSsoUser && !user.TotpEnabled;","tryCatchPattern":null,"preventionTips":["Track TOTP state server-side and gate the initialize action.","Route re-configuration through DisableTOTP first.","Reflect current TOTP state in the UI before offering setup."],"tags":["auth","totp","mfa","state","technitium-dns-server"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}