public ApiErrorItem? PerformPasswordChange()

in src/Unosquare.PassCore.PasswordProvider/PasswordChangeProvider.cs [38:126]


        public ApiErrorItem? PerformPasswordChange(string username, string currentPassword, string newPassword)
        {
            try
            {
                var fixedUsername = FixUsernameWithDomain(username);
                using var principalContext = AcquirePrincipalContext();
                var userPrincipal = UserPrincipal.FindByIdentity(principalContext, _idType, fixedUsername);

                // Check if the user principal exists
                if (userPrincipal == null)
                {
                    _logger.LogWarning($"The User principal ({fixedUsername}) doesn't exist");

                    return new ApiErrorItem(ApiErrorCode.UserNotFound);
                }

                var minPwdLength = AcquireDomainPasswordLength();

                if (newPassword.Length < minPwdLength)
                {
                    _logger.LogError("Failed due to password complex policies: New password length is shorter than AD minimum password length");

                    return new ApiErrorItem(ApiErrorCode.ComplexPassword);
                }

                // Check if the newPassword is Pwned
                if (PwnedPasswordsSearch.PwnedSearch.IsPwnedPassword(newPassword))
                {
                    _logger.LogError("Failed due to pwned password: New password is publicly known and can be used in dictionary attacks");

                    return new ApiErrorItem(ApiErrorCode.PwnedPassword);
                }

                _logger.LogInformation($"PerformPasswordChange for user {fixedUsername}");

                var item = ValidateGroups(userPrincipal);

                if (item != null)
                    return item;

                // Check if password change is allowed
                if (userPrincipal.UserCannotChangePassword)
                {
                    _logger.LogWarning("The User principal cannot change the password");

                    return new ApiErrorItem(ApiErrorCode.ChangeNotPermitted);
                }

                // Check if password expired or must be changed
                if (_options.UpdateLastPassword && userPrincipal.LastPasswordSet == null)
                {
                    SetLastPassword(userPrincipal);
                }

                // Use always UPN for password check.
                if (!ValidateUserCredentials(userPrincipal.UserPrincipalName, currentPassword, principalContext))
                {
                    _logger.LogWarning("The User principal password is not valid");

                    return new ApiErrorItem(ApiErrorCode.InvalidCredentials);
                }

                // Change the password via 2 different methods. Try SetPassword if ChangePassword fails.
                ChangePassword(currentPassword, newPassword, userPrincipal);

                userPrincipal.Save();
                _logger.LogDebug("The User principal password updated with setPassword");
            }
            catch (PasswordException passwordEx)
            {
                var item = new ApiErrorItem(ApiErrorCode.ComplexPassword, passwordEx.Message);

                _logger.LogWarning(item.Message, passwordEx);

                return item;
            }
            catch (Exception ex)
            {
                var item = ex is ApiErrorException apiError
                    ? apiError.ToApiErrorItem()
                    : new ApiErrorItem(ApiErrorCode.Generic, ex.InnerException?.Message ?? ex.Message);

                _logger.LogWarning(item.Message, ex);

                return item;
            }

            return null;
        }