Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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" );
          });
  }
like image 466
Tom Ford Avatar asked Mar 14 '26 06:03

Tom Ford


1 Answers

Hey so I have been having the same issues getting this work as well, but after a long day of troubleshooting, the fix to this was actually fairly simple and easy to overlook.

axios.put(wpApiSettings.root + "wp/v2/posts/" + post.id,
    { headers: {'X-WP-Nonce':wpApiSettings.nonce}},
    { title: 'test' })

should be

axios.put(wpApiSettings.root + "wp/v2/posts/" + post.id,
    { title: 'test' }, 
    { headers: {'X-WP-Nonce':wpApiSettings.nonce}})

I can't believe I misssed this, but the headers should be in an object that is always the third parameter of the PUT or POST functions in Axios. If you don't have any data you want to pass as the second parameter you could also use throw an empty string ''.

I didn't realize the parameter positions mattered, but in the Axios documentation, the prototype is axios.put(url[, data[, config]]). I got it figured out with a friend when we realized that we were putting the header object into the request body instead of actually putting it into the header.

Hope this helps!

like image 89
Andy Nguyen Avatar answered Mar 15 '26 18:03

Andy Nguyen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!