WP REST API nonce authentication

Nonce API REST validation with the WordPress 4.4 infrastructure.

It’s part of Core

The WordPrss REST API is part of WordPress core since version 4.4.
Without installing and activating the WP REST API plugin what I will get, as a developer, is merely an infrastructure.
This means no endpoints, no authentication handling and so on.
Still this is a mighty possibility to tap in and with an implementation that thinks ahead it’s worth putting some effort into code that harnesses this power now.
I’ve been recently developing the “I’d like this” plugin for research and experimentation purposes and ran into the need for a nonce validation full speed ahead.

Nonces – the wrong way

Since the plugin will rely on an AJAX call to trigger the creation of a comment related to a post I’ve baked some simple authentication method in the plugin to add a measure of security to it: requests should come from the site front-end only and WordPress relies on the nonce mechanic to deal with that.
In very simple terms I’m localizing a JavaScript array on the site front-end that contains a nonce specific to the action

 * Returns an array containing the data to be localized.
 * @return array
public function get_data()
    $nonce = wp_create_nonce('button-click');
    return array(
        'endpoints' => array(
            'domain' => home_url(),
            'button_click' => array(
                'url' => rest_get_url_prefix() . '/idlikethis/v1/button-click/',
                'nonce' => $nonce,

and when handling a click request I was trying to verify the nonce with this method, auth is where the generated nonce is stored

 * Verifies an action is authorized.
 * @param WP_REST_Request $request The request representation.
 * @param string $action The action the auth refers to.
 * @return bool
public function verify_auth(WP_REST_Request $request, $action)
    if (!is_string($action)) {
        throw new InvalidArgumentException('Action must be a string');

    $this->action = $action;

    $auth = $request->get_param('auth');
    if (empty($auth)) {
        return false;

    return wp_verify_nonce($auth, $action);

And this was passing some times and failing others.
The nonce verification system relies on the current user id to work and having the code above pass would require to sync the nonce verification to the current user ID; by default the user ID for any REST request will be 0: the nonce verification will pass any time the request is made from the front-end when no user is logged in and fail if the user is logged in (user ID not 0).

Nonces – the right way

The nonce system the REST API infrastructure implements relies on the user authentication cookie to work but will require an header to be set for the request.
The localized data provider I’ve not modified.
That same nonce value will have to be assigned to the X-WP-Nonce header of the request.
In Backbone terms this means that the model implementation will modify the sync method implementation to set the header before the request is sent; in even more specific terms for the “I’d like this” project the code of the vote caster class is the following

var data = require('localized-data'),
    Backbone = require('backbone');

module.exports = Backbone.Model.extend({

    url: data.endpoints.button_click.url,

    sync: function () {

        Backbone.sync('create', this, {
            beforeSend: function (xhr) {
                xhr.setRequestHeader('X-WP-NONCE', data.endpoints.nonce);



Nothing incredible but still a useful thing to know to work with the REST API infrastructure now.

Read the documentation

And all of this can be found in the REST API documentation in greater detail.

2 thoughts on “WP REST API nonce authentication

  1. Great info! I’m curious if you’ve run into anything like I am currently dealing with:

    I have created an endpoint that authenticates a user without requiring the page to refresh within my Angular application… I generate my nonce when the page loads without the user being logged in, then they authenticate, so I don’t believe that nonce is valid, but I can’t appear to “update” the nonce. When I reload the page all works fine, but I’d prefer to not have to reload the page as it’s a single page application… any thoughts?

    1. With the nonce being generated when the user is not logged in it will always authenticate the user as ID 0 hence severely limiting his power.
      I guess the authentication will happen in the context of an AJAX request where a PHP script will sign in the user (and set auth cookies) and return some notification of success; in that first response I’d bundle the user new nonce recreating the nonce after the user has been logged kinda like this:

      $user = wp_signon($credentials);
      if(is_wp_error($user)) {
          'message' => __('Logged In!'),
          'user_id' => $user->ID,
          'nonce' => wp_create_nonce('my-angular-app'),

      And in the JS response handler I’d look for that nonce value in a successful response to update the value of the hidden input field where the nonce is stored on the page.

I appreciate your input