1

How can I add authentication for rest_do_request()? I am trying to add Authentication for a WP_REST_Request object using rest_do_request(). This used within a shortcode that is going to be available for both logged in and non logged in users.

I'm thinking that the best way would be to use Basic Authorization. In an example I've setup, I've added the following line commented with "Basic Authorization Attempt" which does not appear to have any effect.

If it's not possible to add authentication, is there another method such as running certain requests as another user or force rest_do_request() to run regardless of permission?


Here is an example of trying to use WP_REST_Request and rest_do_request() with Retrieving orders from WooCommerce:

    $request = new WP_REST_Request('GET', '/wc/v3/orders');
    $request->set_headers([
        'Content-Type' => 'application/json',
        'Authorization' => 'Basic ' .
            base64_encode( 'ck_The_Consumer_Key:cs_The_Consumer_Secret' )  // Basic Authorization Attempt
    ]);
    $response = rest_do_request($request);
    $decoded_response = $response->get_data();
    return json_encode($decoded_response);

When I'm logged into my admin account, and visit this page, I get the following output as expected:

[{"id":498,"parent_id":0,"number":"498","order_key":"wc_order_...

When I'm not logged in and visit the page with the shortcode, the following is returned:

{"code":"woocommerce_rest_cannot_view","message":"Sorry, you cannot list resources.","data":{"status":401}}

In fact, removing the Authorization header from $request->set_headers() has no effect on the output of either of the two examples, running under a logged in admin account and a non-logged in account.

Please note: While this example uses WooCommerce, this question is specific to WP_REST_Request and rest_do_request().

7
  • 1
    Would it not be much, much easier to use the internal API that the REST route uses instead of calling the REST API internally? E.g. instead of calling the posts endpoint to get posts, use WP_Query, do the equivalent for orders? I'm not sure why you would want to do it this way
    – Tom J Nowell
    Commented Sep 14, 2020 at 9:52
  • @TomJNowell That may be true, but in my use case - I'm using several other plugins that provide nicely documented API routes, but don't provide internal function documentation (if it was just looking up orders, then that's exactly what I would do). I could still try to figure out what the routes end up doing, but I'm really hoping to use the existing API if possible.
    – Tom
    Commented Sep 14, 2020 at 10:32
  • Also, I suppose I could do a CURL request too, but that seems kind of clunky since it's literally the same site.
    – Tom
    Commented Sep 14, 2020 at 10:33
  • using the internal API is what I would suggest you do, start by looking at the implementation of those REST API routes in the respective plugins. WooCommerce in particular does have documentation for those functions and has dedicated classes for people developing with WooCommerce. I would strongly advise against this approach on performance, security, and reliability grounds
    – Tom J Nowell
    Commented Sep 14, 2020 at 10:37
  • I would assume by doing that though, as the plugin author changes the plugin overtime so may the implementation of those REST API routes. I understand that WooCommerce provides lots of documentation on those functions and classes, but the plugins I'm using don't:/
    – Tom
    Commented Sep 14, 2020 at 10:46

2 Answers 2

1

How can I add authentication for rest_do_request()?

No. This solution to your problems will not work, and it will not save time or effort.

In fact, it will require extensive and concerted effort, and lots of time. This despite the entire purpose being to avoid dealing with undocumented PHP code by using the REST API instead.

The fundamental problem is that rest_do_request handles the request in the same request as the current page load, and so it runs in the same context.

So to accomplish what you want, we need to trick WordPress into thinking you're logged in, and as someone else who has the privileges to use that route. This then continues for every single API that route uses.

On top of that, plugins can load code differently depending on the context, so you would need to change how they load, but you don't know if you need to do this yet because shortcodes are processed much later on.

So, you will need to make significant adjustments to WordPress' internal state, as well as lots of adjustments to the plugins, possibly forking them.

The only practical method, is to make a REST API request using the HTTP APIs, but this will incur a large performance cost.

Either way, there are no advantages to this approach.

1
  • My best hope was using the Authorization header and use the generated username/password from the plugin itself - but it's sounding like that's not an option if rest_do_request() handles the request off the same page. Thank you for the insight!
    – Tom
    Commented Sep 14, 2020 at 10:57
0

use woocommerce_rest_check_permissions that filters REST API permissions of current user:

add_filter( 'woocommerce_rest_check_permissions', function ( $permission ) {
    $permission = true;
    return $permission;
}, 10 );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.