0

I have created a plugin in with several custom REST endpoints. However I can not get the permission callbacks to work. Current user is always '0'. I'm using localize script to send the nonce.

        wp_localize_script( $this->cloud_base, 'POST_SUBMITTER', array(
        'root' => esc_url_raw( rest_url() ),
        'nonce' => wp_create_nonce( 'wp_rest' ),
        'success' => __( 'Data Has been updated!', 'your-text-domain' ),
        'failure' => __( 'Your submission could not be processed.', 'your-text-domain' ),
        'current_user_id' => get_current_user_id()
        )
    ); 

And then in the javascript code i'm modifying the sync function to return the nonce:

    app.Model = Backbone.Model.extend({
// over ride the sync function to include the Wordpress nonce.  
    sync: function( method, model, options ){
        return Backbone.sync(method, this, jQuery.extend( options, {
            beforeSend: function (xhr) {
            alert(POST_SUBMITTER.nonce);  // nonce is shown here. 
            xhr.setRequestHeader( 'X-WP-NONCE', POST_SUBMITTER.nonce );
            },
        } ));   
    },  
});

Backbone is used to general a list of items from the REST endpoint and generate a form for adding or updating. (everything works fine if I disable access checks.)

In my access check the current user is always 0

    public function cloud_base_members_access_check(){  
    if (  current_user_can( 'read' )) {
        return true;
    }
    return new \WP_Error( 'rest_forbidden', esc_html__( 'Sorry, you are not authorized for that.', 'my-text-domain' ), array( 'status' => 401 ) );
}   

The Wordpress REST handbook seams to suggest this should just work. I've combined element from several different examples trying to make this work, but I have found no example of how to make this all work together. Have been trying to make this work for about a week now and I am out of ideas? Any suggestion as to how to make this work?

4
  • Have you inspected the network requests (XHR) to check if the nonce header did get sent? And are you aware of the wp-api script and that you can extend its models and collections (e.g. for custom post types)?
    – Sally CJ
    Oct 1 '20 at 17:00
  • I tried checking the nonce with "check_ajax_referer() and by looking at $_REQUEST['wp_rest'} and no it does not appear to be set. Not clear how 'wp-api' would help I have it enqued and it should help with the part where I need to access USER info, but I don't see how that help with my custom endpoints. It appears to be concerned with the standard WP stuff, users, post, comments etc..
    – dsj
    Oct 1 '20 at 17:16
  • 1
    I'm actually referring to tools like the Network tab in Chrome Developer Tools.. details here. Try it out.
    – Sally CJ
    Oct 1 '20 at 17:32
  • I'm using Safari, but have similar set of tools. I went back and rechecked, and realized I was confusing error messages. It is actually sending the nonce on POSTS but not GETs. Important clue...thanks for the suggestion. (so my POSTS work)
    – dsj
    Oct 1 '20 at 18:44
0

The issue was I overrode the Backbone.sync method only in Backbone.Model. When Backbone fetches the initial data (GET) it is using the sync method in Backbone.collections. So I need to override the sync in Backbone.Collections:

app.Collection = Backbone.Collection.extend({   
    sync: function( method, model, options ){
        return Backbone.sync(method, this, jQuery.extend( options, {
            beforeSend: function (xhr) {
            xhr.setRequestHeader( 'X-WP-NONCE', POST_SUBMITTER.nonce );
            },
        } ));   
    },  
 }) ; 

With that the nonce is sent with the GET request as well as POST, PUT and DELETE.

You might be able to override Backbone.sync and thus cover both Model and Collection at once.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.