/// <summary>
        /// Change user password
        /// </summary>
        public bool ChangePassword(string userName, string currentPassword, string newPassword, out string errorReason)
        {
            var identity = LdapIdentity.ParseUser(userName);

            errorReason = null;

            try
            {
                LdapProfile userProfile;

                using (var connection = new LdapConnection(_configuration.Domain))
                {
                    connection.Credential = new NetworkCredential(identity.Name, currentPassword);
                    connection.Bind();

                    var domain = LdapIdentity.FqdnToDn(_configuration.Domain);

                    var isProfileLoaded = LoadProfile(connection, domain, identity, out var profile);
                    if (!isProfileLoaded)
                    {
                        errorReason = Resources.AD.UnableToChangePassword;
                        return(false);
                    }
                    userProfile = profile;
                }

                _logger.Debug($"Changing password for user '{identity.Name}' in {userProfile.BaseDn.DnToFqdn()}");

                using (var ctx = new PrincipalContext(ContextType.Domain, userProfile.BaseDn.DnToFqdn(), null, ContextOptions.Negotiate, identity.Name, currentPassword))
                {
                    using (var user = UserPrincipal.FindByIdentity(ctx, IdentityType.DistinguishedName, userProfile.DistinguishedName))
                    {
                        user.ChangePassword(currentPassword, newPassword);
                        user.Save();
                    }
                }

                _logger.Debug($"Password changed for user '{identity.Name}'");
                return(true);
            }
            catch (PasswordException pex)
            {
                _logger.Warning($"Changing password for user '{identity.Name}' failed: {pex.Message}, {pex.HResult}");
                errorReason = Resources.AD.PasswordDoesNotMeetRequirements;
            }
            catch (Exception ex)
            {
                _logger.Warning($"Changing password for user {identity.Name} failed: {ex.Message}");
                errorReason = Resources.AD.UnableToChangePassword;
            }

            return(false);
        }
        /// <summary>
        /// Verify User Name, Password, User Status and Policy against Active Directory
        /// </summary>
        public ActiveDirectoryCredentialValidationResult VerifyCredential(string userName, string password)
        {
            if (string.IsNullOrEmpty(userName))
            {
                throw new ArgumentNullException(nameof(userName));
            }
            if (string.IsNullOrEmpty(password))
            {
                _logger.Error($"Empty password provided for user '{userName}'");
                return(ActiveDirectoryCredentialValidationResult.UnknowError("Invalid credentials"));
            }

            var user = LdapIdentity.ParseUser(userName);

            try
            {
                _logger.Debug($"Verifying user '{user.Name}' credential and status at {_configuration.Domain}");

                using (var connection = new LdapConnection(_configuration.Domain))
                {
                    connection.Credential = new NetworkCredential(user.Name, password);
                    connection.Bind();

                    _logger.Information($"User '{user.Name}' credential and status verified successfully at {_configuration.Domain}");

                    var domain = LdapIdentity.FqdnToDn(_configuration.Domain);

                    var isProfileLoaded = LoadProfile(connection, domain, user, out var profile);
                    if (!isProfileLoaded)
                    {
                        return(ActiveDirectoryCredentialValidationResult.UnknowError("Unable to load profile"));
                    }

                    var checkGroupMembership = !string.IsNullOrEmpty(_configuration.ActiveDirectory2FaGroup);
                    if (checkGroupMembership)
                    {
                        var isMemberOf = IsMemberOf(connection, profile.BaseDn, user, _configuration.ActiveDirectory2FaGroup);

                        if (!isMemberOf)
                        {
                            _logger.Information($"User '{user.Name}' is NOT member of {_configuration.ActiveDirectory2FaGroup} group");
                            _logger.Information($"Bypass second factor for user '{user.Name}'");
                            return(ActiveDirectoryCredentialValidationResult.ByPass());
                        }
                        _logger.Information($"User '{user.Name}' is member of {_configuration.ActiveDirectory2FaGroup} group");
                    }

                    var result = ActiveDirectoryCredentialValidationResult.Ok();

                    result.DisplayName = profile.DisplayName;
                    result.Email       = profile.Email;

                    if (_configuration.UseActiveDirectoryUserPhone)
                    {
                        result.Phone = profile.Phone;
                    }
                    if (_configuration.UseActiveDirectoryMobileUserPhone)
                    {
                        result.Phone = profile.Mobile;
                    }

                    return(result);
                }
            }
            catch (LdapException lex)
            {
                var result = ActiveDirectoryCredentialValidationResult.KnownError(lex.ServerErrorMessage);
                _logger.Warning($"Verification user '{user.Name}' at {_configuration.Domain} failed: {result.Reason}");
                return(result);
            }
            catch (Exception ex)
            {
                _logger.Error(ex, $"Verification user '{user.Name}' at {_configuration.Domain} failed.");
                return(ActiveDirectoryCredentialValidationResult.UnknowError());
            }
        }