WordPress REST API - How to Authenticate without a plugin - wordpress

I've used the WooCommerce REST API for a number of years and I now need to try and upload some media files to WordPress so we can reference these when adding Product Images to existing Products, as the WooCommerce REST API doesn't allow for uploading image files directly. I have no experience with any WordPress REST API implementations as yet.
I'm pretty confused at this stage whether I need to use a WordPress plugin to allow my remote application (using cURL) to be able to upload files to the Media endpoint? I saw something about not using basic authentication but I can't see any settings within WordPress itself to create API keys like you do for WooCommerce.
Do I need to use a plugin to enable REST API access to allow remote uploading of media files? From what I've read the REST API is not in the WordPress core (I'm running WordPress 4.9.2) but I can't see where I setup authentication for the API requests?

There are different authentication schemes and for remote applications / integrations, you will generally need a plugin to authenticate.
The default idea is one logs into WordPress (e.g. wp-login.php) and that authorizes that user for any REST API functionality that might require it. An example use-case where this is suitable is a plugin that adds a page in the admin dashboard and its back/forth with the server is implemented via JS + REST API. No additional plugins or anything of the sort is required, especially now that the REST API is part of the core.
For integrations, currently decent options include an OAuth plugin, JWT, and the Application Passwords plugin.
Since you're using CURL and loading data ad-hoc, the Application Password plugin could be a pretty straightforward choice that's easy to manage. Once the plugin is installed + activated, given a user, you can edit their profile and add one or more Application Passwords (and disable them). The idea is you use a different password for each application where you want to authenticate as that user.
To use an Application Password, base64-encode "USERNAME:APPLICATION_PASSWORD" and then incorporate the resulting value in an Authorization header along with any requests.
Suppose you create an Application Password for username and the plugin generates "WXYZ WXYZ WXYZ WXYZ WXYZ WXYZ". At a shell prompt you could generate the required base64-encoded format:
echo -n "username:WXYZ WXYZ WXYZ WXYZ WXYZ WXYZ" | base64
For the sake of example, suppose the base64 output is: "AAAAAAAAABBBBBBBBBBBBCCCCCCCCCCCCCCCDDDDDDDDDDD=". You could then use this value in the Authorization header of any requests:
curl --header "Authorization: Basic AAAAAAAAABBBBBBBBBBBBCCCCCCCCCCCCCCCDDDDDDDDDDD=" -X POST -d "title=Editing a Post Title with REST API" https://example.com.test/wp-json/wp/v2/posts/<ID>
It is important to use SSL/TLS as the authorization header can be sniffed out by an attacker if it were transmitted via plaintext.
Plugin link:
https://wordpress.org/plugins/application-passwords/

So according to wordpress they say there are 4 ways to authenticate.
Cookies auth
Basic auth
oauth
json web tokens
Unfortunately all of these methods require you to either edit your functions.php file or download a plugin. There's currently no way around that.
I've found the fastest way to just quickly get this running is to use this plugin. Or if you don't actually want to install the plugin just put their code into your theme's functions.php file and basic auth should be ready to use. Maybe not a great long term solution but it'll get you up and running.

Related

How to secure custom Rest API that is used by a Wordpress plugin

I would like to program a Rest API to be used by a wordpress plugin. The Rest API should only work if the wordpress user also has certain rights. I would like to know how I can protect the Rest API so that it is not used without permission and only works when a Wordpress user is logged in with permission. What is the best way to implement this conceptually? Do you have any ideas?
Thanks.
I don't know what are Wordpress plugin capabilities from an authentication perspective but usually REST APIs do respect HTTP standards so the same authentication schemes (Basic, OAuth, ApiKey, etc...). It also depends on where would the REST API run such as remote server...

Next.js with headless wordpress is authorization (JWT) needed for fetching posts?

I'm building a Next.js site with headless Wordpress and will use the REST api or maybe the graphQL alternative. My question is if authorization with a JWT token is necessary for just fetching public posts?
I have tried it and it seems to make requests very slow plus creates overhead in terms of storing into a cookie etc.
In the Next.js wordpress-cms example they only use authorization optionally to be able to get unpublished posts.
So in a nutshell: do I need to implement authorization with a JWT token for every request to make my site secure or is this not necessary when building a next.js site with headless wordpress?
You don't need to implement any kind of authorization to serve public content. You may need authorization to serve private content and/or to publish data just like a normal WordPress Setup. Compared to REST, GraphQL provides lighter and cleaner data it might be a better solution for an Headless WP most of the time..

Authentication from wordpress REST API

After searching form wordpress documentation and google, i haven't find any proper way to achieve my goal : able to login to wordpress from custom third party application built with nodeJs.
The steps is check if couple username / password is administrator and process tasks on my external app.
Anyone has already used the REST API of wordpress to auth user? WITHOUT INSTALLING ANY PLUGIN , i just want to get response from server if my couple username/ password is true and is administrator, i know i can asks the database to check but i want to pass throught the built-in wp rest api.
Thank you.
The simple answer is no, and here is why
While cookie authentication is the only authentication mechanism
available natively within WordPress, plugins may be added to support
alternative modes of authentication that will work from remote
applications. Some example plugins are OAuth 1.0a Server, Application
Passwords, and JSON Web Tokens.
Source: Wordpress Official Handbook
However there is a painful and insecure way of doing it with plain HTTP authentication which is not recommended.
Recommended way of doing this securely is to get WordPress JWT or oAuth Server extension and deal with standard authentication process which is more convenient and secure, WordPress already lists them which are referenced in the quote. Hope this helps!

