How to securely add an Ajax button to a WP Admin page?

In this answer I created 2 buttons which are visually disabled and get an invalid nonce before submitting.

<?php
/*
Plugin Name: Ajax Example
*/

add_action( 'admin_notices', 'my_action_button' );

define( 'MY_ACTION_NONCE', 'my-action-' );

function my_action_button() {
    $id   = 4321;
    $data = array(
        'data-nonce' => wp_create_nonce( MY_ACTION_NONCE . $id ),
        'data-id'    => $id,
    );
    echo get_submit_button( "Ajax Primary", 'primary large', 'my-action-button-1', FALSE, $data );

    $id   += 1234;
    $data = array(
        'data-nonce' => wp_create_nonce( MY_ACTION_NONCE . $id ),
        'data-id'    => $id,
    );
    echo get_submit_button( "Ajax Secundary", 'secondary', 'my-action-button-2', FALSE, $data );
}

add_action( 'admin_footer', 'my_action_javascript' ); // Write our JS below here

function my_action_javascript() {
    ?>
    <script type="text/javascript">
        jQuery(document).ready(function ($) {
            $('#my-action-button-1,#my-action-button-2').click(function () {
                var $button = $(this);

                var data = {
                    'action': 'my_action',
                    'id': $button.data('id'),
                    'nonce': $button.data('nonce')
                };
                // Give user cue not to click again
                $button.addClass('disabled');
                // Invalidate the nonce
                $button.data('nonce', 'invalid');

                $.post(ajaxurl, data, function (response) {
                    alert('Got this from the server: ' + response);

                });
            });
        });
    </script>
    <?php
}

add_action( 'wp_ajax_my_action', 'my_action' );

function my_action() {
    global $wpdb; // this is how you get access to the database

    $id    = $_POST['id'];
    $nonce = $_POST['nonce'];
    if ( wp_verify_nonce( $nonce, MY_ACTION_NONCE . $id ) ) {
        $response = intval( $id );
        $response += 10;
        echo $response;
    } else {
        echo - 1;
    }
    wp_die(); // this is required to terminate immediately and return a proper response
}

Leave a Comment