WordPress.org

Make WordPress Core

Ticket #35662: 35662.7.diff

File 35662.7.diff, 4.8 KB (added by markjaquith, 3 years ago)
  • src/wp-includes/rest-api/class-wp-rest-server.php

    diff --git a/src/wp-includes/rest-api/class-wp-rest-server.php b/src/wp-includes/rest-api/class-wp-rest-server.php
    index 12e4086..4f9abcf 100644
    a b class WP_REST_Server { 
    260260                 */
    261261                $enabled = apply_filters( 'rest_enabled', true );
    262262
     263                if ( $enabled ) {
     264                        $nonce = null;
     265
     266                        // Find existing nonce.
     267                        if ( isset( $_REQUEST['_wpnonce'] ) ) {
     268                                $nonce = $_REQUEST['_wpnonce'];
     269                        } elseif ( isset( $_SERVER['HTTP_X_WP_NONCE'] ) ) {
     270                                $nonce = $_SERVER['HTTP_X_WP_NONCE'];
     271                        }
     272
     273                        // Check the nonce.
     274                        $nonce_status = wp_verify_nonce( $nonce, 'wp_rest' );
     275
     276                        /**
     277                         * Filter whether the REST API should send a refreshed nonce header in responses to
     278                         * authenticated requests that include a valid nonce.
     279                         *
     280                         * @since 4.5.0
     281                         *
     282                         * @param bool $rest_send_refreshed_nonce Whether to send a refreshed nonce in the response headers.
     283                         *                                        Defaults to true if the user is logged in and the the
     284                         *                                        existing request nonce is valid and expires soon.
     285                         * @param bool $nonce_status The status of the nonce
     286                         */
     287                        $rest_send_refreshed_nonce = apply_filters( 'rest_send_refreshed_nonce', is_user_logged_in() && 2 === $nonce_status, $nonce_status );
     288                        if ( $rest_send_refreshed_nonce ) {
     289                                $this->send_header( 'X-WP-Nonce', wp_create_nonce( 'wp_rest' ) );
     290                        }
     291                }
     292
    263293                /**
    264294                 * Filters whether jsonp is enabled.
    265295                 *
  • tests/phpunit/tests/rest-api/rest-server.php

    diff --git a/tests/phpunit/tests/rest-api/rest-server.php b/tests/phpunit/tests/rest-api/rest-server.php
    index 8a53360..5b4ddfd 100644
    a b class Tests_REST_Server extends WP_Test_REST_TestCase { 
    882882        public function filter_wp_rest_server_class() {
    883883                return 'Spy_REST_Server';
    884884        }
     885
     886        /**
     887         * Testing that the headers are not set for anonymous users.
     888         *
     889         * @ticket 35662
     890         */
     891        function test_rest_send_refreshed_nonce_anonymous_user() {
     892                // Make the request.
     893                $headers = $this->helper_make_request_and_return_headers_for_rest_send_refreshed_nonce_tests();
     894
     895                // Run the assertions.
     896                $this->assertArrayNotHasKey( 'X-WP-Nonce', $headers );
     897        }
     898
     899        /**
     900         * Testing the rest_send_refreshed_nonce filter.
     901         *
     902         * If the nonce is valid and the user is logged in, we're filtering as false so the header is not sent
     903         * and vice-versa for the opposite setup.
     904         *
     905         * @ticket 35662
     906         *
     907         * @dataProvider data_rest_send_refreshed_nonce_filtered
     908         *
     909         * @param bool   $has_logged_in_user Will there be a logged in user for this test.
     910         * @param string $filter_callback    The callback to be used by the add_filter.
     911         * @param bool   $has_key            Should the X-WP-Nonce key be in the sent_headers array.
     912         */
     913        function test_rest_send_refreshed_nonce_filtered( $has_logged_in_user, $filter_callback, $has_key ) {
     914
     915                if ( true === $has_logged_in_user ) {
     916                        // Creat and set the current user.
     917                        $this->helper_setup_user_for_rest_send_refreshed_nonce_tests();
     918                }
     919
     920                // Make the request.
     921                add_filter( 'rest_send_refreshed_nonce', $filter_callback );
     922
     923                $headers = $this->helper_make_request_and_return_headers_for_rest_send_refreshed_nonce_tests();
     924
     925                remove_filter( 'rest_send_refreshed_nonce', $filter_callback );
     926
     927                // Run the assertions.
     928                if ( true === $has_key ) {
     929                        $this->assertArrayHasKey( 'X-WP-Nonce', $headers );
     930                } else {
     931                        $this->assertArrayNotHasKey( 'X-WP-Nonce', $headers );
     932                }
     933        }
     934
     935        /**
     936         * Dataprovider to automate the filter tests.
     937         *
     938         * @return array {
     939         *     @type array {
     940         *         @type bool   $has_logged_in_user Are we registering a user for the test.
     941         *         @type string $filter_callback   The callback passed to the filter.
     942         *         @type bool   $has_key           Should the X-WP-Nonce key be in the sent_headers array.
     943         *     }
     944         * }
     945         */
     946        function data_rest_send_refreshed_nonce_filtered() {
     947                return array(
     948                        array( false, '__return_true', true ),
     949                        array( true, '__return_false', false ),
     950                );
     951        }
     952
     953        /**
     954         * Helper to setup a users for the rest_send_refreshed_nonce related tests.
     955         */
     956        function helper_setup_user_for_rest_send_refreshed_nonce_tests() {
     957                // Create and set the current user.
     958                $author = self::factory()->user->create( array( 'role' => 'author' ) );
     959                wp_set_current_user( $author );
     960        }
     961
     962        /**
     963         * Helper to make the request and get the headers for the rest_send_refreshed_nonce related tests.
     964         *
     965         * @return array
     966         */
     967        function helper_make_request_and_return_headers_for_rest_send_refreshed_nonce_tests() {
     968                $request = new WP_REST_Request( 'GET', '/', array() );
     969                $result  = $this->server->serve_request( '/' );
     970
     971                return $this->server->sent_headers;
     972        }
    885973}