In the
traditional two or three-tier world of web development, there is an inherent
trust between the client and the server. Each is contextually aware of the
other and withholds or shares information depending on the level of trust. The
server may generate and persist session information about the client to enforce
control or to simplify interaction. The client may do the same for a better
user experience. In the world of APIs, this contextual awareness is not
guaranteed since APIs can call or orchestrate other components where the context
of the client may be different or unknown.

API architecture
can be, and often is, layered. Since APIs offer abstraction via their
interfaces, the consumer need not know, nor care about, what goes on behind the
scenes of the interface. This also means that it should not matter to the consumer
what the API does, as long as it sticks to its interface contract. This abstraction
allows an API to do any orchestration, composition, translation or enrichment to
the original request; be that calling other APIs, interfaces, databases, systems,
etc. Basically, the consumer of the API may not know where their request is
actually being fulfilled, or how many other components/interfaces are being
consumed in the process.

On the
counter side of this, components being orchestrated or composed are abstracted
from the original request by the API consumer. They may not be contextually
aware of the overall intentions of the original consumer, and ideally, need not
be; they should only be concerned with responding to their specific request.

This potentially
disparate awareness between the original API consumer and the components being manipulated
by the API can be a problem for the traditional mindset. Some might struggle
with this lack of awareness and see it as a potential risk in security, authorization,
authentication or trust. This often becomes the excuse for not adhering to interface-based
architecture principles and the insistence in sticking to a two or three-tiered
architecture, even with APIs.

The trick
here is to implement and understand a chain of trust. Each conversation in an
end-to-end request should be based on an established trust between consumer and
producer (or requester and responder). The client making the original request should
have a trust relationship with the original API. The API, in turn, should have
an established trust relationship with each of the components it orchestrates
or consumes. And each of these components should have an established trust with
their consumed components.

This trust
and context can be established using a combination of patterns and approaches.
These could include:

· Mutual TLS (or similar) to restrict
boundaries to known systems,

· API Gateways to manage the consuming
systems

· JWT to manage user authentication
and authorization (using OAuth2, SAML, OIDC, etc.)

Plus, many
others.

Picture from Pexels.com