TechnitiumSoftware/DnsServer · warning · InvalidOperationException

Cannot change password for SSO users.

Error message

Cannot change password for SSO users.

What it means

Thrown by User.ChangePassword() when the user was created via an external Single Sign-On (SSO) identity provider. Such users have no local password credential (the _isSsoUser flag is set), so changing a local password is meaningless and would leave the account in an inconsistent state. The guard fires before any hash/salt regeneration so no state is mutated.

Source

Thrown at DnsServerCore/Auth/User.cs:261

            {
                case UserPasswordHashType.OldScheme:
                    using (HMAC hmac = new HMACSHA256(Encoding.UTF8.GetBytes(password)))
                    {
                        return Convert.ToHexString(hmac.ComputeHash(Encoding.UTF8.GetBytes(_username))).ToLowerInvariant();
                    }

                case UserPasswordHashType.PBKDF2_SHA256:
                    return Convert.ToHexString(Rfc2898DeriveBytes.Pbkdf2(Encoding.UTF8.GetBytes(password), _salt, _iterations, HashAlgorithmName.SHA256, 32)).ToLowerInvariant();

                default:
                    throw new NotSupportedException();
            }
        }

        public void ChangePassword(string newPassword, int iterations = DEFAULT_ITERATIONS)
        {
            if (_isSsoUser)
                throw new InvalidOperationException("Cannot change password for SSO users.");

            _passwordHashType = UserPasswordHashType.PBKDF2_SHA256;
            _iterations = iterations;

            _salt = new byte[32];
            RandomNumberGenerator.Fill(_salt);

            _passwordHash = GetPasswordHashFor(newPassword);
        }

        public void LoadOldSchemeCredentials(string passwordHash)
        {
            if (_isSsoUser)
                throw new InvalidOperationException();

            _passwordHashType = UserPasswordHashType.OldScheme;
            _passwordHash = passwordHash;
        }

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Check user.IsSsoUser before calling ChangePassword and skip or redirect the request to the SSO provider's password flow.
  2. If the account must become a local password account, create a new local user instead of trying to convert the SSO user.
  3. Gate the password-change API endpoint so it returns a 4xx 'not applicable for SSO users' response instead of letting the exception propagate.

Example fix

// before
user.ChangePassword(newPassword);

// after
if (!user.IsSsoUser)
    user.ChangePassword(newPassword);
else
    throw new InvalidOperationException("Password changes are managed by the SSO identity provider.");
Defensive patterns

Strategy: validation

Validate before calling

if (user.IsSsoUser)
    return BadRequest("Cannot change password for an SSO user; use the identity provider.");
user.ChangePassword(newPassword);

Type guard

static bool CanChangePassword(User user) => !user.IsSsoUser;

Prevention

When it happens

Trigger: Calling user.ChangePassword(newPassword) on a User instance whose _isSsoUser is true. In Technitium DNS Server this happens when an administrator attempts to reset the password of an SSO-linked account through the web API or the AuthManager wrapper.

Common situations: Mixing local and SSO users in the same directory; an admin UI form that always offers a 'change password' action regardless of account type; migrating from local auth to SSO and forgetting that migrated accounts keep their SSO flag.

Related errors


AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13). Data as JSON: /api/errors/a20b434d4dd9a1a5. Report an issue: GitHub.