Using OpenAPI Overlays to Differentiate Consumer Personas
Is it possible to have a single OpenAPI document that targets different consumer personas?
Not all API operations should be available to all consumers. Depending on who you are, you might have access to some operations and be barred from using others. One of the jobs of API producers is to configure the correct restrictions so access is differentiated based on consumer personas. However, in most situations, API documentation isn't differentiated, so that all consumers can see information about all available operations. Let's see how you can create the proper differentiation with the help of OpenAPI Overlays.
This article is brought to you with the help of our supporter, Scalar.
Scalar is a suite of powerful & customizable developer tools to help you at all stages of API development. Create beautiful API Documentation in a notion-like editing experience.
Let's say you're designing an API with operations that anyone should be able to access, and some others are only available to users with administrative privileges. One way to create a definition for this API is to put all operations on a single OpenAPI document and then, at run time, make sure that non-admin users aren't allowed to access the privileged operations. Another option would be to create separate OpenAPI documents that you'd distribute to regular and admin users. Each option has its own drawbacks that I want to explore in detail before I propose a solution.
Having a single OpenAPI document with all the operations in it feels efficient from a maintenance perspective. However, not being able to differentiate who can access the documentation of privileged operations can constitute a security risk. Yes, just the fact of showing people how a privileged operation works can be a security threat. Knowing all the details of a restricted operation, including its parameters and request and response payloads, gives a malicious actor enough information to attempt unauthorized access. Many of you might be thinking that "security by obscurity" isn't efficient, and I'd say you're right. We're not hiding the privileged operations just for the sake of it.
We want to hide the information so only some people know they exist. That's exactly the ability the second option gives you. You can selectively show a different OpenAPI document depending on the type of user accessing it. This option is interesting from the perspective of who can access information. However, it creates a maintenance cost you'll have to pay over time. Every time you change the definition of any operation that is common across different audiences, you'll have to update the corresponding OpenAPI documents. You also need to restrict access to the OpenAPI document, depending on the operations it describes. If an OpenAPI document mentions any information that shouldn't be public, then its access should be restricted.
So, having one single OpenAPI document doesn't let you differentiate who can view it, and having separate documents creates a maintenance burden over time. How can we have the best of both worlds? That's where OpenAPI Overlays come in. The OpenAPI Overlay Specification v1.0.0 was published on October 17, 2024. It "defines a document format for information that augments an existing OpenAPI description yet remains separate from the OpenAPI description’s source document(s)." The idea is that you can specify a set of changes that are applied to the original OpenAPI document(s).
Let's see how you can use OpenAPI Overlays to create different API definitions for two types of users. Suppose you're designing an API to let consumers access and manage articles. You want to offer a read-only set of operations to regular users, the ability to create and update articles to writers, and the ability to delete articles to administrators. The idea is to create a base OpenAPI document with the read-only operations only and then have overlays that add the writer and administrator operations. Let's begin by seeing what the read-only API would look like. I'm simplifying the description to make it easier to understand.
openapi: 3.0.0
info:
title: Articles API
version: 0.1.0
description: Find, read, create, and manage articles.
servers:
- url: http://localhost:8080
description: Local server
paths:
/articles:
get:
summary: Get articles
operationId: getArticles
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Articles'
/articles/{id}:
parameters:
- name: id
in: path
required: true
schema:
type: string
description: Article identifier
get:
summary: Get article
operationId: getArticle
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Article'
components:
schemas:
Article:
type: object
required:
- id
- title
- content
properties:
id:
type: string
format: uuid
title:
type: string
content:
type: string
Articles:
type: array
items:
$ref: '#/components/schemas/Article'
This OpenAPI document describes the getArticles
operation that lists all the articles and getArticle
, an operation that lets you read a specific article. There's no other operation in the document meaning you don't know how to create, update, or delete articles. Here's the overlay with the writers operations, which I'm naming add-writer-operations.yaml
.
overlay: 1.0.0
info:
title: Article API writer operations
version: 0.1.0
actions:
- target: $.paths['/articles']
update:
post:
summary: Create article
operationId: createArticle
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Article'
responses:
'201':
description: Created
content:
application/json:
schema:
$ref: '#/components/schemas/Article'
- target: $.paths['/articles/{id}']
update:
put:
summary: Update article
operationId: updateArticle
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Article'
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Article'
Finally, here's the overlay that adds the deleteArticle
operation which is available to administrators only. I'm naming this overlay add-admin-operations.yaml
.
overlay: 1.0.0
info:
title: Article API admin operations
version: 0.1.0
actions:
- target: $.paths['/articles/{id}']
update:
delete:
summary: Delete article
operationId: deleteArticle
responses:
'204':
description: No Content
Now, you can generate a new OpenAPI document for writers by combining add-writer-operations.yaml
with the base document. To do that let's use the overlayjs
package which you can install by running npm i -g openapi-overlays-js
. Running overlayjs --openapi openapi.yaml --overlay add-writer-operations.yaml
generates a new OpenAPI document with both the read-only and writer operations. To add the admin operations you'd repeat the command but use the corresponding overlay file: overlayjs --openapi openapi.yaml --overlay add-admin-operations.yaml
.
In summary, the OpenAPI Overlays specification brings much-needed functionality. By using it, you’re able to maintain several representations of your API description without incurring high maintenance costs. In this example, you saw how you can differentiate consumer personas by using different overlays. However, you can use overlays for other purposes, such as providing localized translations of the API documentation, and changing servers and authentication based on your audience. As a last note, you should validate all the customizations you create with overlays at runtime. In the example we covered, for example, you still need to validate which users are writers and administrators at runtime. Using the overlay is not enough to guarantee proper authorization.