TodoMVC with WordPress and intercooler.js 04

Securing the communications.

Nonces

WordPress packs a pervasive library dedicated to security to authenticate the source of a request be it made via a traditional HTML request or an AJAX one.
The term “nonce” means “number used once”; this is not exactly the case in WordPress: a nonce number will remain valid for 12 hours plus or minus filter modifications.
This means that, in an application unmodified by filters, using the same “nonce” multiple times is ok.
With this in mind I will modify the TodoMVC port based around intercooler.js and a WordPress backend to secure its communications.

Markup refresh

Looking at the flow of the theme each successful request will give an HTML response generated by the todomvc_the_list function defined in the functions/output.php file.
That HTML will be used by intercooler.js to replace the content of the #todo-list element on the page.
This means that anything that’s inside the #todo-list element will be regenerated on each request.
Since I do not want to go crazy with security I will be content to have a single nonce powering the whole application and will store it, as customary to WordPress, in an hidden input.

Modifying the index

With little fantasy I’ve modified the markup of the index.php file to read (an extract)

<!--more markup here-->

<section class="todoapp">
    <header class="header">
        <h1>todos</h1>
        <input class="new-todo" placeholder="What needs to be done?" autofocus="" ic-post-to="/tasks" name="task-title"
               ic-target="#todo-list">
    </header>

    <?php wp_nonce_field( 'todo-mvc' ) ?>

    <div id="todo-list" <?php echo todomvc_get_display() ?>>
        <?php todomvc_the_list() ?>
    </div>
</section>

<!--more markup here-->

Including the nonce

The application, a theme in WordPress terms, uses intercooler.js to send and handle AJAX requests and this leaves me two options:

  1. use the ic-include attribute to specify, in any component of the page that’s triggering a request of sort, to include the nonce field in the data
  2. tap into the JavaScript part of intercooler.js to add the nonce value to each request data hash

Spoiler: I took the second option.

Routes and verification

Since I’m using the wp-routes plugin to define and handle the application API I’ve added the nonce verification in any route before any request is made.
To make a PHP code example the route in charge of deleting a todo item now reads

// file functions/routes.php

// Delete a todo
respond( 'DELETE', '/tasks/[i:id]', function ( $request, $response ) {
    parse_str( file_get_contents( 'php://input' ), $request_vars );
    if ( ! wp_verify_nonce( $request_vars['_wpnonce'], 'todo-mvc' ) ) {
        return;
    }
    if ( ! get_post( $request->id ) ) {
        return;
    }
    $id = wp_delete_post( $request->id );
    if ( $id === false ) {
        return;
    }

    todomvc_maybe_hide( $response );
    todomvc_the_list( todomvc_current_view() );
} );

JavaScript manipulation of data

Following along the intercooler.js JavaScript reference I’ve modified the small JavaScript part of the theme

/*global jQuery:false */
jQuery( document ).ready( function ( $ ) {
    'use strict';

    // ...code not changed 

    $( 'section.todoapp' ).on( 'beforeSend.ic', function ( evt, elt, data, settings) {
        var nonce = '&_wpnonce=' + $( '#_wpnonce' ).val()
        switch ( settings.type ) {
            case 'GET'    :
                settings.url = settings.url + nonce;
                break;
            default :
                settings.data = data + nonce;
                data = data + nonce;
                break;
        }
    } );

    Intercooler.defaultTransition( 'none' );
} );

What’s of note here:

  1. I’m listening on the element that contains the nonce hidden input field and the text input used to insert new tasks (section.todo).
  2. I’m modifying both the data hash and the settings.data hash for PUT, POST and DELETE requests and modifying just the URL for GET requests.

In the functions/routes.php I’m checking each request against the nonce to make sure it’s the theme that’s making the requests.
A further line of defense could be to check for specific intercooler.js headers but that seemed redundant.

Next

The project had a purely experimental purpose and that’s satisfied on my side.
I’ve begun fiddling around with intercooler.js in a client project and so far found it almost too easy to work with to believe.
The code of the theme is on GitHub.

I appreciate your input