{"record":{"id":"08dc1c4dc2a40eb7","repo":"TechnitiumSoftware/DnsServer","slug":"time-based-one-time-password-totp-feature-is-not","errorCode":null,"errorMessage":"Time-based one-time password (TOTP) feature is not available for SSO users.","messagePattern":"Time-based one-time password \\(TOTP\\) feature is not available for SSO users\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"warning","filePath":"DnsServerCore/Auth/User.cs","lineNumber":284,"sourceCode":"            _salt = new byte[32];\n            RandomNumberGenerator.Fill(_salt);\n\n            _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)","sourceCodeStart":266,"sourceCodeEnd":302,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Auth/User.cs#L266-L302","documentation":"Thrown by User.InitializedTOTP(issuer) when the target user is an SSO user. Two-factor TOTP is a local-credential feature that supplements a local password; because SSO users authenticate externally, the local TOTP secret would never be consulted and enabling it would mislead administrators. The check runs before AuthenticatorKeyUri.Generate so no key material is created.","triggerScenarios":"Calling user.InitializedTOTP(issuer) on any User with _isSsoUser == true, typically through the 'enable two-factor authentication' web API action for an SSO-linked account.","commonSituations":"Enforcing a blanket 'all users must have TOTP' policy that ignores account type; an admin dashboard that shows the TOTP setup button uniformly; importing SSO users and running a provisioning script that calls InitializedTOTP for everyone.","solutions":["Skip TOTP provisioning for SSO users by checking user.IsSsoUser first.","Configure MFA at the SSO identity provider level instead of relying on Technitium's local TOTP for SSO accounts.","Hide or disable the TOTP setup control in the UI when user.IsSsoUser is true."],"exampleFix":"// before\nvar keyUri = user.InitializedTOTP(issuer);\n\n// after\nif (user.IsSsoUser)\n    throw new InvalidOperationException(\"TOTP must be configured at the SSO provider for SSO users.\");\nvar keyUri = user.InitializedTOTP(issuer);","handlingStrategy":"validation","validationCode":"if (user.IsSsoUser)\n    return BadRequest(\"TOTP is not available for SSO users.\");\nvar keyUri = user.InitializedTOTP(issuer);","typeGuard":"static bool SupportsLocalTotp(User user) => !user.IsSsoUser;","tryCatchPattern":null,"preventionTips":["Hide the TOTP setup flow for SSO users.","Enforce MFA at the SSO identity provider for federated accounts.","Add an IsSsoUser branch in every TOTP-related endpoint."],"tags":["auth","sso","totp","mfa","technitium-dns-server"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}