The WordPress REST API is quite a feature, but it can be a struggle to deal with authentication. One option is Basic Auth. But can we leverage the built-in cookie authentication?
If you look at rest_cookie_check_errors(), you’ll see where it’s checking for an authentication cookie and valid nonce. Using WP-CLI, we can carefully piece together a cURL command that passes those values appropriately. Remember, cookies and nonces have a limited lifetime, so be sure to generate new commands as time goes by.
Example
Run wp-cli command
$ wp curl-rest --user=admin
Output:
curl -H 'X-WP-NONCE: ooO0o00o00' --cookie \
'wordpress_logged_in_wwWwwwWwwwWWwwwwwWwwwWWwwWWWwwwww=admin|xxxxxxxxxx|YYyyYyyyyYyYyYYYYYyyyYYyyyyYyyYYyyyyyyYYyyY|zZzzzzzZzZzzzzzZZzzzZzzzZzzZZzzzzzzZZzZzzzZZZzzZzZzzzZZzzzzzZzzz' \
'http://local.wordpress.local/wp-json/wp/v2/settings'
Run curl command
$ curl -H 'X-WP-NONCE: ooO0o00o00' --cookie \
'wordpress_logged_in_wwWwwwWwwwWWwwwwwWwwwWWwwWWWwwwww=admin|xxxxxxxxxx|YYyyYyyyyYyYyYYYYYyyyYYyyyyYyyYYyyyyyyYYyyY|zZzzzzzZzZzzzzzZZzzzZzzzZzzZZzzzzzzZZzZzzzZZZzzZzZzzzZZzzzzzZzzz' \
'http://local.wordpress.local/wp-json/wp/v2/settings'
Output:
(prettified, I recommend the jq
command line tool)
{
"title": "wordpress.local",
"description": "Just another WordPress site",
"url": "http://local.wordpress.local",
"email": "[email protected]",
"timezone": "",
"date_format": "F j, Y",
"time_format": "g:i a",
"start_of_week": 1,
"language": "",
"use_smilies": true,
"default_category": 1,
"default_post_format": "0",
"posts_per_page": 10,
"default_ping_status": "open",
"default_comment_status": "open"
}
<?php | |
if ( !defined( 'WP_CLI' ) ) return; | |
/** | |
*/ | |
class trepmal_cURL_REST extends WP_CLI_Command { | |
/** | |
* Generate cURL command for REST API | |
* | |
* ## EXAMPLES | |
* | |
* # Generare command for fetching all administrators | |
* $ wp curl-rest –user=1 wp/v2/users?role=administrator | |
* | |
* @synopsis [<route>] –user=<user> | |
* | |
*/ | |
function __invoke( $args, $assoc_args ) { | |
$args = wp_parse_args( [ | |
0 => 'wp/v2/settings' | |
], $args ); | |
list( $route ) = $args; | |
$route = trim( $route, '/'); | |
if ( substr( $route, 0, 5 ) !== 'wp/v2' ) { | |
$route = "wp/v2/$route"; | |
} | |
if ( ! $user_id = get_current_user_id() ) { | |
WP_CLI::error( 'Please pass –user' ); | |
} | |
$expiration = time() + DAY_IN_SECONDS; | |
$manager = WP_Session_Tokens::get_instance( $user_id ); | |
$token = $manager->create( $expiration ); | |
$logged_in_cookie = wp_generate_auth_cookie( $user_id, $expiration, 'logged_in', $token ); | |
$_COOKIE[ LOGGED_IN_COOKIE ] = $logged_in_cookie; // for nonce creation | |
$url = rest_url( $route ); | |
$nonce = wp_create_nonce( 'wp_rest' ); | |
$cookie = LOGGED_IN_COOKIE . "={$logged_in_cookie}"; | |
$nonce_header = "X-WP-NONCE: $nonce"; | |
$curl = "curl -H '$nonce_header' –cookie '$cookie' '$url'"; | |
$split_curl = _split_str_by_whitespace( $curl, 100 ); | |
$curl = implode( "\\\n ", $split_curl ); | |
WP_CLI::line( $curl ); | |
} | |
} | |
WP_CLI::add_command( 'curl-rest', 'trepmal_cURL_REST' ); |