Drupal 8 REST API: Making authenticated REST API requests

In order to securely create, read, update and delete entities via the Drupal 8 REST API it is important you protect your REST endpoints with some kind of authentication process.

Out of the box Drupal 8 supports Basic Auth and cookie based authentication and I believe OAuth is either available or coming soon; in this post I am going to demonstrate using Basic Auth.

Configuring the REST API

Before you can make REST API requests to the Drupal 8 API there is some setup you need to do first.

By default Drupal 8 allows REST API access to pretty much all of the entities within the system.

Drupal 8 also takes the more secure approach of requiring you to opt an entity into to allow REST API access; this is also at the verb level for added security.

There are essentially two steps to prepare Drupal 8 for your REST API access:

  1. Switch on REST API access to entities and describe allowed verbs and formats
  2. Add user permissions for each verb

In order to switch on the REST API access the best way is to install the REST UI plugin. If you don't already have it downloaded you'll be able to easily find it with installation instructions online.

You will also be required to enable the following plugins to use REST UI effectively:

  • HAL
  • HTTP Basic Authentication
  • RESTful Web Services
  • Serialization

Once installed you will find its UI in the Drupal admin interface by navigating to Configuration => Web services => REST.

In this page you will see a table of entity types (or resource names) with enable buttons next to them.

You will need to enable the entities that you want to interact with via the REST API.

When configuring a entity for the REST API - each verb is set up separately:

GET: used for retrieving entities.

POST: used for creating or updating entities.

PATCH: used for partially updating entities.

DELETE: used for deleting entities.

For each of the available HTTP verbs you can select from the following content types:

  • XML
  • JSON
  • HAL_JSON

I tend to not work in XML unless I really have to I typically select JSON and HAL_JSON - this is because sometimes I just need a very simple JSON view of an object but other times I might need to create entities with references to other entities and in this case HAL is a better choice - it's still JSON but it includes a neat way to describe relationships between nodes.

The other decision is which authentication methods will you allow:

  1. Basic Auth
  2. Cookie
  3. OAuth (maybe at the time of reading)

For my architecture I am currently just selecting Basic_Auth.

Once the entity types are enabled and configured you now need to set the permissions.

Configuration the REST API permissions

In the same way you would normally configure permission in Drupal - you also need to configure permissions for REST API usage.

By default there is no access so you must opt-in HTTP verbs for an entity.

In the Drupal admin interface navigate to People => Permissions.

For each of the entities you have configured for REST API usage - find them in the permissions page under the RESTful Web Services section and enable which verbs you want to use.

If you enabled the Content entity for the REST API for all verbs you will find the following permissions:

  • Access GET on Content resource
  • Access POST on Content resource
  • Access PATCH on Content resource
  • Access DELETE on Content resource

You can set these verbs to any of the Drupal users types including anonymous user, authenticated user, administrator etc. etc.

What is Basic Auth?

Basic auth is pretty much as simple as it gets; it is essentially sending a username and password as a HTTP header.

Create a user using the Drupal 8 admin interface.

The username and password needs to be Base64 encoded, you can do this in tools such as Postman and DHC or it can also be achieve programmatically for example:

var userName = "myusername";
var password = "mypassword";
var basicAuthCredential = $"{userName}:{password}";
var credentialBytes = Encoding.UTF8.GetBytes(basicAuthCredential);
var base64Credential = Convert.ToBase64String(credentialBytes);

The final variable base64Credential value can then be used as the Authorization header in the REST API request:

// if base64Credential == iamthebase64value
Authorization: Basic iamthebase64value

CSRF Token

Another little gotcha when using the REST API for creating or updating entities is the X-CSRF-Token header.

I have a feeling this aspect of using the API might change as I'm not convinced the developers could be happy with this requirement.

To get a valid token for this header you can get a token from the website itself by hitting the following URL in a browser:

{YOUR DRUPAL DOMAIN}/rest/session/token

For example my local url is https://hackered.dd:8083/rest/session/token

Once you have this value you add the X-CSRF-Token header to the request:

X-CSRF-Token: MY_SESSION_TOKEN

Some Notes

I had a lot of fun with some of the node types on the version of Drupal 8 I was using at the time of writing including some nodes not working anonymously and vice versa.
Whilst Drupal 8 becomes more stable on each release; be prepared for some back and forth when things don't work the way they should.