Implement Secure Ajax Login in WordPress Without Page Refresh

Transform your user authentication flow with a high-performance Ajax login system. This guide covers how to process login requests in the background using the wp_ajax action and the wp_signon function. By integrating jQuery's $.ajax and WordPress nonces for security, you can provide real-time feedback (success or error messages) directly on the login form without refreshing the page. This modern approach reduces server load and creates a smoother, more professional user experience for membership sites and online stores.

WordPress Ajax Login with jQuery and PHP

Ajax Wordpress Code Snippets Coding Blog PHP PHP Debugging PHP Development PHP Snippets Theme Customization Theme Development WooCommerce Tips Wordpress WordPress Code Snippets WordPress Development WordPress Functions

WordPress Ajax Login with jQuery and PHP Tutorial/Guide

Here’s a complete walkthrough for creating an Ajax-based login system in WordPress, ensuring users can log in without page reloads:

1. Modify functions.php

Head to Appearance > Theme Editor and open functions.php. Add the following code snippet:

function enqueue_custom_scripts() {
    wp_enqueue_script('jquery');
    wp_enqueue_script('custom-scripts', get_stylesheet_directory_uri() . '/js/custom-scripts.js', array('jquery'), '1.0', true);
    wp_localize_script('custom-scripts', 'ajax_login_object', array(
        'ajax_url' => admin_url('admin-ajax.php'),
        'redirect_url' => home_url()
    ));
}
add_action('wp_enqueue_scripts', 'enqueue_custom_scripts');

function ajax_login() {
    check_ajax_referer('ajax-login-nonce', 'security');

    $info = array(
        'user_login'    => $_POST['username'],
        'user_password' => $_POST['password'],
        'remember'      => true
    );

    $user_signin = wp_signon($info, false);

    if (is_wp_error($user_signin)) {
        echo json_encode(array('loggedin' => false, 'message' => __('Invalid username or password.', 'text-domain')));
    } else {
        echo json_encode(array('loggedin' => true, 'message' => __('Welcome back!', 'text-domain')));
    }

    die();
}
add_action('wp_ajax_ajax_login', 'ajax_login');
add_action('wp_ajax_nopriv_ajax_login', 'ajax_login');

2. Create JavaScript File

Inside your theme's /js folder, create custom-scripts.js and add the following code:

jQuery(document).ready(function($) {
    $(document).on('submit', '#login-form', function(e) {
        e.preventDefault();

        var $form = $(this),
            $submit = $form.find('input[type="submit"]'),
            $msg = $form.find('.login-message');

        $submit.attr('disabled', true);

        $.ajax({
            type: 'POST',
            url: ajax_login_object.ajax_url,
            data: {
                action: 'ajax_login',
                username: $form.find('#username').val(),
                password: $form.find('#password').val(),
                security: $('#ajax-login-nonce').val()
            },
            success: function(res) {
                var data = JSON.parse(res);
                $msg.html('<p class="' + (data.loggedin ? 'login-success' : 'login-error') + '">' + data.message + '</p>');

                if (data.loggedin) {
                    window.location.href = ajax_login_object.redirect_url;
                }
                $submit.removeAttr('disabled');
            },
            error: function() {
                $msg.html('<p class="login-error">Login failed. Please try again.</p>');
                $submit.removeAttr('disabled');
            }
        });
    });
});

3. HTML Login Form

Use this form where you want the login box to appear:

<form id="login-form" method="post">
    <input type="text" id="username" name="username" placeholder="Username" required>
    <input type="password" id="password" name="password" placeholder="Password" required>
    <?php wp_nonce_field('ajax-login-nonce', 'ajax-login-nonce'); ?>
    <input type="submit" value="Log In">
    <div class="login-message"></div>
</form>

Pro Tip: Always test login functionality with both valid and invalid credentials, and use a child theme to ensure your modifications aren’t lost on update.  

๐Ÿ’ก Have a Coding Problem?

Search our archives or reach out to our team for solutions and expert advice.