Nonces and Ajax request to REST API and verification

For restricting access to your REST API endpoint, you can use the permission_callback parameter like so:

register_rest_route( 'rw-user/v1', '/log-out', array(
    'methods'             => 'POST',
    'callback'            => 'ajax_logout',
    'permission_callback' => function () {
        return current_user_can( 'read' );
    },
) );

And that will require the current user to be logged into WordPress and also the REST API in order to access the endpoint at example.com/wp-json/rw-user/v1/log-out.

So, if the endpoint is already doing the verification, surely it should fail if no nonce is present?

Yes. However,

If I don’t pass the nonce header, it doesn’t check the nonce, yet still runs the function…

That’s because the endpoint’s callback is always called once the permissions callback returns a true — and note that, in WordPress 5.5 and later, you should always set the callback — you can use __return_true to allow all access to the endpoint. E.g.

register_rest_route( 'rw-user/v1', '/log-in', array(
    'methods'             => 'POST',
    'callback'            => 'ajax_login',
    'permission_callback' => '__return_true',
) );

I can see the new nonce returned in my console… I used it to update the header in my next request – but the nonce fails despite being new?

It’s probably because you’re not sending the correct nonce.

  • The nonce action for authenticating the current user is wp_rest, so you should use wp_create_nonce( 'wp_rest' ) when generating the (new) nonce.

  • And be sure to send the nonce via either the X-WP-Nonce header (preferred) or the _wpnonce data parameter (which is not bad, but not very reliable).

So regarding that “do not need to verify“, it’s only true for the wp_rest nonce (i.e. the default cookie-based authentication). All other nonces, should there be any, need to be verified manually.

Leave a Comment