Limit Login Attempts

Is there a way to link the login modals and the hp login block with a plugin that limits login attempts? First and foremost I want to remove the default wordpress login possibilty through wp-admin, and I find that the login block that comes with hivepress can work good instead.

The limiting login attempts plugins that I’ve found seems to just work with the default wp-admin / wp-login form, not with any modals or login-blocks.

Also, is the login-block using the wp_login_form( ); function? Can I add a redirect for when people logs in through this login-block? (I don’t wanna touch the modals redirection, because it makes sense to stay on the same page then)

The HivePress login form doesn’t use the wp_login_form function, but it uses the same WordPress actions - I recommend checking another plugin that uses the wp_authenticate or other WordPress hooks to count the login attempts and block the login. You can also enable reCaptcha instead or in addition to this, this will prevent possible brute force attacks.

Thank you for the input and suggestions.

If you have time, can you point me in the direction of the template file that is used for the login modal/block?

There’s no specific file, but you can almost fully customize this form via these hooks:

hivepress/v1/blocks/user_login_form
hivepress/v1/forms/user_login

This way you can customize the form message, fields, add some content before or after the form, etc.

1 Like

You can also call a custom function on form submission using this hook:

hivepress/v1/forms/user_login/errors

1 Like

For some styling reasons, I’m trying to push the element below the input element, but when I try to move it, the label and the input moves together.

add_filter(
	'hivepress/v1/forms/user_login',
	function( $form ) {
		$form['fields']['username_or_email']['_order'] = 100;

		return $form;
	},
	1000
);

Any idea how I can achieve this?

Yes, the form field is an element that contains the field label, description and the input itself (you can check how fields are rendered in HTML, with .hp-form__field DIV containers), unfortunately there’s no way to move the input without a label.

I see. Can I unset the current form layout and load some custom html, and target the hivepress login logic by adding id’s and/or classes to the inputs and submit button?

It would be easier to use the existing HivePress hooks because overriding the form may cause issues in future updates, e.g. if we fix or update something regarding the login process and something in the forum parameters will also change.

If the login attempts plugin you’re using has any function to count or check the attempts, I recommend adding it to the hivepress/v1/forms/user_login/errors callback, it’s a filter hook so you can add any custom errors this way:

if(plugin_function_that_counts_login_attempts()>3) {
    $errors[]='Too many login attempts, please wait a bit.';
}

Thanks. Well, the main reason for creating a new html is to restructure the order, making it more customizable. So i can have Input then label

There may be some CSS hacks for this, for example:

display:flex;
flex-direction: column-reverse;

Unfortunately I can’t suggest anything about replacing the form, this would require further template customizations in site_footer_block and user_login_page, causing possible incompatibility issues in the future.

I understand, however it does not change the order of the elements, only visually. It doesnt allow for the input element to controll the label element through CSS sibling selectors like + and ~, because the input is after the label.

Its strange that there is no easy way to achieve it? If not, maybe the vanilla layout should have the reverse order, making it more customizable.

It’s not impossible, but it’s a bad practice because any improvements or changes made to the default form will not be reflected if you override it with a completely custom one. If you’re familiar with PHP please try following this tutorial Customizing Templates I HivePress Developer Docs - YouTube to replace the user_login_form block in site_footer_block and user_login_page templates.

Okay so I’ve come up with a workaround using the :has condition.

Anyway, I need to add an html element after the inputs now:

<label> username </label>
<input> </input>
<HTML CUSTOM> <----- HERE, this one i need to add

<label> password</label>
<input> </input>
<HTML CUSTOM><----- HERE, this one i need to add

so within every hp-form__field wrapper

thanks alot for the help @ihor

Unfortunately there’s no hook for this at the moment, you can use these hooks to override the form and field parameters, or add custom validation:

hivepress/v1/forms/user_login
hivepress/v1/forms/user_login/errors

Also, you can replace the form completely by customizing the site_footer_block and user_login_page templates.

When it comes to linking the limiting login function to the hivepress login form, I cannot get it to work. I think the problem is that trying to login through the hivepress login forms doesn’t increase the count of login attempts in the function.

First is the limit login attempts logic, and down is the connection with the HP login form.

// Limit login attempts

function check_attempted_login( $user, $username, $password ) {
    if ( get_transient( 'attempted_login' ) ) {
        $datas = get_transient( 'attempted_login' );

        if ( $datas['tried'] >= 3 ) {
            $until = get_option( '_transient_timeout_' . 'attempted_login' );
            $time = time_to_go( $until );

            return new WP_Error( 'too_many_tried',  sprintf( __( '<strong>ERROR</strong>: You have reached authentication limit, you will be able to try again in %1$s.' ) , $time ) );
        }
    }

    return $user;
}
add_filter( 'authenticate', 'check_attempted_login', 30, 3 ); 
function login_failure( $username ) {
    if ( get_transient( 'attempted_login' ) ) {
        $datas = get_transient( 'attempted_login' );
        $datas['tried']++;

        if ( $datas['tried'] <= 3 )
            set_transient( 'attempted_login', $datas , 300 );
    } else {
        $datas = array(
            'tried'     => 1
        );
        set_transient( 'attempted_login', $datas , 300 );
    }
}
add_action( 'wp_login_failed', 'login_failure', 10, 1 ); 

function time_to_go($timestamp)
{

    // converting the mysql timestamp to php time
    $periods = array(
        "second",
        "minute",
        "hour",
        "day",
        "week",
        "month",
        "year"
    );
    $lengths = array(
        "60",
        "60",
        "24",
        "7",
        "4.35",
        "12"
    );
    $current_timestamp = time();
    $difference = abs($current_timestamp - $timestamp);
    for ($i = 0; $difference >= $lengths[$i] && $i < count($lengths) - 1; $i ++) {
        $difference /= $lengths[$i];
    }
    $difference = round($difference);
    if (isset($difference)) {
        if ($difference != 1)
            $periods[$i] .= "s";
            $output = "$difference $periods[$i]";
            return $output;
    }
}

// Connect it with the hp login form
add_filter(
	'hivepress/v1/forms/user_login/errors',
	function( $errors ) {

		if ( check_attempted_login() > 3 ) {
            $errors[]='Too many login attempts, please wait a bit.';
        }

		return $errors;
	},
	1000,
	2
);

Please try debugging this further, because the hivepress/v1/forms/user_login/errors is 100% called on every HivePress login form submission. You can check this by adding error_log(123) and checking the PHP log after every submission, if it’s called correctly you can move error_log to other functions you’re using to calculate and save the number of attempts.

When adding the above hp Hook, it not only does not work, but it removes the other errors from the form aswell (like wrong username or password, or captcha error).

I might have gotten the implementation wrong, and have to merge it or something?

Please make sure that you don’t override the errors array, but add a new item, and it’s also important to return it at the end of the function (it’s a filter hook).

Yes I seem to be overriding something. Instead of launching an error message, the login page is refreshed.

Is it possible to get some help with the snippet?

Also, the first part of the code is aimed at the generic wordpress login form. However, hivepress already returns errors upon entering a wrong username / passord combination. Is it possible to get assistance with adding a counter to this error, and then when it exceeds “X” attempts, return the error restricting login attempts? (I think the captcha solution takes away from the user experience, as it affects every login atempt)

Thank you in advance.