Search code examples
wordpressapioauth-2.0ionic2wordpress.com

Wordpress API: Get posts from private wordpress.com site


I am building a mobile app, and I want to use the wordpress.com api to get posts from my wordpress.com site. Normally, you can follow the instructions here: https://developer.wordpress.com/docs/api/getting-started/. However, in this case, the wordpress.com site I am trying to access is set to 'private'.

When I try to make the api get request, I get the 403 error message "User cannot access this private blog".

Is it possible to use the wordpress.com api to load posts from a private wordpress.com blog?

I am hopeful this is possible when someone controls the app making the api request and also controls the target private site (like in the case here). This seems like a good use case for the api.

I don't want to change the site from being private for now. I also don't want users of the app to have to enter log-in credentials anywhere. I want the app itself to be able to provide the relevant credentials when loading posts.

I have gone through various oauth actions, such as getting a client_id, client_secret_key, and a token, but I don't see any method for actually loading posts from a private site.

I have seen the question asked before, without answer, like: https://wordpress.stackexchange.com/questions/180637/fetching-private-posts-or-custom-post-types-via-wp-api-with-basic-authentication and How to retrieve private posts from wordpress using JSON rest api?.


Solution

  • I was able to (mostly) figure this out. Yes, it is definitely possible to use the wordpress.api to load posts from a private wordpress.com site.

    In order to do this, any api call you make to the private site (get, post, etc...) needs to have an oauth2 token in the header along with the request. You get the token from wordpress.com.

    Note that this description is about the wordpress.com api, not the wordpress.org api.

    To get that token, you can follow the steps here: https://developer.wordpress.com/docs/oauth2/. You can potentially get a short term token that needs to be refreshed regularly or a permanent token. You get the permanent token from the server-side code method.

    There are a few different ways to do that:

    All of them require that you register a separate url with wordpress.com, here: https://developer.wordpress.com/apps/. At that site, you create a new "app" that will ask for permission. The app can use your url if you have a website, or just the localhost site you use in development (or even just a localhost port url if you don't use it in development--the key is to get a client_id and use it in the request process). There, you will get a client_id and client_secret_code that you will need for these steps. From there:

    1) You can just use curl code to query the api and get back an auth code, and then another query with that auth code to get a token. Note that the curl code on the wordpress.com oauth2 documentation is in PhP (not pure curl).

    2) You can provide the methods to get the token, as described in the wordpress oauth2 doc linked above, in your app directly. For ionic apps, this probably requires using an inappbrowser plugin, to go to the page where the api app gives you permission.

    3) Another possibility: wordpress set up a fairly simple node-based process to get a token: go to https://github.com/Automattic/node-wpcom-oauth, download the code there, and follow the steps. A very helpful tutorial on that is at:http://haiku2.com/2015/11/how-to-setup-a-wordpress-com-oauth-token/. It is a few years old but it still works as of now.

    Once you have a token, you include it in the header to make the call. For example, using HttpClient from @angular/common/http (for ionic/angular/typescript apps):

    var token = 'YOUR TOKEN'
    var url = 'THE API ENDPOINT'
    return new Promise((resolve) => {  
            let headers = new HttpHeaders();
            headers.append('Authorization', 'Bearer ' + token)
            this.http.get(url, {headers: headers}) 
            .subscribe(data => {
                console.log(data)
                }, err => {
                console.log(err);
            });
     });
    

    This should all work...unless you hit against CORS (cross origin) issues.

    If it just doesn't seem to work, or if you get errors about the results being null, the token being invalid, or no 'Access-Control-Allow-Origin' header being present, there is a good chance CORS is the problem.

    On ionic--and maybe other web-based tools--you probably need to configure your settings to use the wordpress.com endpoint as the proxy server. Info on that is here:https://blog.ionicframework.com/handling-cors-issues-in-ionic/.

    For ionic and ios--when you want to put the app onto a device or emulator, there is a separate set of CORS issues in more recent ionic versions, owing to ionic's later 2017 implementation of WKWebView.

    Here is more detail about that:https://blog.ionicframework.com/wkwebview-for-all-a-new-webview-for-ionic/. To get over the CORS problems on the ios device, you have to bypass CORS. Ionic's current advice for that is to use the Ionic Native http plugin. It seems to be a little inconsistent in the implementation right now, but that is the only solution I have seen so far.