What works is using a separate token for external-to-internal ("external token" for brevity) and internal-to-internal ("internal token" for brevity) requests:
- When Clients send requests to the Resource Server, the API Gateway exchanges the external token for an internal token with the Authorization Server.
- The API Gateway then forwards the request with the internal token to internal services.
A variant of Token Refresh using mTLS or the internal service's credentials can be used to obtain a new internal token.
OWASP recommends this approach.
after the external request is authenticated by the authentication service at the edge layer [referring to API Gateway], a data structure representing the external entity identity (e.g., containing user ID, user roles/groups, or permissions) is generated, signed, or encrypted by the trusted issuer and propagated to internal microservices.
Netflix (see references 1 & 2) uses this approach.
we created a new identity structure called Passport. What is Passport? It is an identity structure created at the edge [referring to API Gateway] for each request and services consumed in the scope of same request. It contains user and device identity information. It is internal to Netflix ecosystem, meaning it is an internal identity token that we don't send it out back to the device.
You can see my discussion with contributors from OWASP on GitHub.
Edit: Previously, I suggested validating the lifetime of the Access Token only at the API Gateway and not validate at the services. This is insecure as it violates Defense in Depth (see link to GitHub above).