Paulund
2013-07-03 #wordpress

Validate Requests In WordPress Using Nonce

There are loads requests that you can perform in WordPress from either forms or links that will do things like updating database values or deleting posts. If you are deleting a post or updating any value in the database by using a link then you will able to delete a post by typing a URL into the browser, this can dangerous as this can be abused to delete all the posts on your blog. You need a way of verifying a request is valid and to stop duplicate requests from a URL. In WordPress you can verify a request by using a nonce.

What Is A Nonce?

A nonce is used for security reasons to protect the system from unexpected or duplicate requests. This will help protect against the same requests being sent to the database. A nonce is used as a one time token to identify a request on the website, when a request is made it can verify the nonce and you can decide if you will allow the request to proceed. A nonce is generated by an action and a timestamp, this can be used to know when the previously action was requested. Because you know when the previous request was actioned you can decide if to allow it to proceed or block this same request for a certain amount of time. When a action is verified by WordPress it will let you know if the nonce was generated in the last 12 hours or in the last 12 - 24 hours. If a call is not verified WordPress will generate a prompt to make sure the user is certain of proceeding with the next request. Because a request can be done by a form or a link, a nonce value can be added to a form hidden field or as part of a URL.

Working With Nonce In WordPress

WordPress comes with a number of different functions to work with nonces, allowing you to create a new nonce and verify nonces so you can create your own pages and requests securely with a nonce.

  • wp_nonce_ays() - Will allow you to display a are you sure message to confirm the request can take place.
  • wp_nonce_field() - This is used to confirm that a form request came from the current site. When submitting a form request you should always use a nonce so that you can confirm the request came from your site.
  • wp_nonce_url() - Gets the URL attached to the nonce.
  • wp_verify_nonce() - Used to verify the nonce is correct.
  • wp_create_nonce() - Returns a generated nonce based on the current time and an action.
  • check_admin_referer() - Checks to see if the current request was a request from the admin screens.
  • check_ajax_referer() - Verifies that the request was from an ajax request.
  • wp_referer_field() - When you submit a form in the admin area a hidden field will be populated with a none this function will return the value of that hidden field.

Using A Nonce In A Form

When you are creating a new form in WordPress and want to add a nonce hidden field to the form you will need to use the wp_create_nonce() function which requires you to submit an action argument. For example if you want to build custom post meta boxes in WordPress you may want a nonce to allow you to submit this data separately to the post data.

<?php
 
function show_embed_tweet_meta_box() {
    global $post;  
        $meta = get_post_meta($post->ID, 'twitter_embed', true);  
	
    // Use nonce for verification  
	echo '<input type="hidden" name="custom_meta_box_nonce" value="'.wp_create_nonce(basename(__FILE__)).'" />';  
   
   echo '<table class="form-table">';   
        // begin a table row with
        
        echo '<tr>
            <th><label for="twitter_embed">Twitter Embed</label></th>
            <td><textarea name="twitter_embed" id="twitter_embed" cols="60" rows="4">'.$meta.'</textarea>
		        <span class="description">Use to embed tweets on your post.</span></td>
            </tr>';
            
    echo '</table>';
}

This uses the wp_create_nonce() and passes in the base name of the current file as the action basename(FILE). Now we can verify against this action when we process the save action of this data.


if (!wp_verify_nonce($_POST['custom_meta_box_nonce'], basename(__FILE__)))
        return false;

For this we use the function wp_verify_nonce() and pass in the value of the nonce submitted by the form and the action we are verifying it against. If this nonce does not verify then we can return false from this function and not process the rest of the form.


/**************************************************************************
 * Save the meta fields on save of the post
 **************************************************************************/
function save_embed_tweet_meta($post_id) {   
    // verify nonce
    if (!wp_verify_nonce($_POST['custom_meta_box_nonce'], basename(__FILE__)))
        return $post_id;
        
    // check autosave
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
        return $post_id;
        
    // check permissions
    if ('page' == $_POST['post_type']) {
        if (!current_user_can('edit_page', $post_id))
            return $post_id;
        } elseif (!current_user_can('edit_post', $post_id)) {
            return $post_id;
    }  
    
    $old = get_post_meta($post_id, "twitter_embed", true);
    
    $new = $_POST["twitter_embed"];
    
    if ($new && $new != $old) {
        update_post_meta($post_id, "twitter_embed", $new);
    } elseif ('' == $new && $old) {
        delete_post_meta($post_id, "twitter_embed", $old);
    }
}
 
add_action('save_post', 'save_embed_tweet_meta');