skip to Main Content

I really don’t understand what is happening with WordPress nonces, i think they’re wrong, or they’re useless.

I always have troubles working with that nonces, WordPess never been able to check one nonce successfully, i will put here 2 cases in which the nonces aren’t working, in all cases i tried to maken aj AJAX request:

CASE 1:

In this case i tried to use wp_rest nonce to verify it:

PHP (plugin.php):

<?php

require("ajax_endpoints.php");

class MyPluginClass {

public static function setup_plugin() {
   add_shortcode("my_shortcode", array(self::class, "my_shortcode_func"));
}

public my_shortcode_func() {
    
   // Only add scripts when this shotcode is used
   self::add_plugin_scripts();

   wp_enqueue_script("my_script", plugin_url("js/myscript.js", __FILE__), [], "1.0");

   wp_localize_script("my_script", "script_data", array(
        "endpoint_url" => rest_url("/my/rest"),
        "endpoint_url2" => rest_url("/my/rest2"),
        "nonce" => wp_create_nonce("wp_rest")
   ));

}

}

MyPluginClass::setup_plugin();

?>

JS:

$.ajax({
   url: script_data.endpoint_url,
   data: [], // Here is some real data
   type: "post",
   dataType: "json",
   headers: {
     'X-WP-Nonce': script_data.nonce
   },
   success: () => { ... },
   error: () => { ... }
});

It only works when the user is logged in, but i’m not using users on my website, the only user is admin, so, it doesn’t work for guests users (And i need to works for them), when is a guest user, it returns: rest_cookie_invalid_nonce 403 error PD. I don’t put the code of the ajax functions ’cause it doesn’t even get to run them

CASE 2

So i don’t want to put more code here, but, for this case, in wp_create_nonce function i change the wp_rest string for any_valuestring

In the $.ajax call y delete the headers option, and y pass the nonce in the data option as "nonce_field", and in my rest functions i do this:

var_dump(check_ajax_referer("any_value", "nonce_field"));

And it always returns false, the nonce never pass, and also happens with:

var_dump(wp_verify_nonce($_POST["nonce_field"], "any_value"));

So the nonce never is true, and i don’t know why, it should be an WordPress issue, i’m using WordPress 5.5 (The most recent version) so i think if it’s always return false then the nonce in WordPress are useless

Or can you help me what i’m doing wrong? Thanks a lot!!!

2

Answers


  1. Use wp_verify_nonce( $_POST["nonce_field"], "wp_rest" ); for verify nonce.

    Login or Signup to reply.
  2. When you take a look at the wp_verify_nonce function in wp-includes/pluggable.php, you’ll see that it is a user based validation. But in your case you want to make it public and in this case there is no need for nonces. Just tell WordPress the route is to be public by adding 'permission_callback' => '__return_true' into the args array when creating your custom route via the register_rest_route function:

        public function __construct() {
            add_action( 'rest_api_init', array( $this, 'registerRoutes' ), 10 );
        }
    
        public function registerRoutes() {
            register_rest_route(
                'mybase',
                'my/custom/path',
                array(
                    'methods'             => 'POST',
                    'callback'            => array( $this, 'addToCart' ),
                    'permission_callback' => '__return_true',
                    'args'                => array(
                        'product_id'   => array(
                            'type'              => 'integer',
                            'sanitize_callback' => 'absint',
                        ),
                        'variation_id' => array(
                            'type'              => 'integer',
                            'sanitize_callback' => 'absint',
                        ),
                        'quantity'     => array(
                            'type'              => 'integer',
                            'sanitize_callback' => 'absint',
                        )
                    ),
                )
            );
    
        }
    

    Then just remove the x-wp-nonce header from the ajax function:

    $.ajax({
       url: script_data.endpoint_url,
       data: [], // Here is some real data
       type: "post",
       dataType: "json",
       success: () => { ... },
       error: () => { ... }
    });
    

    WordPress checks the nonce automatically (by running the wp_verify_nonce function against the "wp_rest" action name) when you add an X-WP-Nonce header to your ajax request or a "_wpnonce" key to your POST/GET arguments/parameters.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search