API icon in a blog about WordPress API secrity

The most important security considerations when developing WordPress APIs

Your website’s security, along with its associated software and applications, is paramount. You’re not only securing the private information of your members or clients. You’re also mitigating the impact any breaches might have on the trust and confidence others have in your organisation. This, of course, can impact your company’s profit or viability.

When building APIs (application program interfaces) within your WordPress CMS, there are a number of security measures developers should undertake to minimise vulnerabilities and prevent your site from being exploited. 

These measures range from those that should be used at all times such as validation, sanitising and escaping; to case-specific actions like OAuth.

Of course, there are other strategies that can be set in place on the server and— though they may not be a developer’s responsibility—it’s important to be aware of these options, such as server firewalls and rate-limiting.

It should also be noted that some of these examples are not restricted to APIs, but can be employed within website theme templates.

First steps to API security: Validating, Sanitising and Escaping

The most basic practice to adhere to for a secure API is to ensure you employ a combination of validating, sanitising and escaping of incoming data.

Validating is the process of ensuring an API knows what data to expect and is able to verify that it is indeed the data expected.

Sanitising involves filtering input to ensure that it’s clean and safe to use.

Escaping ensures that the data you are rendering is secure and clean. These principles are not limited to APIs and should be followed within the theme template code at all times.

Consider, for example, an API that delivers content for a custom infinite scroll / next page function. This API would receive query parameters that get passed to the database via WP_Query. If you don’t validate and sanitise the request, an unexpected query could cause significant harm to the server.

However by validating and sanitising, you will have the peace of mind to know that the data is safe to be used by any method.

In this example, during the rendering of HTML on the infinite scroll template, all output should be run through escaping functions to prevent XSS (cross-site scripting) attacks.

<div class="car card-<?php echo esc_attr( $content_type ); ?>">
   <a href="<?php echo esc_url( $link ) ; ?>">
      <div class="card-title">
         <h2><?php echo esc_html( $title ); ?></h2>
         <img class="img wp-image-<?php echo esc_attr( $img_class ); ?>"
            src="<?php echo esc_url( $img_src ); ?>"
            alt="<?php echo esc_attr( $img_alt ); ?>"
            srcset="<?php echo wp_get_attachment_image_srcset( $img_id ); ?>"
            sizes="<?php echo wp_get_attachment_image_sizes( $img_id ); ?>">
      </div>
      <div class="card-contents">
         <div><?php echo esc_html( $contents ); ?></div>
      </div>
   </a>
</div>

There are a number of WordPress helper functions that streamline this process and further reading can be found here, sanitising, escaping and data validation.

User permission checks

User permission checks assist in determining if the user has the correct access to conduct the activities that they are attempting.

This could be as simple as retrieving content behind a paywall, checking user roles, or capabilities to complete an administration-only action.

From an API perspective, this is a vital strategy that prevents unauthorised users from accessing or manipulating data on the server. This may also be implemented at the theme template level to manipulate the content that users see (via a paywall for example). WordPress has a number of built-in functions to help assess (logged-in) users’ status, roles and capabilities. 

In addition to the WordPress functions, some sites have user services with different user roles and capabilities such as subscription levels provided through a plugin.

This changes the approach you would use to check user-permissions, as you would leverage the plugin’s inbuilt functions, in some cases in conjunction with the WordPress functions. These range from permission levels for custom roles to account activation / status levels, allowing you to manipulate the outcome of the connection with your API.

Nonce within WordPress: When and How

In addition to user permissions, there are situations where you will require additional security checks. One of these is a nonce (Number Used Once), which in most cases is used to protect URLs and forms from malicious intent.

It should be noted, nonces within the WordPress context are not true nonces, as they are a hash made from letters and numbers that can be used more than once within its lifetime depending on the user and context.

WordPress specifically advises against relying on nonces for authentication or authorisation access. The developer should then consider nonces to always be compromised. As a result they should be accompanied by user permission checks (as noted above) or the user’s authentication cookie.

<a href="https://site-x.com.au/wp-json/sitex/v1/user-management?action=delete-user&user_id=25">

Consider this basic example:
A user with administrator privileges is already logged into site x, their site.

They are visiting site y which contains an element (such as a link), that when clicked, unassumingly directs them to a custom endpoint on site x with query variables.

Let’s also say that this URL and query variables are in the format to manipulate their website (site x). With nonce verification and user permission checks in place, access is not granted. If the nonce was not in place, the user permission checks would pass due to the logged in status and allow the user to unknowingly alter the site.

For a better understanding of nonces within WordPress and how to create them, refer to the WordPress codex

When to use OAuth

OAuth is an authorisation method that allows unrelated services or users to safely authenticate and communicate by providing access without sharing their login credentials.

OAuth would only become a consideration if you required your service to communicate with another service to complete a specific task as an authorised user.

Although WordPress core doesn’t currently offer an OAuth solution, there are several third party plugins available. We currently use WP OAuth Server as our solution.

OAuth Example.

Recently The Code Company worked with a client what requested two separate sites. The first site had paywalled content. The second site required group administrators to create, update and remove users on the first site under a group subscription managed on the second site.

For this to work, the first site needed a REST endpoint for manipulating the group users from the second site. 

By implementing OAuth the request between sites became secure, preventing any other connections to the endpoint from manipulating users on the first site.

Firewalls and rate limiting

Both firewalls and rate-limiting are set at a server or WAF (web application firewall) level, yet they are important security tools a developer should endeavour to learn more about and have a basic understanding of.

By using a web-infrastructure such as Cloudflare, it is easy to implement such security features as a web application firewall (WAF).

In this instance, Cloudflare will monitor the web requests and filter out undesired traffic based on any of the rules in place. This will remove suspicious activity such as—but not limited to—cross-site scripting attacks (XSS) and SQL injections (SQLi). The WAF will also provide the ability to add rules for IP address whitelisting, block users by IP address, or specific countries.

Dependent on your scenario, your API may only receive requests from a single given IP, hence an IP whitelist rule would prevent unintended IPs from connecting with your API. Where possible rules such as this should be used in conjunction with the other mentioned security checks.

Rate-limiting can be applied to the entire domain or specific URL to identify an excessive number of request rates. This prevents such issues as denial-of-service (DoS)brute force attacks. In the instance of the API, there are multiple scenarios that can use rate-limiting, for example, the data sent from a subscription form to your API endpoint would be perfect for monitoring and denying excessive rates of request.

Security is a team effort 

Knowledge of website security and vulnerabilities should be within every web developers’ arsenal. The examples mentioned here are just the tip of the iceberg.

It benefits every developer and the projects they work on to read more and understand these topics so you can confidently build APIs that include a security mindset from the beginning. 

Anthony Thorne

Anthony is a full stack WordPress engineer at The Code Company. He works with clients on projects and retainer engagements. Anthony has worked on large Chargify and other payment related API services.