REST API: Include a refreshed nonce in a `X-WP-Nonce` header when responding to an authenticated request.

Props adamsilverstein, welcher, markjaquith, aidvu.
Fixes #35662.




git-svn-id: https://develop.svn.wordpress.org/trunk@37905 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Rachel Baker 2016-06-29 03:00:54 +00:00
parent e81a5da327
commit 0e6a328782
2 changed files with 98 additions and 4 deletions

View File

@ -548,10 +548,12 @@ function rest_output_link_header() {
*
* @since 4.4.0
*
* @global mixed $wp_rest_auth_cookie
* @global mixed $wp_rest_auth_cookie
* @global WP_REST_Server $wp_rest_server REST server instance.
*
* @param WP_Error|mixed $result Error from another authentication handler, null if we should handle it,
* or another value if not.
* @param WP_Error|mixed $result Error from another authentication handler,
* null if we should handle it, or another value
* if not.
* @return WP_Error|mixed|bool WP_Error if the cookie is invalid, the $result, otherwise true.
*/
function rest_cookie_check_errors( $result ) {
@ -559,7 +561,7 @@ function rest_cookie_check_errors( $result ) {
return $result;
}
global $wp_rest_auth_cookie;
global $wp_rest_auth_cookie, $wp_rest_server;
/*
* Is cookie authentication being used? (If we get an auth
@ -592,6 +594,9 @@ function rest_cookie_check_errors( $result ) {
return new WP_Error( 'rest_cookie_invalid_nonce', __( 'Cookie nonce is invalid' ), array( 'status' => 403 ) );
}
// Send a refreshed nonce in header.
$wp_rest_server->send_header( 'X-WP-Nonce', wp_create_nonce( 'wp_rest' ) );
return true;
}

View File

@ -23,6 +23,7 @@ class Tests_REST_Server extends WP_Test_REST_TestCase {
public function tearDown() {
// Remove our temporary spy server
$GLOBALS['wp_rest_server'] = null;
unset( $_REQUEST['_wpnonce'] );
parent::tearDown();
}
@ -893,4 +894,92 @@ class Tests_REST_Server extends WP_Test_REST_TestCase {
public function filter_wp_rest_server_class() {
return 'Spy_REST_Server';
}
/**
* Refreshed nonce should not be present in header when an invalid nonce is passed for logged in user.
*
* @ticket 35662
*/
public function test_rest_send_refreshed_nonce_invalid_nonce() {
$this->helper_setup_user_for_rest_send_refreshed_nonce_tests();
$_REQUEST['_wpnonce'] = 'random invalid nonce';
$headers = $this->helper_make_request_and_return_headers_for_rest_send_refreshed_nonce_tests();
$this->assertArrayNotHasKey( 'X-WP-Nonce', $headers );
}
/**
* Refreshed nonce should be present in header when a valid nonce is
* passed for logged in/anonymous user and not present when nonce is not
* passed.
*
* @ticket 35662
*
* @dataProvider data_rest_send_refreshed_nonce
*
* @param bool $has_logged_in_user Will there be a logged in user for this test.
* @param bool $has_nonce Are we passing the nonce.
*/
public function test_rest_send_refreshed_nonce( $has_logged_in_user, $has_nonce ) {
if ( true === $has_logged_in_user ) {
$this->helper_setup_user_for_rest_send_refreshed_nonce_tests();
}
if ( $has_nonce ) {
$_REQUEST['_wpnonce'] = wp_create_nonce( 'wp_rest' );
}
$headers = $this->helper_make_request_and_return_headers_for_rest_send_refreshed_nonce_tests();
if ( $has_nonce ) {
$this->assertArrayHasKey( 'X-WP-Nonce', $headers );
} else {
$this->assertArrayNotHasKey( 'X-WP-Nonce', $headers );
}
}
/**
* @return array {
* @type array {
* @type bool $has_logged_in_user Are we registering a user for the test.
* @type bool $has_nonce Is the nonce passed.
* }
* }
*/
function data_rest_send_refreshed_nonce() {
return array(
array( true, true ),
array( true, false ),
array( false, true ),
array( false, false ),
);
}
/**
* Helper to setup a users and auth cookie global for the
* rest_send_refreshed_nonce related tests.
*/
protected function helper_setup_user_for_rest_send_refreshed_nonce_tests() {
$author = self::factory()->user->create( array( 'role' => 'author' ) );
wp_set_current_user( $author );
global $wp_rest_auth_cookie;
$wp_rest_auth_cookie = true;
}
/**
* Helper to make the request and get the headers for the
* rest_send_refreshed_nonce related tests.
*
* @return array
*/
protected function helper_make_request_and_return_headers_for_rest_send_refreshed_nonce_tests() {
$request = new WP_REST_Request( 'GET', '/', array() );
$result = $this->server->serve_request( '/' );
return $this->server->sent_headers;
}
}