WooCommerce REST API AJAX Auth – 401 response

First off, the WooCommerce REST API documentation is available here and you should check it out.

Secondly, the examples below are using the /wc/v3/products/categories (“List all product categories“) endpoint.

And here’s a proper way to authenticate your request using OAuth — it always works when authenticating over HTTPS and it is the only accepted option for authenticating over HTTP:

  • It’s up to you how to make the relevant variables available in JavaScript via wp_localize_script(). Or to implement the PHP code below in JavaScript.

  • You can generate your WooCommerce REST API keys via the WordPress admin interface — WooCommerce → Settings → “Advanced” tab → REST API.

// Define the request method.
$method = 'GET';
// Just set the second parameter to the proper endpoint, without /wp-json.
$url = get_rest_url( null, '/wc/v3/products/categories' );
// Define your keys.
$ck = '<put key here>'; // consumer key
$cs="<put key here>"; // consumer secret

$params = [
    // Required parameters:
    'oauth_consumer_key'     => $ck,
    'oauth_timestamp'        => time(),
    'oauth_nonce'            => wp_create_nonce( time() ),
    'oauth_signature_method' => 'HMAC-SHA1',

    // Parameters specific to the endpoint:
    'per_page' => 2,
];

// Sort the parameters and encode them into a single string.
uksort( $params, 'strcmp' );
$params2 = '';
foreach ( $params as $key => $value ) {
    $params2 .= ( $params2 ? '%26' : '' ) .
        rawurlencode( $key ) . '%3D' . rawurlencode( $value );
}

// Create the signature base string.
$sig_base = $method . '&' . rawurlencode( $url ) . '&' . $params2;
// And generate the signature base.
$sig = base64_encode( hash_hmac( 'sha1', $sig_base, $cs . '&', true ) );

// Add the required oauth_signature parameter.
$params['oauth_signature'] = $sig;
// And build the query string.
$query = http_build_query( $params );

// Then make request to this URL:
//$req_url = $url . '?' . $query;

And here are other options you can use, but only when authenticating over HTTPS, and you should know that these will expose your consumer secret key:

  1. Use HTTP Basic Auth — set the HTTP Authorization header; i.e. Authorization: Basic <base64 encoding of <consumer key>:<consumer secret>>:

    jQuery.ajax( {
        url: '/wp-json/wc/v3/products/categories',
        headers: {
            'Authorization': 'Basic <base64-encoded value here>'
        },
        ...
    } );
    

    In PHP, you can do base64_encode( '<consumer key>:<consumer secret>' ); to get the base64-encoded value.

    And make sure the Authorization header is enabled on the server.

  2. Or provide the consumer key/secret as query string parameters — e.g. https://example.com/wp-json/wc/v3/products/categories?consumer_key=<KEY>&consumer_secret=<KEY>:

    jQuery.ajax( {
        url: '/wp-json/wc/v3/products/categories?consumer_key=<key>&consumer_secret=<key>',
        ...
    } );
    

Another option when authenticating over HTTPS, is by using the standard cookie authentication as explained here:

// This example provides the nonce as a query string parameter.
jQuery.ajax( {
    url: '/wp-json/wc/v3/products/categories?_wpnonce=<nonce>',
    ...
} );

You may also use authentication plugins, but you will need to test them on your own.