wp-json API returns 401 on post edit with React and nonce

Viewed 1807

I am trying to create an admin page in WordPress with React that allows users to manage post content. I have successfully created a delete method in react to work with the API, but I'm having difficulties getting update to work.

// plugin_file.php
add_action('admin_enqueue_scripts', function() {
    wp_localize_script('tfw-js', 'wpApiSettings', [
        'root' => esc_url_raw( rest_url() ),
         'nonce' => wp_create_nonce( 'wp_rest' )
    ]);
});

The code above dumps this object near the bottom of my page

<script type='text/javascript'>
/* <![CDATA[ */
var wpApiSettings = {"root":"http:website.com\/wp-
json\/","nonce":"9eb4c99f2c"};
/* ]]> */
</script>

Here is the delete method that works as intended

deletePost(post) {

    var _this = this;
    this.serverRequest =
          axios
            .delete(wpApiSettings.root + "wp/v2/posts/" + post.id, {
                headers: {'X-WP-Nonce': wpApiSettings.nonce},
            })
            .then(function(result) {
                _this.updatePostList();

            })
  }

However my update method, that uses the same nonce key as delete returns 401 unauthorized. I am unsure if the using the same key is the correct approach, but admin-ajax.php uses the same nonce key so I am guessing it is.

updatePost(post) {
    var _this = this;
    this.serverRequest =
      axios
        .put(wpApiSettings.root + "wp/v2/posts/" + post.id, {
            headers: {'X-WP-Nonce':wpApiSettings.nonce},
            data : {
                title: 'test'
            }
        })
        .then(function(result) {
            _this.updatePostList();
        })
}

Error that is returned

{"code":"rest_cannot_edit","message":"Sorry, you are not allowed to edit this post.","data":{"status":401}}

I would prefer not to use an additional plugin to manage this.

Thanks!

Update:

I got this to work easily using jQuery. Not that big of a deal for me as I am just trying to learn React. Still curious if anyone can fill me in on why axios does not work with the exact same headers & post data. My current solution:

  updatePost(post) {
    var _this = this;

    jQuery.ajax({
        type: "POST",
        url: wpApiSettings.root + "wp/v2/posts/" + post.id,
        data: {
            "title": 'test',
        },
        beforeSend: function( xhr ) {
            xhr.setRequestHeader("X-WP-Nonce", wpApiSettings.nonce);
          }
        }).done(function(response) {
            _this.updatePostList();
        })
        .fail(function() {
            alert( "error" );
          });
  }
2 Answers

You have to

axios.defaults.headers.common['X-WP-Nonce'] = wpApiSettings.nonce; 

before sending a request. Best practice would be to set it at your constructor.

and always remember to use qs to serialize your object before sending it.

Related