Access
Subscription, IP filtering, spike arrest and quota, OAuth2, OIDC, mTLS and token exchange: who is calling, with what proof, and how far.
OAuth2 is an authorisation delegation framework: an application obtains limited access to a resource on someone's behalf, without handling their password. OpenID Connect adds identification on top: knowing who the user is. The distinction carries direct consequences for design.
The access token is there to call the API, it is meant for the API, and the client has no business reading it. The identity token describes the authenticated user, it is meant for the client application, never for the API. An API that accepts an identity token as authorisation has a design fault, and it shows up by reading the token's audience.
Who proves what
Three questions arise on every call, and confusing them is the original error behind most designs. Authentication establishes who is calling. Authorisation establishes what that caller is allowed to do. And a third, often forgotten: on whose behalf, when an application calls in the name of a user.
An API key answers only the first, and only partly: it proves the caller holds the key, not who they are. It designates no end user and does not expire. It is a traffic identifier, insufficient as soon as there is data to protect.
What it does bring lies elsewhere, and it is the central mechanism of an API platform. The key, or the OAuth client, belongs to a declared application, and that application has subscribed to products. The platform therefore knows, before even looking at the token, which APIs this caller is allowed to call and at what volume. A call to an API with no subscription is refused without the service being consulted, and the quota counter is charged to the subscription, not to the IP address.
That is what separates an API platform from a proxy with a list of keys. The test goes to whoever runs the platform: when a partner asks for access to one more API, is it a subscription form they fill in, or a ticket that ends in a line of configuration written by hand? The second answer points to a catalogue that will never be up to date.
The access token answers all three. In its most common form it is a signed token, a JWT: a readable object carrying the issuer, the audience, an expiry date and the granted scopes, with a cryptographic signature to check it was not forged. Verifying it therefore requires no network call, and it is that property which drives everything that follows.
Which flow for which case
| Case | Flow | Note |
|---|---|---|
| Service to service, no user | Client credentials | The most common in the enterprise |
| Web application with a back end | Authorization code + PKCE | The secret stays server side |
| Mobile or single page application | Authorization code + PKCE | No embedded secret |
| Device with no browser | Device authorization | Terminal, television set, printer |
| A service acting in the name of a user | Token exchange | Detail below |
Two flows are to be set aside, and RFC 9700 does not put them on the same footing. The password flow, where the application handles the user's credentials, must not be used, without reservation. The implicit flow is discouraged: the token comes back in the fragment of the redirect URL, never sent to the server but exposed to browser history and to the injection of a token into the authorisation response. Both survive mainly in copied configurations.
Token exchange
A user calls API A, which has to call API B to serve them. There are three answers.
Forwarding the user's token hands B a token whose audience designates A, with all the user's scopes. If B is compromised, that token can be used elsewhere.
Calling B with a service token makes the user disappear: audit and authorisation decisions can no longer rely on them.
Token exchange, standardised by RFC 8693, answers properly. A obtains from the identity provider a token meant for B, with reduced scopes, which preserves the original identity.
Where to validate the token
Client
Access token
Gateway
Signature, expiry, audience, issuer
Service
Business authorisation, revalidation
Validating at the gateway alone leaves the backend defenceless the day a call bypasses it, and one eventually does. Validating at the service alone multiplies implementations, and therefore mistakes: audience left unchecked, algorithm accepted without constraint, keys never rotated.
The robust answer uses both, with distinct roles: authentication and scopes at the gateway, which rejects early and protects capacity, business authorisation in the service, the only place that knows who is allowed to see which record. A gateway that takes business authorisation decisions has picked up logic that does not belong to it, see the gateway.
Token lifetime, and revocation
This is the heaviest design decision on the page, and the least debated. It settles three things at once: the latency of every call, the coupling to the identity provider, and the real delay before an access can be cut off.
Two forms exist. The signed token is verified locally, with no network call, so with no added latency and no dependency on the IdP on the call path. It stays valid until it expires, whatever happens: nothing can cancel it.
The opaque token is a reference with no content, which the validator has to submit to the IdP through introspection, standardised by RFC 7662. Every call becomes dependent on the availability of the IdP, but revocation is immediate.
| Signed token | Opaque token | |
|---|---|---|
| Verification | Local | Introspection call |
| Added latency | None | The IdP's, on every call not cached |
| IdP outage | Traffic carries on | Traffic stops |
| Revocation | At expiry | Immediate |
The compromise that holds in most cases pairs a short-lived signed token, a few minutes, with a long-lived refresh token held by the client. The first is never revoked, it expires. The second is revocable, and since it is only used at spaced intervals, querying it puts no weight on the call path.
Hence the figure that has to be stated: the real delay before a consumer can be cut off is the lifetime of the access token. A platform that issues eight hour tokens cannot promise to cut a partner off in less than eight hours, whatever the console says. If the contractual or regulatory commitment is shorter, either the lifetime has to come down, or a revocation list consulted at the gateway has to be added for urgent cases only.
The usual setting, to be confirmed against exposure: five to fifteen minutes for an access token, a few hours to a few days for the refresh. Shortening further simply moves the load onto the IdP, which then becomes the component to size.
The points to watch
The audience. A token issued for API A must not be accepted by API B. Checking aud
fits in one line of configuration. Its absence remains the most widespread fault.
The algorithm. Accepting the algorithm declared in the token header is a documented vulnerability. The list of permitted algorithms is set on the validation side.
Key rotation. The JWKS cache has to refresh itself, failing which the platform rejects every token at the identity provider's next rotation.
Clock skew. A few seconds of drift between issuer and validator are enough to reject valid tokens. The tolerance is set small. Set wide, it becomes a vulnerability.
Token size. A token loaded with roles can exceed the header size allowed by an intermediate component. The failure only hits users with many roles, which makes it slow to diagnose.
Scope granularity. A single scope across the whole platform protects nothing, hundreds of scopes are no longer granted correctly by anyone. The useful grain is the resource and the operation.
mTLS
OAuth2 identifies the calling application, mutual TLS identifies the channel. The two combine, and mTLS remains the mechanism expected by default on highly sensitive partner flows, particularly in banking and insurance.
Its two difficulties have nothing to do with cryptography. Certificate lifecycle first, which demands an inventory, expiry alerts and a renewal notice period written into the contract. Termination next: if a load balancer terminates TLS before the gateway, the client identity has to be passed on to the gateway through a trustworthy channel.
A partner certificate expiring is a common incident, and its peculiarity is being entirely predictable: the date is known at issuance.
Filtering and limits
Before any question of identity, two defences sit at the gateway and cost almost nothing. They are also the ones most often forgotten in configurations carried over from one project to the next.
IP address filtering. Restricting the origin of traffic to a known list. On a partner flow, on an administration API, on a back office, it is the measure that takes the least work for the most effect. It never replaces authentication, because an address can be spoofed and a partner changes infrastructure without warning, but it cuts the surface down before the first token is read. The trade-off is an inventory to keep, and an expiry to watch like a certificate's.
Rate limits, which are two distinct mechanisms. Confusion between the two is common and is paid for in incidents.
| Spike arrest | Quota | |
|---|---|---|
| Window | The second, the minute | The day, the month |
| What it protects | Backend capacity | The commercial contract |
| Attached to | The route, the instance | The subscription |
| On breach | Smoothing or immediate rejection | Refusal until the next period |
| Who sets it | Operations | The product |
Spike arrest absorbs a burst. A client sending a thousand calls in one second when the backend holds a hundred is stopped before it has brought the service down, and the rest of the consumers do not notice. The quota, for its part, says a subscription is entitled to a million calls a month, which has nothing to do with capacity and everything to do with what was sold.
A platform that has only the quota lets bursts through. A platform that has only spike arrest cannot bill, nor tell two consumers apart. Both are put in place, and the refusal returns a 429 with a header saying when to retry, failing which the client retries immediately and aggravates the very thing the limit was meant to avoid.
What the gateway protects, and what it does not
The OWASP API Security Top 10 lists the risks specific to APIs. The useful way to read it is to sort what is handled at the gateway from what is not.
| Risk | Handled at the gateway? |
|---|---|
| Object level authorisation, reaching someone else's record | No, only the service knows the right |
| Broken authentication | Yes, largely |
| Property level authorisation, modifying a forbidden field | Partly, through schema filtering |
| Unrestricted consumption | Yes |
| Function level authorisation, calling an administration operation | Partly, through routing |
| Unrestricted access to sensitive business flows | No, a matter for the service |
| Server side request forgery | Partly, through validation of incoming URLs |
| Security misconfiguration | Yes |
| Improper inventory, forgotten APIs or old versions still live | Yes, if the inventory is kept |
| Unsafe consumption of third party APIs | Partly |
Authorisation faults, the most exploited of the lot, are handled in the code and checked in test. Buying a platform changes nothing there.
The gateway does cover volume and configuration risks well. Four defences are switched on from the start: spike arrest and quota as described above, inbound schema validation with unknown properties refused, size and depth limits on bodies, and error messages that reveal neither the technical stack nor an internal query.
The GraphQL case
A single route, a body that describes an arbitrary query: per call rate limiting loses its meaning when one call can cost a thousand times more than another. And while POST is the mandatory verb, the specification allows GET for reads, which is enough to slip traffic past a protection placed on POST alone.
The specific protections therefore have to be put in place explicitly: maximum depth, cost analysis, introspection disabled in production, persisted queries for known clients. A gateway that advertises GraphQL support often does no more than route it. The list above makes a good pre-sales questionnaire.
Updated August 2026.