The WordPress REST API is a great tool that opens a new world of WordPress possibilities. From plugin and theme development to integrations, headless WordPress, and beyond, the wonders that the WordPress REST API offers are often only limited by your imagination.
As wonderful as all of this is, it is just as important to take the appropriate measures to keep everything as secure as possible.
In this article, we will go through everything you need to properly secure the WordPress REST API.
Table of contents
What is REST API?
REST is an acronym for Representational State Transfer. It’s an architectural style often used as an API standard by web applications. WordPress also uses the REST API.
The REST API specifies a number of standards and behaviors that define how data should be sent and received.
REST API requests will typically include:
- Endpoint: This is the location of the server resource that the client is requesting.
- Headers: Headers provide additional details about the request that is being made, such as credentials.
- Method: The method defines the function of the request, such as updating specific data or deleting it
- Body: The body includes the actual information that is being passed on, such as the updated information in an update request
- Parameters: Parameters provide instructions related to the request being made, such as links and metadata
The method, then, is what gives API its functionality since it defines which tasks we are able to carry out. Common REST API methods include:
- GET: Used to fetch a resource from WordPress, such as an existing post
- POST: Used to send a new resource to WordPress, such as a new post
- DELETE: Used to delete an existing resource from WordPress, such as a page
- PUT: Used to update an existing resource on WordPress
The WordPress REST API
The WP REST API offers access to WordPress data types such as posts, pages, and taxonomies. It enables you to interact with WordPress programmatically. It is enabled by default with each WordPress installation and plays a critical role in the function of your websites.
The WordPress REST API offers a number of functions that can be executed remotely. Some may notice that these are HTTP-based, and you would be correct. Data is sent and received in JSON (JavaScript Object Notation) format, ensuring wide compatibility across many different platforms.
Using the REST API you can make requests directly to the WordPress database without having to log in to your WordPress site (although some exceptions do apply). It also allows for process automation, which can enhance workflows while opening new opportunities.
REST API authentication options
There are several different options for WordPress API authentication methods. By default, the WordPress REST API offers cookie authentication; however, depending on your use case, you might want to choose a different method.
Cookie
Cookie authentication is the default authentication method for making REST API requests. When using this authentication method, the client must possess a valid cookie. The cookie can be obtained by logging in to the WordPress dashboard from the same client that will be making the requests.
Basic authentication
Basic authentication does away with the need for a cookie. Instead, the user credentials are sent in the API request. To use this method, you’ll need to install the WordPress REST API plugin.
Do note that the current available version is 0.1. Testing in a staging environment is highly recommended.
Step 1
Download the plugin .ZIP file: Head to the WordPress REST API plugin GitHub page, click on the green <> Code button, and choose Download ZIP file from the drop-down menu.
Step 2
Install and activate the plugin: From your WordPress dashboard, navigate to Plugins > Add New Plugin, upload the .ZIP file, and activate the plugin once it has been installed.
Valid WordPress user credentials must be used to authenticate using this method. We’ll discuss user credentials in more detail in the next section.
oAuth
oAuth, short for Open Authorization, is a security standard authentication method used in HTTP implementations to delegate access. WordPress does not provide this out of the box. As such, you will need a 3rd party plugin to implement this type of authentication method.
API Key authentication
When using API key authentication, you get one key that remains valid until a new key is generated. The key is passed to the WordPress REST API through the authorization header when accessing WordPress REST API endpoints. A 3rd party plugin is also required to enable this method.
Do note that many hosting providers disable the authorization header. As such, you may need to update this setting by adding the following to the .htaccess file:
RewriteEngine On
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
JSON Web Token
Think of tokens like cookies that do not require you to sign in to WordPress like cookies do. However, they function differently than an API key in one fundamental way – they expire. You also need a secret key, which authorizes the tokens.
To use JSON Web Tokens, you’ll need to install a WordPress plugin that adds this functionality since it is not supported by default.
WordPress REST API authentication security
WordPress’ REST API allows for both authenticated and unauthenticated requests. Resources available through the front end of the website can typically be requested and served without the need to submit any authentication. On the other hand, resources and functions available through the admin dashboard require authentication.
Use an SSL/TLS certificate
While HTTP may be used as an umbrella term, you’ll need to make sure all requests are going through HTTPS. HTTP requests are sent in plain text, making them easy targets for anyone looking to gather information to breach your website.TLS Certificates are important regardless of which authentication method you use. They encrypt traffic between WordPress and clients that connect to it, ensuring the safe passage of data as it traverses the Internet.
Create a custom user role
In the majority of use cases, API requests are done for specific actions. As such, the default WordPress user roles might include extra permissions that the API user could very well do without. In such cases, a custom WordPress user role can help you balance security and usability.
Keep in mind the principle of least privilege, which states that users should have access to carry out the tasks they’re assigned but not more. This limits the damage any one user can do, whether inadvertently or not.
Require authentication for all REST requests
We can ensure all REST API endpoints are secure by telling WordPress to only accept authenticated requests. This means that only authorized users are able to make requests to the API and receive an answer.
Before making this change, it is important to test it out in a staging environment. This will ensure that nothing breaks once you roll it out to your live environment.
Here, we will need to add a filter to the functions.php file, which returns an error if the user making the request is not logged in.
Add the following code to your functions.php file:
add_filter( 'rest_authentication_errors', function( $result ) {
// If a previous authentication check was applied,
// pass that result along without modification.
if ( true === $result || is_wp_error( $result ) ) {
return $result;
}
// No authentication has been performed yet.
// Return an error if user is not logged in.
if ( ! is_user_logged_in() ) {
return new WP_Error(
'rest_not_logged_in',
__( 'You are not currently logged in.' ),
array( 'status' => 401 )
);
}
// Our custom authentication check should have no effect
// on logged-in requests
return $result;
});
Whitelist IPs
Limiting connections to the server from specific IPs also improves the security of the REST API since only IPs of trusted clients will be allowed to connect.
Do keep in mind that IP address whitelisting will only work if you know who will be making the API requests and they have a static IP address.
You can whitelist IP addresses in several ways, including through the functions.php file or the .htaccess file. You’ll also find 3rd party plugins such as Wordfence that’ll allow you to restrict access through its user interface.
For example, to whitelist IPs through the .htaccess file, simply add the following code, replacing ip_address with the IP addresses that you want to whitelist:
<FilesMatch "wp-json">
Order Deny,Allow
Deny from all
Allow from ip_address_1
Allow from ip_address_2
</FilesMatch>
More WordPress REST API security tips
Secure your WordPress REST API endpoint even further by implementing these security best-practices:
Install an Activity Log plugin
Keeping a log of all changes done through API calls ensures that you have an activity record you can refer to should you suspect illegitimate access or unauthorized changes. Our very own WP Activity Log keeps a log of authenticated requests made through the REST API.
Each log entry includes useful information such as the user who made the change, the IP address from which the request originated, the date and time, and other important information.
Input validation
Input validation prevents the processing of malformed data. Attacks such as XSS (Cross-Site Scripting) and SQL injection contort input strings to embed malicious code into input strings. While these types of attacks are common, they can be prevented through input validation.
As a matter of best practice, input validation should be implemented early on to prevent compromised systems from affecting your processes. This can be achieved in several different ways, including using safelists, blocklists, format detection, and format correction.
The implementation of input sanitization and validation will depend on individual scenarios. Because of this, validation should be carried out through custom code. However, WordPress includes several helper functions to help you in this regard.
One such function is the sanitize_email() function. By using this function, you can ensure that any provided email address is correctly formatted.
$email = sanitize_email( $request->get_param( 'email' ) );
While this function can be very useful, do keep in mind that it does not check whether the email address is actually valid or not, nor does it fix any typos.
Rate limiting
Rate limiting limits the number of requests that can be made within a given period. Limits can be placed by client or location. You may also choose to place limits on the server itself, which applies irrespective of the client or location from which requests are made.
Limits can be placed in a number of ways, including hard limits – which stop processing requests to every REST API endpoint until such limits are lifted, and throttling, which slows down the processing of requests.The easiest way to implement rate limiting is by using a plugin such as WP REST Cop. Other plugins, such as Wordfence and ShieldPro, also offer this functionality.
How APIs work
For an API to work, you need two participants—a client and a server. The client makes an API request, also known as an API call, to the server, which then services that request.
The server defines how API requests need to be made. For example, if you want to connect to the Google Maps API, you’ll need to follow its requirements. In this case, you would need to set the Google ‘Maps Embed API URL’ within the src attribute or use Google’s Quick Builder to build the required code.
The structure of requests and responses varies from one API to another. As such, you’ll often need to refer to the developer’s documentation to understand how a specific API works.
Frequently asked questions
By default, the WordPress REST API uses cookie authentication, making it as secure as logging into the WordPress dashboard. However, there are steps you can take to make it even more secure. From using a TLS certificate to limiting call rates and whitelisting IPs, measures to harden access to the REST API will help you stay even more secure.
When using cookie or basic authentication for API access, you should also put a WordPress password policy in place by using a plugin like our very own Melapress Login Security. This ensures strong passwords are used thus keeping WordPress and REST API access as secure as possible.
There are a number of steps you can take to secure the WordPress REST API. If you are using cookie or basic authentication, have a WordPress password policy in place. Use a TLS (SSL) certificate to ensure all communication is encrypted and always validate any inputs to prevent attacks such as XSS and SQL injection. Other steps that you might want to take include IP whitelisting, API call rate limiting, and ensuring all API calls require authentication.
The WordPress REST API should not be disabled as this will break the wp-admin functionality. Instead, you should require authentication for all API requests. You can achieve this by adding the relevant code to the functions.php file. For more information, refer to the ‘Require authentication for all REST requests’ section.
By default, WordPress uses cookie authentication for WordPress REST API access. However, you can opt for a different method through 3rd party plugins. Available options include basic authentication, oAuth, JWT (JSON Web Token), and API key access.
Well, so far I was able to keep the URL routes to the REST API locked for non-admins, but now that more and more plugins need API access for anonymous frontend display, I am forced to open at least some routes.
After reading your post (and others, too) about relying on the REST API being safe enough to be left open, I was a bit relieved.
However, it still opens up some kind of “back door” – not in the way that secret content is revealed, but content is revealed and offered in a different way than what authors/publishers aim for when creating a site.
It is hard to explain to customers that their site is not “hacked” when they make panic calls just because someone sent them an API link where all the content of their site is published as JSON.
Also, what you say about fixing security holes might be true for WP Core, but not necessarily for the authors of plugins. But hey – if we don’t trust them we might as well not install their plugins at all …
Indeed, many website owners are not technical so they tend to “panic” when they see an alert from some plugin about a request. It’s a question of training and awareness, and also our responsability to create better products and solutions that help users in a meaningul way, rather than falsely alerting them.