[✅ Solution] Authentication with WordPress Rest API

Hi,
from what I learnt about the WordPress Rest API, most calls need a cookie based authentication on top of / instead of the basic auth. Otherwise only public information is responded.

How could I do that with Tape? Or should an Oauth add on be used?

2 Likes

@dirk_s I don’t have a lot of value to add here. But we have had a lot of luck using this plugin to pull data into the ‘other guy’ using webhooks. Their dev team is very responsive with requests for additional functionality and fringe use cases.

I know this isn’t a solution to your actual question but my comment will be archived with your post so it may help someone researching in the future.

1 Like

@dirk_s as we recently added full support for external OAuth integrations that would be the preferred way.

I assume you are talking about accessing the WordPress REST API inside of Tape workflow automations? Setting cookies in a Node environment (which Tape workflow automations use under the hood) is not trivial and usually rather inconvenient. That’s why the OAuth solution would be more recommended.

Curious to hear more and to potentially read your solution - could be useful to more people inside the Tape community. :blue_heart:

Cheers
Tim

1 Like

If you manage that WP site, you can install the Basic Auth plugin. GitHub - WP-API/Basic-Auth: Basic Authentication handler for the JSON API, used for development and debugging purposes.

Or use the built-in APP Password. Authentication – REST API Handbook | Developer.WordPress.org

Then …/wp-json/wp/… Don’t need to worry about cookies.

4 Likes

I tried with basic auth and still - only public stuff was returned. However I managed to use Oauth2 and can now also retrieve e.g. posts with status=draft.

I succeeded with Insomnia / Postman. Also was able to setup Oauth2 connection in Tape. NowI’m struggling with the logic of the API call.

Like other APIs, WordPress returns results paginated.
How would I loop with the API Call automation element until I have all my results?

I tried to access to find out what the return header contains - it also lists the number of results and pages. However, the “API response” variable contains the body of the response and seems like only a part of the header of the response.

  …
  "statusCode": 200,
  "headers": {
    "Authorization": "Bearer qREDACTEDn"
  }

Is this some limitation of the current implementation of the API call element, @Tim ?

Hi Dirk I’m not familiar with the API however when you say number of results and pages if this means you get a page ID or name can you put them in a list(array) and then loop through each making a new call to get the details of each?

The API Response gives me some information in the headers:

x-wp-total	83
x-wp-totalpages	9

This means, there are 83 articles that I can pull. In numbers of 10 (default), it would be 9 pages of results to pull. I would need to loop 9 times.

The number can be increased. However, there is a hard limit depending on the settings of each WordPress System.

Thats why I need to think about a procedure to run API the API call element in a loop. Probably I need to switch it to custom code and adjust?

@dirk_s

Okay without the response or a WordPress server to play with I have to make some guesses however hopefully this will get you there with some tweaks:

First Call

You make the first call and then extract the total number of pages the extraction of the pages is the biggest issue as I can’t test but I think something along the lines of what I have shown should work.

Build an Array

Next, we want something to loop through so we will build an array of numbers from 1 up to the totalPages number:

The Loop

Now we can loop through the pages by looping for each number in our array we can then add the page number to our API Request with page=@pageArray:

You may need to tweak the request as well but I believe it will be something like this:

@Collected / API Configset / API Base URL /posts?page=@pageArray 

Put it all together

When you put it all together you end up with something like this:

Something along those lines should work for you anyway, but of course, at 3am I could be typing complete rubbish :wink:

4 Likes

Unfortunately the idea breaks with that:

var_api_response.headers.get is not a function

Also the complete var_api_response object doesn’t contain the complete response header. I guess it may be the way, the API call element is implemented currently?

it was the bit I was most worried about if you could send me where you are seeing the x-wp-totalpages 9 so if it is the response then the full format you can sanitise it if you need (and DM it to me if you want) then we can work out how to pull it out as once we have that number we can build the loop?

1 Like

Hi,
I see it with Insomnia (like Postman), doing the same call. There I can access all headers from the response. I removed some lines, which are not interesting…

server: nginx
date: Tue, 13 Feb 2024 20:29:44 GMT
content-type: application/json; charset=UTF-8
…
x-wp-total: 83
x-wp-totalpages: 9
…

I also tried with the correct case and spelling. The object I receive from the call within Tape:

Bildschirmfoto 2024-02-14 um 17.21.43

The headers are almost missing completely.

@TapeTeam is there any chance you could have a look at this and let us know? Maybe we are holding it wrong :smiley:

1 Like

Hi @dirk_s,

I checked this out and indeed the API CALL workflow action does not expose response headers, which is an advanced feature. From WordPress API’s side, imo it would be preferable to return the pagination data in the body instead of the headers. But I guess we’ll need to work with what we have.

What you can do, is convert your action to an “Execute Script” action, and slightly adjust the code to yield the headers. Your code should look something like this:



  // assemble body
  const request_body = `{"value": "test"}` || undefined;
  const request_headers = {};

  // assemble options
  const request_options = { followRedirects: false, data: request_body, headers: request_headers };

      const httpResult = await await tape.HttpRequest.sendAuthenticatedHttpRequest({
    authenticatedViaIntegrationId: YOUR_ID_HERE, // an integer ID that will be generated by your conversion
    httpCallType: 'POST',
    httpCallUrl: `https://api.podio.com/...`, // use you URL here
    httpCallBody: request_body,
    httpCallHeaders: request_headers,
    httpCallFollowRedirects: false
  });

console.log(JSON.stringify(httpResult.headers)); // prints all HTTP response headers in my example

In above scenario, I used an example that posts a comment to Podio - but it should also work with other HTTP methods such as GET in your case.

Good luck &
Cheers
Tim

2 Likes

I did again some tests and found out a more convenient way for now:

While Basic Auth doesn’t work with USERNAME and USERPASSWORD - it works with USERNAME and APPLICATION PASSWORD. This was added in WP 5.6 and allows external API access without nonce (not recommended for production access anyway) and cookies.

Also it doesn’t require any third party plugins as it would be required for Oauth2.

My sync is now running fine, except the same situation we have experienced with Mautic - fields with 150.000 characters are too small for some posts / pages ([✅ Solution] Whats the maximum length of different field types?), as the raw view includes all short codes of the template for instance.