REST - Access control with HATEOAS

Back to overview

Many web applications today consist of a JavaScript frontend (Angular, React, Svelte, etc.) and a separate backend. One of the most popular backend options are REST APIs. Most of the web applications we develop for one of our clients also use REST APIs in the backend. One of the main advantages of REST APIs is the ability to offload the heavy lifting of access control to the backend side. This is done with the help of the HATEOAS(Hypermedia As the Engine of Application State) constraint, which is part of the unified interface constraint of REST APIs.

HATEOAS and access control

Since REST is the underlying architecture of the World Wide Web, an example of HATEOAS can be found on virtually any website that can be accessed with a standard web browser. When accessing a website, the state can only be changed or controlled by clicking on the embedded hyperlinks. It is possible to visualize all transitions of the website with a state machine. This applies to both static websites and dynamically generated websites. With dynamically generated websites, the state machines can be different for each user who accesses the page. Access control usually plays a role here, as not every user normally has the same access to all resources of a web application.

To illustrate this, we can take a simple blogging website. There are two types of users: the owner of the blog and the visitors who want to read the blog entries. While the owner of the blog should be able to create, delete or update entries on this site, visitors should only be able to read the entries. Assuming that authentication and authorization are already implemented correctly, the two state machines for users are as follows:

Two state machines for website users

Each node of the state machine represents a state that is returned by the server when a page is visited. The outgoing edges of each node show what a user can do based on their current state. Each of these edges is technically represented by a link. If an edge/link is missing in the state machine, it means that the user is not allowed to take the same path as another user. As the state machine implies, a guest cannot change a resource, while the owner is allowed to perform all operations.

Conventional websites respond with an HTML payload that browsers can already display. Thus, a button that is not included in the HTML response will not be displayed on the screen. This could be due to the backend deciding that a user does not have sufficient rights. However, REST APIs usually respond with some kind of JSON payload. When using HATEOAS, this payload will contain some form of a list of links that tells the client what it is allowed to do next. In this case, the frontend must implement logic to achieve the same dynamic rendering of the user interface. In the next section, we will show a short example of how we achieve frontend-side access control in Svelte.

Example in Svelte

Assume the following response object is returned from a REST API after requesting a single sample resource (links are implemented with a proprietary reserved property):

   const response = {
	“xxx”: “data XXX”,
	“yyy”: “data YYY”,
	“_links”: {
		“self”: “https://example.net/things/first”,
		“next”: “https://example.net/things/second”,
		“create”: ”https://example.net/things”,
		“delete”: “https://example.net/things/first”,
		“update”: ”https://example.net/things/first”
	}
   }

Based on this answer, we can represent the parts responsible for creating, deleting or updating a resource in Svelte as follows:

  {#if response._links.hasOwnProperty(“create”) }.
	
  {/if}
  {#if response._links.hasOwnProperty(“delete”) }
	
  {/if}
  {#if response._links.hasOwnProperty(“update”) }
	
  {/if}

As you can see, the conditions on the frontend are very simple and only work with the links provided by the backend. This means that the potentially cumbersome logic for access control lies entirely on the backend side, which greatly relieves the client side and reduces complexity.

Summary

This article showed how access control can be achieved, at least visually, through HATEOAS. Of course, not displaying UI elements does not prevent otherwise malicious clients from accessing protected API endpoints. Therefore, all endpoints that require restricted access must be additionally secured in the backend.

Do you have any questions? We have the answers!

Please write to us. We look forward to hearing from you!