App Passwords: Introduce introspection endpoint.

This introduces a new endpoint, `wp/v2/users/me/application-passwords/introspect`, that will return details about the App Password being used to authenticate the current request. This allows for an application to disambiguate between multiple installations of their application which would all share the same `app_id`.

Props xkon, peterwilsoncc, TimothyBlynJacobs.
Fixes #52275.

Built from https://develop.svn.wordpress.org/trunk@50065


git-svn-id: http://core.svn.wordpress.org/trunk@49766 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
TimothyBlynJacobs 2021-01-29 00:07:02 +00:00
parent 0000f669b6
commit cd6238947e
4 changed files with 108 additions and 4 deletions

View File

@ -280,7 +280,7 @@ add_action( 'auth_cookie_bad_username', 'rest_cookie_collect_status' );
add_action( 'auth_cookie_bad_hash', 'rest_cookie_collect_status' );
add_action( 'auth_cookie_valid', 'rest_cookie_collect_status' );
add_action( 'application_password_failed_authentication', 'rest_application_password_collect_status' );
add_action( 'application_password_did_authenticate', 'rest_application_password_collect_status' );
add_action( 'application_password_did_authenticate', 'rest_application_password_collect_status', 10, 2 );
add_filter( 'rest_authentication_errors', 'rest_application_password_check_errors', 90 );
add_filter( 'rest_authentication_errors', 'rest_cookie_check_errors', 100 );

View File

@ -1048,15 +1048,39 @@ function rest_cookie_collect_status() {
* Collects the status of authenticating with an application password.
*
* @since 5.6.0
* @since 5.7.0 Added the `$app_password` parameter.
*
* @global WP_User|WP_Error|null $wp_rest_application_password_status
* @global string|null $wp_rest_application_password_uuid
*
* @param WP_Error $user_or_error The authenticated user or error instance.
* @param array $app_password The Application Password used to authenticate.
*/
function rest_application_password_collect_status( $user_or_error ) {
global $wp_rest_application_password_status;
function rest_application_password_collect_status( $user_or_error, $app_password = array() ) {
global $wp_rest_application_password_status, $wp_rest_application_password_uuid;
$wp_rest_application_password_status = $user_or_error;
if ( empty( $app_password['uuid'] ) ) {
$wp_rest_application_password_uuid = null;
} else {
$wp_rest_application_password_uuid = $app_password['uuid'];
}
}
/**
* Gets the Application Password used for authenticating the request.
*
* @since 5.7.0
*
* @global string|null $wp_rest_application_password_uuid
*
* @return string|null The App Password UUID, or null if Application Passwords was not used.
*/
function rest_get_authenticated_app_password() {
global $wp_rest_application_password_uuid;
return $wp_rest_application_password_uuid;
}
/**

View File

@ -57,6 +57,22 @@ class WP_REST_Application_Passwords_Controller extends WP_REST_Controller {
)
);
register_rest_route(
$this->namespace,
'/' . $this->rest_base . '/introspect',
array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_current_item' ),
'permission_callback' => array( $this, 'get_current_item_permissions_check' ),
'args' => array(
'context' => $this->get_context_param( array( 'default' => 'view' ) ),
),
),
'schema' => array( $this, 'get_public_item_schema' ),
)
);
register_rest_route(
$this->namespace,
'/' . $this->rest_base . '/(?P<uuid>[\w\-]+)',
@ -373,6 +389,70 @@ class WP_REST_Application_Passwords_Controller extends WP_REST_Controller {
);
}
/**
* Checks if a given request has access to get the currently used application password.
*
* @since 5.7.0
*
* @param WP_REST_Request $request Full details about the request.
* @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise.
*/
public function get_current_item_permissions_check( $request ) {
$user = $this->get_user( $request );
if ( is_wp_error( $user ) ) {
return $user;
}
if ( get_current_user_id() !== $user->ID ) {
return new WP_Error(
'rest_cannot_introspect_app_password_for_non_authenticated_user',
__( 'The authenticated Application Password can only be introspected for the current user.' ),
array( 'status' => rest_authorization_required_code() )
);
}
return true;
}
/**
* Retrieves the application password being currently used for authentication.
*
* @since 5.7.0
*
* @param WP_REST_Request $request Full details about the request.
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
*/
public function get_current_item( $request ) {
$user = $this->get_user( $request );
if ( is_wp_error( $user ) ) {
return $user;
}
$uuid = rest_get_authenticated_app_password();
if ( ! $uuid ) {
return new WP_Error(
'rest_no_authenticated_app_password',
__( 'Cannot introspect Application Password.' ),
array( 'status' => 404 )
);
}
$password = WP_Application_Passwords::get_user_application_password( $user->ID, $uuid );
if ( ! $password ) {
return new WP_Error(
'rest_application_password_not_found',
__( 'Application password not found.' ),
array( 'status' => 500 )
);
}
return $this->prepare_item_for_response( $password, $request );
}
/**
* Performs a permissions check for the request.
*

View File

@ -13,7 +13,7 @@
*
* @global string $wp_version
*/
$wp_version = '5.7-alpha-50060';
$wp_version = '5.7-alpha-50065';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.