
When building distributed systems, an API Gateway is often one of the first components we introduce.
It gives clients a single entry point, handles routing and keeps individual services hidden from the outside world.
But there's a question worth asking.
Just because a request came through our gateway, should the receiving service automatically trust it?
Not necessarily.
The Gateway's Responsibility
Imagine a system made up of several independently deployed services.
Rather than exposing each service directly, we introduce a Global Gateway (GG).
The gateway maintains a service discovery mechanism that identifies which service is responsible for a requested resource.
When a request arrives, the gateway determines its destination and forwards it to the appropriate service.
This solves an important problem: clients don't need to know where individual services live.
But routing requests and securing them are two different responsibilities.
Two Identities, One Request
A user authenticates with an Identity Provider (IdP) and receives a JWT access token.
When the user makes a request, that token accompanies it to the Global Gateway.
The gateway discovers the destination service and forwards the request with two credentials.
The first is the user's JWT, which represents the authenticated user.
The second is a machine-to-machine (M2M) token, which identifies the gateway itself and establishes its permissions.
Why do we need both?
Because a legitimate user doesn't automatically make the calling machine trustworthy.
And a trusted machine doesn't mean every user request should be permitted.
These are two separate identities serving different purposes.
Trust Is Established at the Service
This is where the architecture becomes interesting.
Instead of blindly trusting requests forwarded by the gateway, each service independently performs three checks.
First, is the calling machine trusted?
The service validates the gateway's machine token and confirms that the gateway has permission to invoke it.
Second, is the user authenticated?
The service validates the user's JWT, checking its signature, issuer, audience and expiry.
The access token must be intended for the receiving service. Where necessary, an appropriate downstream token can be obtained through token exchange.
Third, is the user authorised?
Even with both identities verified, the service must determine whether the user has permission to perform the requested action.
Only when all three checks succeed does the service execute the operation.
This separation matters because authentication and authorisation are not the same thing.
Why Not Trust the Gateway?
We could validate everything at the gateway and allow backend services to trust whatever reaches them.
It would certainly be simpler.
But it also introduces an assumption that every request reaching a service has already been correctly authorised.
The gateway would also need to understand permissions belonging to potentially unrelated business domains.
Instead, we can keep responsibilities separate.
The gateway manages discovery and routing, while individual services control access to their own resources.
This follows a fundamental Zero Trust principle: being inside the system doesn't automatically make something trustworthy.
There's a Trade-off
Of course, this approach introduces complexity.
Each service needs to validate credentials and enforce authorisation.
Machine tokens need appropriate scopes and audiences. Signing keys need managing. Communication between services must be secured.
We can reduce duplication through shared authentication middleware while keeping business-specific authorisation within each service.
The goal isn't to make every service implement security differently.
It's to make sure every service enforces the same fundamental trust boundaries.
Final Thoughts
An API Gateway is an excellent way to manage communication across distributed services.
But being the entry point doesn't necessarily make it the ultimate authority on security.
I find it helpful to separate the architecture into three questions.
Routing: Where should this request go?
Authentication: Who is making the request, both the machine and the user?
Authorisation: Is the user permitted to perform this action?
The gateway handles routing. The receiving service verifies both identities and makes the final authorisation decision.
An API Gateway controls how requests enter your system. Each service should still control what those requests are allowed to do.