WP AJAX: nonce works when logged out, but not when logged in
If you've ever worked with WordPress, you're probably familiar with the concept of nonces. Nonces are unique tokens that WordPress uses to help protect against CSRF (Cross-Site Request Forgery) attacks. They are an essential part of secure WordPress development.
However, when it comes to using nonces with WordPress' REST API, there are some specific requirements that you need to be aware of. In this article, we'll dive into the problem of nonces not working when a user is logged in, and provide a solution to ensure your AJAX requests are properly authenticated.
The Problem: nonce works when logged out, but not when logged in
The issue arises when you're making AJAX requests to custom WordPress REST API endpoints. You might find that your nonce works fine when the user is logged out, but as soon as they log in, the nonce suddenly stops working.
The reason for this is that nonces are handled differently for API requests compared to regular WordPress requests. According to the WordPress developer documentation:
For developers making manual Ajax requests, the nonce will need to be passed with each request. The API uses nonces with the action set to wp_rest
. These can then be passed to the API via the _wpnonce
data parameter (either POST data or in the query for GET requests), or via the X-WP-Nonce
header.
In other words, when you're making AJAX requests to the WordPress REST API, you need to use a specific nonce action, wp_rest
, instead of your custom nonce action.
The Solution: Use the wp_rest
nonce action
To fix the issue of nonces not working when the user is logged in, you need to follow these steps:
- Generate the nonce with the
wp_rest
action:
$nonce = wp_create_nonce('wp_rest');
- Pass the nonce via the
X-WP-Nonce
header:
$.ajax({
type: 'POST',
url: your-api-url-here,
contentType: 'application/json; charset=UTF-8',
beforeSend: function(jqXhr) {
jqXhr.setRequestHeader('X-WP-Nonce', nonce);
},
data: your-data-here
});
By using the wp_rest
nonce action and passing the nonce via the X-WP-Nonce
header, you're ensuring that the logged-in user is correctly loaded in the API request context. Otherwise, you would be generating your custom nonce with a logged-in user, but trying to verify it with an anonymous user (which is the default for API calls unless you use this nonce).
Here's an example of how you can implement this in your WordPress plugin or theme:
// PHP
function my_custom_ajax_endpoint() {
$nonce = wp_create_nonce('wp_rest');
// Your custom API logic
$response = array(
'success' => true,
'data' => 'This is a successful response!'
);
wp_send_json($response);
}
add_action('wp_ajax_my_custom_ajax_endpoint', 'my_custom_ajax_endpoint');
add_action('wp_ajax_nopriv_my_custom_ajax_endpoint', 'my_custom_ajax_endpoint');
// JavaScript
jQuery(document).ready(function($) {
$('#my-ajax-button').on('click', function() {
var nonce = '<?php echo wp_create_nonce('wp_rest'); ?>';
$.ajax({
type: 'POST',
url: '<?php echo admin_url('admin-ajax.php'); ?>',
data: {
action: 'my_custom_ajax_endpoint',
_wpnonce: nonce
},
beforeSend: function(jqXhr) {
jqXhr.setRequestHeader('X-WP-Nonce', nonce);
},
success: function(response) {
console.log(response);
}
});
});
});
In this example, we're creating a custom AJAX endpoint called my_custom_ajax_endpoint
. We're generating the nonce with the wp_rest
action and passing it via the X-WP-Nonce
header in the JavaScript AJAX request.
By following this approach, your nonces should now work correctly, regardless of whether the user is logged in or not.
Additional Considerations
- Make sure you're setting the
contentType
option in your AJAX request to 'application/json; charset=UTF-8'
. This ensures that your data is properly serialized and sent in the correct format.
- If you're using a plugin or a library that handles AJAX requests for you (like
wp.ajax
in the WordPress admin), you'll need to ensure that it's properly passing the X-WP-Nonce
header. Consult the documentation for the specific plugin or library you're using.
- In addition to the
X-WP-Nonce
header, you can also pass the nonce as a data parameter (_wpnonce
) in your AJAX request. However, the X-WP-Nonce
header is the recommended approach.
By following these steps, you should be able to resolve the issue of nonces not working when a user is logged in, and ensure your WordPress REST API AJAX requests are properly authenticated.
Flowpoint.ai can help you identify all the technical errors that are impacting conversion rates on your website and directly generate recommendations to fix them