How to Build a Front-end Password Reset Form in WordPress

on in WordPress
Last modified on

I have just moved an entire user account module from the back-end of WordPress to the front-end. This includes the login form, the registration form and the user account section, where users can manage their accounts, and also do specific tasks related to the project.

Although WordPress has a default system in place for this, this was an instance where a custom implementation was needed.

In this article, I’ll guide you on how to build a front-end forgotten password form.

Table of Contents

1. Building the Form

Firstly, you’ll need to create the HTML form where users can enter their email address. Here’s a basic example:

<form id="lostpasswordform" action="" method="post">
    <p>
        <label for="user_login">Email</label>
        <input type="text" name="user_login" id="user_login">
    </p>
    <input type="hidden" name="action" value="reset">
    <p class="submit">
        <input type="submit" name="submit" id="submit" value="Request New Password">
    </p>
</form>

This is a simple form that includes an input field for the user’s email and a submit button.

2. Processing the Form with AJAX

We can use WordPress’s built-in AJAX functionality to handle form submissions. In your JavaScript file, add the following:

jQuery('#lostpasswordform').on('submit', function(e) {
    e.preventDefault();
    var formData = jQuery(this).serialize();
    jQuery.ajax({
        type: 'POST',
        dataType: 'json',
        url: ajax_object.ajaxurl,
        data: formData,
        success: function(response) {
            if(response.status === 'success') {
                alert('Check your email for the confirmation link.');
            } else {
                alert('An error occurred, please try again.');
            }
        }
    });
});

Or, if you want vanilla JavaScript (which you should), see below:

document.getElementById('lostpasswordform').addEventListener('submit', function(e) {
    e.preventDefault();
    var formData = new FormData(this);
    var xhr = new XMLHttpRequest();
    xhr.open('POST', ajax_object.ajaxurl, true);
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xhr.onreadystatechange = function() {
        if (xhr.readyState === XMLHttpRequest.DONE) {
            var response = JSON.parse(xhr.responseText);
            if (response.status === 'success') {
                alert('Check your email for the confirmation link.');
            } else {
                alert('An error occurred, please try again.');
            }
        }
    };
    xhr.send(new URLSearchParams(formData).toString());
});

Or, if you want to use the Fetch API, see below:

document.getElementById('lostpasswordform').addEventListener('submit', async (e) => {
    e.preventDefault();
    const formData = new FormData(e.target);
    try {
        const response = await fetch(ajax_object.ajaxurl, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            body: new URLSearchParams(formData)
        });
        const data = await response.json();
        if (data.status === 'success') {
            alert('Check your email for the confirmation link.');
        } else {
            alert('An error occurred, please try again.');
        }
    } catch (error) {
        console.error('An error occurred:', error);
        alert('An error occurred, please try again.');
    }
});

Ensure that you’ve localized the ajax_object correctly in WordPress.

3. Handling the Form Submission in PHP

Now we need to handle the form submission in PHP. This will be done by adding a new function to your theme’s functions.php file or to a custom plugin:

function ajax_password_reset() {
    $email_address = $_POST['user_login'];
    $user_data     = get_user_by( 'email', trim( wp_unslash( $email_address ) ) );
    if ( empty( $user_data ) ) {
        echo json_encode( [ 'status' => 'error' ] );
        exit;
    }

    $user_login = $user_data->user_login;
    $user_email = $user_data->user_email;

    do_action( 'retrieve_password', $user_login );

    $allow = apply_filters( 'allow_password_reset', true, $user_data->ID );
    if ( ! $allow ) {
        echo json_encode( [ 'status' => 'error' ] );
        exit;
    } elseif ( is_wp_error( $allow ) ) {
        echo json_encode( [ 'status' => 'error' ] );
        exit;
    }
    $key = get_password_reset_key( $user_data );

    if ( is_wp_error( $key ) ) {
        echo json_encode( [ 'status' => 'error' ] );
        exit;
    }


    $message  = __( 'Someone has requested a password reset for the following account:' ) . "\r\n\r\n";
    $message .= network_home_url( '/' ) . "\r\n\r\n";
    $message .= sprintf( __( 'Username: %s' ), $user_login ) . "\r\n\r\n";
    $message .= __( 'If this was a mistake, just ignore this email and nothing will happen.' ) . "\r\n\r\n";
    $message .= __( 'To reset your password, visit the following address:' ) . "\r\n\r\n";
    $message .= network_site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user_login ), 'login' ) . "\r\n";

    if ( is_multisite() ) {
        $blogname = $GLOBALS['current_site']->site_name;
    } else {
        $blogname = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
    }

    $title = sprintf( __( '[%s] Password Reset' ), $blogname );

    if ( $message && ! wp_mail( $user_email, wp_specialchars_decode( $title ), $message ) ) {
        echo json_encode( [ 'status' => 'error' ] );
    } else {
        echo json_encode( [ 'status' => 'success' ] );
    }
    exit;
}
add_action( 'wp_ajax_nopriv_reset', 'ajax_password_reset' );

This function retrieves the user’s data using the submitted email address, generates a password reset key, constructs a password reset email, and sends it to the user’s email address.

Now you have a frontend password reset form in WordPress! You may need to customize this code further to suit your site’s design and functionality requirements.

By following these steps, you can create a functional and user-friendly frontend password reset form for your WordPress site. Not only does this provide a better user experience by keeping users on the frontend of your site, but it also allows you to maintain consistent branding and design throughout the user journey.

Remember to always test thoroughly when implementing new functionality, and take user privacy and security into account. Encrypt or safely discard any data that you don’t need to store, and ensure you’re following best practices when it comes to handling user data.

Related posts