Reputation: 133
I'm using AJAX to check body class and conditionally fire one of 2 actions. If the Google Speech API is supported, a voice-search capable form loads. If it isn't, a regular search form loads.
The check_ajax_referer()
function is coming up 403, so there's something wrong with my nonce.
The website is mercury.photo. Code is simplified for clarity; I already know it works if I don't include the nonce check.
In my script, I have:
//-------------------------------------------------*/
// Speech Recognition
//-------------------------------------------------*/
jQuery(document).ready(function ($) {
$(function () {
// Add body class if browser supports Google Voice API
if (Modernizr.speechrecognition) {
$("body").addClass("voice-searchable");
}
var ajaxData;
if ($("body").hasClass("voice-searchable")) {
ajaxData = { "action": "my_voice" }
} else {
ajaxData = { "action": "my_novoice" }
};
xhr = new XMLHttpRequest();
// Use a variable so we can callback 'done' and 'fail'; see https://medium.com/coding-design/writing-better-ajax-8ee4a7fb95f
var ajaxCall = $.ajax({
type: "POST",
url: myVoiceSearch.ajaxurl,
dataType: "html",
data: ajaxData,
security: myVoiceSearch.ajax_nonce
});
// 'success' & 'error' promises are deprecated; use 'done' and 'fail' instead
ajaxCall.done(function (data) {
$(".breadcrumb_search").html(data);
});
ajaxCall.fail(function (data, xhr, ajaxOptions, thrownError) {
var errorMsg = "Oh, bother. Your AJAX request failed with a status code of " + xhr.responseText + ".";
console.log( errorMsg );
});
});
});
(window, jQuery, window.Window_Ready);
// More scripts to load Google Voice API
And in functions.php
, I enqueue my scripts and add the actions:
/*
* Ajax scripts for speech recognition
*/
add_action( 'wp_print_scripts', 'my_search_ajax_enqueue' );
function my_search_ajax_enqueue() {
if ( ! is_admin() ) { // Load the script only on the front end
$protocol = isset( $_SERVER['HTTPS'] ) ? 'https://' : 'http://';
wp_register_script( "my-search-ajax-script", get_stylesheet_directory_uri() . '/js/speech-input.js', array( 'jquery' ) );
$params = array( 'ajaxurl' => admin_url( 'admin-ajax.php', $protocol), 'ajax_nonce' => wp_create_nonce( 'my-create-voice-search-nonce' ), );
wp_localize_script( 'my-search-ajax-script', 'myVoiceSearch', $params );
wp_enqueue_script( 'my-search-ajax-script' );
};
}
/**
*
* Generate custom search form
*
**/
function my_voice() {
// This check fails
check_ajax_referer( 'my-create-voice-search-nonce', 'security' );
$form = 'A most excellent form, m’lord.';
echo $form;
wp_die();
}
add_action('wp_ajax_my_voice', 'my_voice');
add_action('wp_ajax_nopriv_my_voice', 'my_voice');
function my_novoice() {
// check_ajax_referer( 'my-create-voice-search-nonce', 'security' );
$form = 'Lame form, dude!';
echo $form;
wp_die();
}
add_action('wp_ajax_my_novoice', 'my_novoice');
add_action('wp_ajax_nopriv_my_novoice', 'my_novoice');
EDIT: Did some more reading, and it appears the main function of WP nonces is to prevent CSRF, and as such, is really only useful for logged-in users. So, more questions:
EDIT: Further reading confirms that I shouldn't even be doing this, since it's a front-end form. Closing this question, but feel free to comment/answer if you know what was wrong with my code — I always appreciate the opportunity to learn!
EDIT: Answer given and accepted.
Upvotes: 0
Views: 3022
Reputation: 1458
All the variables to be accessible for the wp_ajax
callback functions need to be set in the data
argument of the jquery ajax request. Therefore the nonce value needs to be included in your ajaxData variable as follows:
ajaxData = { "action": "my_voice", "security": myVoiceSearch.ajax_nonce}
Upvotes: 1