Action uncanny-learndash-toolkit

wp_login_failed

Fires when a user's login attempt fails due to incorrect username or password.

add_action( 'wp_login_failed', $callback, 10, 1 );

Description

Fires immediately after a login attempt has failed. This hook is useful for logging failed login attempts, implementing brute-force protection, or sending notifications when a user fails to log in. The `$user` parameter contains the username or user ID that was attempted.


Usage

add_action( 'wp_login_failed', 'your_function_name', 10, 1 );

Parameters

$user (mixed)
The `$user` parameter is a mixed type that can contain a `WP_User` object if the login attempt included a valid username, or a string containing the username that was attempted otherwise.

Examples

<?php
/**
 * Log failed login attempts to a custom log file or external service.
 *
 * This function is triggered when a user fails to log in to WordPress.
 * It captures the username (or email if that's what was used) and logs
 * the event for security auditing or debugging purposes.
 *
 * @param string $user The username (or email) that was attempted for login.
 */
function my_custom_wp_login_failed_handler( $user ) {
    // Ensure the log directory exists.
    $upload_dir = wp_upload_dir();
    $log_dir    = trailingslashit( $upload_dir['basedir'] ) . 'login-attempts/';

    if ( ! file_exists( $log_dir ) ) {
        wp_mkdir_p( $log_dir );
    }

    $log_file = trailingslashit( $log_dir ) . 'failed-logins.log';

    // Get current timestamp.
    $timestamp = current_time( 'mysql' );

    // Get the IP address of the user attempting to log in.
    $ip_address = '';
    if ( ! empty( $_SERVER['REMOTE_ADDR'] ) ) {
        $ip_address = sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) );
    }

    // Format the log message.
    $log_message = sprintf(
        "[%s] Failed login attempt for user: '%s' from IP: %sn",
        $timestamp,
        sanitize_text_field( $user ),
        $ip_address
    );

    // Append the log message to the file.
    // Use FILE_APPEND and LOCK_EX for safe writing.
    @file_put_contents( $log_file, $log_message, FILE_APPEND | LOCK_EX );

    // You could also send an email notification to an administrator for critical events.
    // For example:
    /*
    $admin_email = get_option( 'admin_email' );
    if ( $admin_email ) {
        wp_mail(
            $admin_email,
            sprintf( __( '[%s] Failed Login Attempt', 'your-text-domain' ), get_bloginfo( 'name' ) ),
            sprintf(
                __( 'A failed login attempt occurred for user "%s" from IP address %s at %s.', 'your-text-domain' ),
                sanitize_text_field( $user ),
                $ip_address,
                $timestamp
            )
        );
    }
    */
}
add_action( 'wp_login_failed', 'my_custom_wp_login_failed_handler', 10, 1 );
?>

Placement

This code should be placed in the functions.php file of your active theme, a custom plugin, or using a code snippets plugin.


Source Code

src/includes/two-factor/providers/wp-2fa/legacy/class-frontend-login-plus-2fa-2.6.php:370
src/includes/two-factor/providers/wp-2fa/legacy/class-frontend-login-plus-2fa-2-4.php:333
src/includes/two-factor/providers/wp-2fa/legacy/class-frontend-login-plus-2fa-2-5.php:332

exit;
			}

			// Backup Codes.
			if ( 'backup_codes' === $provider && true !== Backup_Codes::validate_backup_codes( $user ) ) {

				do_action( 'wp_login_failed', $user->user_login );

				$login_nonce = $this->two_factor::create_login_nonce( $user->ID );

				if ( ! $login_nonce ) {
					wp_die( esc_html__( 'Failed to create a login nonce.', 'uncanny-learndash-toolkit' ) );
				}

Scroll to Top