diff --git a/src/wp-admin/includes/user.php b/src/wp-admin/includes/user.php index 5b6c6ffd8b..05dd852f2f 100644 --- a/src/wp-admin/includes/user.php +++ b/src/wp-admin/includes/user.php @@ -612,6 +612,7 @@ Please click the following link to activate your user account: * Checks if the Authorize Application Password request is valid. * * @since 5.6.0 + * @since 6.2.0 Allow insecure HTTP connections for the local environment. * * @param array $request { * The array of request data. All arguments are optional and may be empty. @@ -625,12 +626,13 @@ Please click the following link to activate your user account: * @return true|WP_Error True if the request is valid, a WP_Error object contains errors if not. */ function wp_is_authorize_application_password_request_valid( $request, $user ) { - $error = new WP_Error(); + $error = new WP_Error(); + $is_local = 'local' === wp_get_environment_type(); if ( ! empty( $request['success_url'] ) ) { $scheme = wp_parse_url( $request['success_url'], PHP_URL_SCHEME ); - if ( 'http' === $scheme ) { + if ( 'http' === $scheme && ! $is_local ) { $error->add( 'invalid_redirect_scheme', __( 'The success URL must be served over a secure connection.' ) @@ -641,7 +643,7 @@ function wp_is_authorize_application_password_request_valid( $request, $user ) { if ( ! empty( $request['reject_url'] ) ) { $scheme = wp_parse_url( $request['reject_url'], PHP_URL_SCHEME ); - if ( 'http' === $scheme ) { + if ( 'http' === $scheme && ! $is_local ) { $error->add( 'invalid_redirect_scheme', __( 'The rejection URL must be served over a secure connection.' ) diff --git a/tests/phpunit/tests/admin/includesUser.php b/tests/phpunit/tests/admin/includesUser.php index 0b590377e9..c4f6f0c9c1 100644 --- a/tests/phpunit/tests/admin/includesUser.php +++ b/tests/phpunit/tests/admin/includesUser.php @@ -7,52 +7,82 @@ class Tests_Admin_IncludesUser extends WP_UnitTestCase { /** - * @ticket 42790 + * Test redirect URLs for application password authorization requests. + * + * @ticket 42790 + * @ticket 52617 + * + * @covers ::wp_is_authorize_application_password_request_valid + * * @dataProvider data_is_authorize_application_password_request_valid - * @param array $request The request data to validate. - * @param string $error_code The expected error code, empty if no error. + * + * @param array $request The request data to validate. + * @param string $expected_error_code The expected error code, empty if no error is expected. + * @param string $env The environment type. Defaults to 'production'. */ - public function test_is_authorize_application_password_request_valid( $request, $error_code ) { - $error = wp_is_authorize_application_password_request_valid( $request, get_userdata( 1 ) ); + public function test_is_authorize_application_password_request_valid( $request, $expected_error_code, $env = 'production' ) { + putenv( "WP_ENVIRONMENT_TYPE=$env" ); - if ( $error_code ) { - $this->assertWPError( $error ); - $this->assertSame( $error_code, $error->get_error_code() ); + $actual = wp_is_authorize_application_password_request_valid( $request, get_userdata( 1 ) ); + + putenv( 'WP_ENVIRONMENT_TYPE' ); + + if ( $expected_error_code ) { + $this->assertWPError( $actual, 'A WP_Error object is expected.' ); + $this->assertSame( $expected_error_code, $actual->get_error_code(), 'Unexpected error code.' ); } else { - $this->assertNotWPError( $error ); + $this->assertNotWPError( $actual, 'A WP_Error object is not expected.' ); } } public function data_is_authorize_application_password_request_valid() { - return array( - array( - array(), - '', - ), - array( - array( 'success_url' => 'http://example.org' ), - 'invalid_redirect_scheme', - ), - array( - array( 'reject_url' => 'http://example.org' ), - 'invalid_redirect_scheme', - ), - array( - array( 'success_url' => 'https://example.org' ), - '', - ), - array( - array( 'reject_url' => 'https://example.org' ), - '', - ), - array( - array( 'success_url' => 'wordpress://example' ), - '', - ), - array( - array( 'reject_url' => 'wordpress://example' ), - '', - ), - ); + $environment_types = array( 'local', 'development', 'staging', 'production' ); + + $datasets = array(); + foreach ( $environment_types as $environment_type ) { + $datasets[ $environment_type . ' and no request arguments' ] = array( + 'request' => array(), + 'expected_error_code' => '', + 'env' => $environment_type, + ); + + $datasets[ $environment_type . ' and a "https" scheme "success_url"' ] = array( + 'request' => array( 'success_url' => 'https://example.org' ), + 'expected_error_code' => '', + 'env' => $environment_type, + ); + + $datasets[ $environment_type . ' and a "https" scheme "reject_url"' ] = array( + 'request' => array( 'reject_url' => 'https://example.org' ), + 'expected_error_code' => '', + 'env' => $environment_type, + ); + + $datasets[ $environment_type . ' and an app scheme "success_url"' ] = array( + 'request' => array( 'success_url' => 'wordpress://example' ), + 'expected_error_code' => '', + 'env' => $environment_type, + ); + + $datasets[ $environment_type . ' and an app scheme "reject_url"' ] = array( + 'request' => array( 'reject_url' => 'wordpress://example' ), + 'expected_error_code' => '', + 'env' => $environment_type, + ); + + $datasets[ $environment_type . ' and a "http" scheme "success_url"' ] = array( + 'request' => array( 'success_url' => 'http://example.org' ), + 'expected_error_code' => 'local' === $environment_type ? '' : 'invalid_redirect_scheme', + 'env' => $environment_type, + ); + + $datasets[ $environment_type . ' and a "http" scheme "reject_url"' ] = array( + 'request' => array( 'reject_url' => 'http://example.org' ), + 'expected_error_code' => 'local' === $environment_type ? '' : 'invalid_redirect_scheme', + 'env' => $environment_type, + ); + } + + return $datasets; } }