What's the best method to transfer strings from wordpress plugin to server?

Good day.
I have my own WordPress plugin in which I want to deliver certain things (configuration) to my webserver.
The plugin will be available for free afterwards and I would like to send certain values from the plugin to my webserver when activating the plugin (only with the permission of the user).
What is the best way to transfer values ​​like (plugin configuration, name, email etc.) from a WordPress Plugin to a PHP Webserver?
I would have done it first with curl but that could be disabled, right?
I'm looking for a simple way to pass parameters (strings/arrays only) from a client (plugin) to my host (webserver).
It is important that it is not cURL or fopen, etc., so a function which can be disabled. It should always work to 100%.
Would $_GET be a good option? Is it only usable within a form or? So the user must submit a form to transfer the values.
What else is there to do with a pure PHP Server - Client | Client - Server connection?

Integrating Drupal + Moodle + MediaWiki with OpenID

I'd like to be able to use these "best of breed" opensource solutions, with the only requirement of some sort of single-sign-on between the different sites. I don't want my users having to log-in in 3 different places, so I though it could be possible with OpenId.
Has anyone tried something similar?
OpenID will not avoid the problem of having to sign in 3 separate times. It was allow the user to share the same login credentials between the sites, but they will have to actually log in to each of the three systems. If that is not a problem, go with OpenID. If it is, you have two options:
Use an LDAP server to authenticate on all three sites. I think all three software packages have modules/plugins for LDAP (Drupal, Moodle, MediaWiki). Once you have the LDAP server running, the rest should be easy.
Write custom modules/plugins for each platform that authenticate against a single database. Maybe you could use the Drupal database as the primary one, and have MediaWiki and Moodle authenticate with that. So, effectively, the user will only have an account on the Drupal site, but will get access to all three. This is basically the same idea as an LDAP server, but might save you some overhead and complication.
There is also the Moodle Integration module for Drupal that attempts to accomplish the same thing, only without MediaWiki in the mix. I would check that out.
Good luck!
here are three possible solutions: (1) sigle sign-in site, (2) inject login/register forms into all sites using server site includes - SSI and (3) - ajax.
Single sign-in site.
suppose you have site1.domain.com and site2.domain.com and you want to login/register at both simultaneously. Probably the easiest way to do it will be to create another domain e.g. login.domain.com that will do the job. Your login/register application will need access to databases for site1 and site2 and/or their api's. Since login status usually resides in the cookies, your login application will need to set those login cookies to both sites simultaneously (on successful login/registration) and delete on logout.
To set cookies for all sites from login.domain.com - all of the must sit on .domain.com and cookie domain parameter must be .domain.com
If your solution needs both api access (to the other applications) and access to the same database by several applications - you may need to deal with database transactions. This is because new registrations won't be visible on other sites until transaction is committed - so for example - you can not call api from within login code to retrieve cookies before committing the transaction with the new registration.
One important detail. If you already have users separately registered at site1 and/or site2 but not on both your signon site will either have to handle those cases or you'll need to sync registrations manually yourself upon deployment of your new registration system. Manual fix won't be possible when extra user input is required to complete the cross-site registration. This point also becomes important when you add new sites requiring some new user input for the registration.
Finally, carefully choose domain name handling OpenID. To the best of my knowledge it is impossible to transfer openid endorsements across subdomains without users consent - please correct me if I am wrong. You don't want to ask users to re-register just because you decide to rename the sub-domain.
server side include (ssi) method
Another solution is to inject those forms via sever-side includes into all sites. This may be considerably harder and will depend on the type of webserver in use and will work slower.
A pre-requisite here is that all your applications run on the same subdomain - so that openid works for all of them.
I've once built common user registration for MW (php) and cnprog (python/django).
My solution was to display the same exact registration form on the wiki and the forum site, while generating and processing this form with django. I did it this way because wiki and forum "skins" are so different that I did not want to surprise visitors with the dramatic change of site appearance when they go to the registration page. This is complicated and I will not do it again :) and instead would go with single sign-in method.
in order to display django output through mediawiki I've created a wiki extension printing apache "include virtual" call to glue django-generated content with the wiki output. This comes with problems.
Apache include virtual on my installation cannot POST to subrequests and cannot pass cookies from subrequests and cannot pass redirect responses (all http headers will be thrown out) to the upstream user requests.
So I've added "was_posted=true" to mark the posts for django and a secret code to prevent cross-site forgery. To get the cookies out - had them printed with cookie_morsel.output_js() in python. So javascript must run on the client for this to work. Any redirects will have to be done with javascript too. Extra work will still be needed to upload files (like avatar picture).
So single sign-on may be the best solution.
ajax may be a neat way around - just build forms in all of your sites with javascript and submit them via ajax. Will work fast and will not break appearance of your various sites,
but this won't please the folks allergic to javascript.
Actually, the only method that does not require any javascript is single sign-in site.
Posted this because I've spent enough time building this thing for MW and django - an hour of typing did not make a difference :).

Resources