Blog

A collection of musings about technology, animation, and design.

It can definitely get a little laborious to create, send, and verify nonces manually with every AJAX request in WordPress. Thankfully, there’s an easier way. In this post we’re going to take a look at an easy to set up solution that will automatically send nonces along with every request.

I’m not sure who invented this technique, but the first place I saw it was in Laravel‘s boilerplate JS file.

1. Create a nonce at the top of every page containing AJAX calls

It’s easy enough to do this. Simply add an action to wp_head that injects a meta tag with a nonce. You can add this to functions.php, or wherever makes sense in your plugin or theme.

/**
 * Add a general nonce to requests
 *
 * @link    https://laternastudio.io?p=2110
 * @return  void
 */
function add_general_nonce()
{
    // If you want to limit to specific pages
    // $current_page = get_current_screen()->base;
    //
    // if ( false === strpos( $current_page, 'my-page' ) ) {
    //    return;
    // }

    $nonce = wp_create_nonce( 'my_general_nonce' );
    echo "<meta name='csrf-token' content='$nonce'>";
}

// To add to front-end pages
add_action( 'wp_head', 'add_general_nonce' );

// To add to admin pages
add_action( 'wp_head', 'add_general_nonce' );

2. Have your AJAX framework send the nonce as a HTTP header

I expect in most cases you’ll be using jQuery to handle your AJAX requests. In that case, simply add this to your application’s JS file, or (worst) inline in the footer of your theme.

jQuery(document).ready(function($) {
    var nonce = $('meta[name="csrf-token"]').attr('content');
    $.ajaxSetup({headers: {'X-CSRF-TOKEN': nonce}});
});

3. Create a helper function that verifies your general nonce

Now, in your AJAX endpoints, you’ll want to verify the presence and value of your general nonce. While you could write that verification code separately inside every ajax call, I like to just create a helper function that includes all the logic.  Drop this into your functions.php file.

/**
 * Verify the submitted nonce
 *
 * @return  void
 */
function verify_general_nonce()
{
    $nonce = isset( $_SERVER['HTTP_X_CSRF_TOKEN'] )
        ? $_SERVER['HTTP_X_CSRF_TOKEN']
       : '';

    if ( !wp_verify_nonce( $nonce, 'my_general_nonce' ) ) {
        die();
    }
}

4. Add verify_general_nonce() to your AJAX endpoints

Now that you have a helper function to use you can simply drop it into your AJAX Endpoints like this:

function my_action() {
    verify_general_nonce();

    // Your other code
}
add_action( 'wp_ajax_my_action', 'my_action' );

Pretty handy, right?