WordPress.org

Make WordPress Core

Changeset 49334


Ignore:
Timestamp:
10/27/2020 06:30:03 PM (3 months ago)
Author:
TimothyBlynJacobs
Message:

Site Health, App Passwords: Test if the Authorization header is populated correctly.

App Passwords rely on the Authorization header to transport the Basic Auth credentials. For Apache web servers, WordPress automatically includes a RewriteRule to populate the value for servers running in CGI or FastCGI that wouldn't ordinarily populate the value.

This tests if the header is being filled with the expected values. For Apache users, we direct the user to visit the Permalinks settings to flush their permalinks. For all other users, we direct them to a help document on developer.wordpress.org.

Props Clorith, marybaum, TimothyBlynJacobs.
Fixes #51638.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/js/_enqueues/admin/site-health.js

    r49154 r49334  
    213213                if ( 'undefined' !== typeof( this.has_rest ) && this.has_rest ) {
    214214                    wp.apiRequest( {
    215                         url: this.test
     215                        url: this.test,
     216                        headers: this.headers
    216217                    } )
    217218                        .done( function( response ) {
  • trunk/src/wp-admin/includes/class-wp-site-health.php

    r49266 r49334  
    136136                        'has_rest'  => ( isset( $test['has_rest'] ) ? $test['has_rest'] : false ),
    137137                        'completed' => false,
     138                        'headers'   => isset( $test['headers'] ) ? $test['headers'] : array(),
    138139                    );
    139140                }
     
    20742075            );
    20752076            return $result;
     2077        }
     2078
     2079        return $result;
     2080    }
     2081
     2082    /**
     2083     * Tests if the Authorization header has the expected values.
     2084     *
     2085     * @since 5.6.0
     2086     *
     2087     * @return array
     2088     */
     2089    public function get_test_authorization_header() {
     2090        $result = array(
     2091            'label'       => __( 'The Authorization header is working as expected.' ),
     2092            'status'      => 'good',
     2093            'badge'       => array(
     2094                'label' => __( 'Security' ),
     2095                'color' => 'blue',
     2096            ),
     2097            'description' => sprintf(
     2098                '<p>%s</p>',
     2099                __( 'The Authorization header comes from the third-party applications you approve. Without it, those apps cannot connect to your site.' )
     2100            ),
     2101            'actions'     => '',
     2102            'test'        => 'authorization_header',
     2103        );
     2104
     2105        if ( ! isset( $_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'] ) ) {
     2106            $result['label'] = __( 'The authorization header is missing.' );
     2107        } elseif ( 'user' !== $_SERVER['PHP_AUTH_USER'] || 'pwd' !== $_SERVER['PHP_AUTH_PW'] ) {
     2108            $result['label'] = __( 'The authorization header is invalid.' );
     2109        } else {
     2110            return $result;
     2111        }
     2112
     2113        $result['status'] = 'recommended';
     2114
     2115        if ( ! function_exists( 'got_mod_rewrite' ) ) {
     2116            require_once ABSPATH . 'wp-admin/includes/misc.php';
     2117        }
     2118
     2119        if ( got_mod_rewrite() ) {
     2120            $result['actions'] .= sprintf(
     2121                '<p><a href="%s">%s</a></p>',
     2122                esc_url( admin_url( 'options-permalink.php' ) ),
     2123                __( 'Flush permalinks' )
     2124            );
     2125        } else {
     2126            $result['actions'] .= sprintf(
     2127                '<p><a href="%s" target="_blank" rel="noopener">%s <span class="screen-reader-text">%s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
     2128                'https://developer.wordpress.org/rest-api/frequently-asked-questions/#why-is-authentication-not-working',
     2129                __( 'Learn how to configure the Authorization header.' ),
     2130                /* translators: Accessibility text. */
     2131                __( '(opens in a new tab)' )
     2132            );
    20762133        }
    20772134
     
    21782235                    'async_direct_test' => array( WP_Site_Health::get_instance(), 'get_test_loopback_requests' ),
    21792236                ),
     2237                'authorization_header' => array(
     2238                    'label'     => __( 'Authorization header' ),
     2239                    'test'      => rest_url( 'wp-site-health/v1/tests/authorization-header' ),
     2240                    'has_rest'  => true,
     2241                    'headers'   => array( 'Authorization' => 'Basic ' . base64_encode( 'user:pwd' ) ),
     2242                    'skip_cron' => true,
     2243                ),
    21802244            ),
    21812245        );
     
    22042268         * @since 5.2.0
    22052269         * @since 5.6.0 Added the `async_direct_test` array key.
     2270         *              Added the `skip_cron` array key.
    22062271         *
    22072272         * @param array $test_type {
     
    22182283         *                                           to be called to perform an async test.
    22192284         *         @type boolean  $has_rest          Optional. Denote if `$test` has a REST API endpoint.
     2285         *         @type boolean  $skip_cron         Whether to skip this test when running as cron.
    22202286         *         @type callable $async_direct_test A manner of directly calling the test marked as asynchronous,
    22212287         *                                           as the scheduled event can not authenticate, and endpoints
     
    25582624
    25592625        foreach ( $tests['async'] as $test ) {
     2626            if ( ! empty( $test['skip_cron'] ) ) {
     2627                continue;
     2628            }
     2629
    25602630            // Local endpoints may require authentication, so asynchronous tests can pass a direct test runner as well.
    25612631            if ( ! empty( $test['async_direct_test'] ) && is_callable( $test['async_direct_test'] ) ) {
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-site-health-controller.php

    r49225 r49334  
    9999                    'permission_callback' => function () {
    100100                        return $this->validate_request_permission( 'dotorg_communication' );
     101                    },
     102                ),
     103                'schema' => array( $this, 'get_public_item_schema' ),
     104            )
     105        );
     106
     107        register_rest_route(
     108            $this->namespace,
     109            sprintf(
     110                '/%s/%s',
     111                $this->rest_base,
     112                'authorization-header'
     113            ),
     114            array(
     115                array(
     116                    'methods'             => 'GET',
     117                    'callback'            => array( $this, 'test_authorization_header' ),
     118                    'permission_callback' => function () {
     119                        return $this->validate_request_permission( 'authorization_header' );
    101120                    },
    102121                ),
     
    176195    public function test_loopback_requests() {
    177196        return $this->site_health->get_test_loopback_requests();
     197    }
     198
     199    /**
     200     * Checks that the authorization header is valid.
     201     *
     202     * @since 5.6.0
     203     *
     204     * @return array
     205     */
     206    public function test_authorization_header() {
     207        return $this->site_health->get_test_authorization_header();
    178208    }
    179209
  • trunk/tests/phpunit/tests/rest-api/rest-schema-setup.php

    r49154 r49334  
    137137            '/wp-site-health/v1/tests/loopback-requests',
    138138            '/wp-site-health/v1/tests/dotorg-communication',
     139            '/wp-site-health/v1/tests/authorization-header',
    139140            '/wp-site-health/v1/directory-sizes',
    140141        );
Note: See TracChangeset for help on using the changeset viewer.