1


I've a made a plugin which generates a login form, by using a shortcode. The login works, however, inside the dashboard I've noticed that the forms submits don't work properly. For example, the profile update doesn't work, namely, when the Save button is pressed, the page is reloaded, but the changes are not stored into the database.
Here is the code:

function login_validation( $username, $password )  {
    global $reg_errors;
    $reg_errors = new WP_Error;

    if ( empty( $username ) && !empty( $password ) ) {
        $reg_errors->add('field', 'The username field is empty');
    } else if ( !empty( $username ) && empty( $password ) ) {
        $reg_errors->add('field', 'The password field is empty');
    } else if ( empty( $username ) && empty( $password ) ) {
        $reg_errors->add('field', 'The fields are empty');
    } else if ( !username_exists( $username ) ) {
        $reg_errors->add('user_name', 'Sorry, that username doesn\'t exists!');
    } else if ( !validate_username( $username ) ) {
        $reg_errors->add('username_invalid', 'Sorry, the username you entered is not valid');
    }

    if ( is_wp_error( $reg_errors ) ) {

        foreach ( $reg_errors->get_error_messages() as $error ) {
            echo '<div class="alert alert-danger message-box">';
            echo '<strong>ERROR</strong>: ';
            echo $error . '<br/>';
            echo '</div>';
        }
    }
}

function custom_login() {
    if (isset($_POST['submit'])) {
        $login_data = array();
        $login_data['user_login'] = sanitize_user($_POST['username']);
        $login_data['user_password'] = esc_attr($_POST['password']);

        $user = wp_signon( $login_data, false );

        if ( is_wp_error($user) ) {
            echo $user->get_error_message();
        } else {
            wp_clear_auth_cookie();
            do_action('wp_login', $user->ID);
            wp_set_current_user($user->ID);
            wp_set_auth_cookie($user->ID, true);
            $redirect_to = $_SERVER['REQUEST_URI'];
            wp_safe_redirect($redirect_to);
            exit;
        }
    }
}

function login_form() { ?>
    <form action="<?php echo $_SERVER['REQUEST_URI'] ?>" method="post">
        <div class="input-group">
            <label for="username">Username <span class="form-required" title="This field is required.">*</span></label>
            <input type="text" name="username" placeholder="Username">
        </div>

        <div class="input-group">
            <label for="password">Password <span class="form-required" title="This field is required.">*</span></label>
            <input type="password" name="password" placeholder="Password">
        </div>
        <?php wp_nonce_field('wp_login'); ?>

        <div class="input-group">
            <input type="submit" name="submit" value="Log in"/>
        </div>
    </form>
<?php }

add_action( 'after_setup_theme', 'custom_login' );

/*
 * Remove the response error messages from the header
 */
add_filter( 'gettext', 'change_error_messages', 10, 3 );
function change_error_messages( $translation, $text, $domain ) {
    if ( 'default' !== $domain )
        return $translation;

    if ( '<strong>ERROR</strong>: The password you entered for the username <strong>%1$s</strong> is incorrect. <a href="%2$s" title="Password Lost and Found">Lost your password</a>?' == $text )
        return '';

    if ( '<strong>ERROR</strong>: The password field is empty.' == $text )
        return '';

    if ( '<strong>ERROR</strong>: Invalid username. <a href=\"%s\" title=\"Password Lost and Found\">Lost your password</a>?' == $text )
        return '';

    return $translation;    
}

// The callback function that will replace
function custom_login_shortcode() {
    ob_start();
    custom_login_function();
    return ob_get_clean();
}

// Register a new shortcode: [cr_custom_login]
add_shortcode('cr_custom_login', 'custom_login_shortcode');

If I disable this plugin, everything works. I think the problem is that some sort of validation doesn't take place. Maybe the nonce field? Am I right? How can I fix it?
Thanks!

UPDATE
As the user @Krzysiek Dróżdż suggested, I updated the custom_login function as follows:

function custom_login() {
    if (isset($_POST['submit'])) {
        $login_data = array();
        $login_data['user_login'] = sanitize_user($_POST['username']);
        $login_data['user_password'] = esc_attr($_POST['password']);
        $nonce = $_REQUEST['_wpnonce'];

        $user = wp_signon( $login_data, false );

        global $user_ID;
        // Check whether the user is already logged in
        if ( !$user_ID ) {
            if ( ! wp_verify_nonce( $nonce, 'wp_login' ) ) {
                // die( 'Security check' );
                exit;
            } else {
                if ( is_wp_error($user) ) {
                    echo $user->get_error_message();
                } else {
                    wp_clear_auth_cookie();
                    do_action('wp_login', $user->ID);
                    wp_set_current_user($user->ID);
                    wp_set_auth_cookie($user->ID, true);
                    $redirect_to = $_SERVER['REQUEST_URI'];
                    wp_safe_redirect($redirect_to);
                    exit;
                }
            }
        }
    }
}

Now the problem seems to be fixed.
What if I want to use another type of check instead of if (isset($_POST['submit']))?

  • 1
    You're pretty brave to try the login process every time there is a $_POST['submit'] available. Any form could set that. Also sending the form to current address isn't very good idea. And worse, you don't check that nonce anywhere... Why don't you use wp_login_form() function? – Krzysiek Dróżdż Mar 24 '18 at 11:27
0

Here is my working solution:

function custom_login() {
    if(!empty($_POST['user_login']) && !empty($_POST['user_pass'])){
        $login_data = array();
        $login_data['user_login'] = sanitize_user($_POST['user_login']);
        $login_data['user_password'] = esc_attr($_POST['user_pass']);
        $login_data['rememberme'] = true;
        $nonce = $_REQUEST['_wpnonce'];

        $user = wp_signon( $login_data, false );

        global $user_ID;
        // Check whether the user is already logged in and the nonce is verified
        if ( !$user_ID && !wp_verify_nonce( $nonce, 'wp_login' ) ) {
            exit;
        } else {
            if ( is_wp_error($user) ) {
                echo $user->get_error_message();
            } else {
                wp_clear_auth_cookie();
                do_action('wp_login', $user->ID);
                wp_set_current_user($user->ID);
                wp_set_auth_cookie($user->ID, true);
                wp_safe_redirect(home_url());
                exit;
            }
        }
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.