Microservices security: secure calls between services
Microservices security comes down to one habit: check every call, not only the ones that arrive from the internet. When an app is split into many small services, a request passes through a gateway and then hops from service to service, and each hop is a place where a missing check lets something through. The OWASP Microservices Security Cheat Sheet calls authentication and authorization the fundamental requirements to settle at design time. This guide walks through its advice and ends with a review of one internal call.
Microservices security: the gateway is not the only door
Many teams put sign-in and permission checks in an API gateway and treat everything behind it as trusted. OWASP's guidance splits the job in two:
- At the edge, the gateway rejects unauthorized requests, and you make sure nothing can reach the services by going around it.
- In each service, the service enforces access to its own protected operations, including calls from other internal services. Rules that need context about the object, the tenant or the business stay here.
The cheat sheet is direct about the limit: gateway checks complement service checks, but they do not establish that a downstream operation is authorized. As the system grows, prefer shared, reviewed policies over each team writing its own, while each service still applies the object and tenant rules only it can know. Tenant rules in particular are covered in multi-tenant security.

Five places to check. Simplified from the OWASP Microservices Security Cheat Sheet.
Pass the user's identity so each service can check it
A service deep in the chain still needs to know which user the request is for. OWASP says to pass the authenticated user's context in a form each receiving service can validate, and to authenticate the calling service separately. Those are two different questions: who is the user, and which service is asking.
A signed assertion helps, with a limit the cheat sheet spells out: a signature protects the assertion from being changed, but it does not by itself grant access to the resource being asked for. The receiving service still decides whether this user may do this thing.
Service-to-service authentication: mutual TLS
With mutual TLS, each service has its own key pair and uses it to prove who it is to the services it calls. Both sides then know who they are talking to, and the traffic gets confidentiality and integrity as well. OWASP notes that mutual TLS usually runs on a self-hosted public key infrastructure, and that the main challenges are giving every service its keys, revoking certificates and rotating keys. The server-side TLS settings still matter; see TLS settings.
Service-to-service authentication: tokens
The token approach works at the application layer. A calling service gets a signed token from a security token service, holding its service ID and its permissions, and attaches it to each request, for example in a header. The called service then validates it in one of two ways:
- Online. The service asks the token service whether the token is still active. It can see revocation, but each call adds latency and a dependency on the token service being up. Caching those answers delays spotting a revoked token, so keep the cache short and never past the token's expiry.
- Local. The service validates the signed token itself with the issuer's trusted keys and the right token profile. For JWT access tokens, OWASP points to RFC 9068 and warns that checking the signature alone is not enough. Local checks cannot see a revocation before the token expires, so keep lifetimes short or add a revocation mechanism.
Two rules apply either way: neither method replaces the service's own authorization, and if a token cannot be validated, the request is refused. Tokens usually travel over TLS. For how to test token handling itself, see JWT security.
Log every call chain without leaking secrets
Logs are how you trace an attack across services. The cheat sheet describes a common design: each service writes to standard output, an agent on the same host collects the logs and sends them to a message broker, and a central logging service reads from the broker. Its recommendations:
- Every call chain gets a correlation ID, and every log message carries it, so you can follow one request across services.
- Secrets and needless sensitive data are left out before the service writes the log line; filtering later cannot remove what is already on disk.
- The agent and the broker authenticate each other and encrypt what they send, and the broker applies least privilege.
- Logs are structured, such as JSON, with context like the host and container name.
- Local buffering helps through outages, but local files can still lose records, so monitor delivery and test recovery.
What to record and what to keep out is in OWASP's Logging Cheat Sheet, and keeping log lines trustworthy is covered in log injection.
Worked example: reviewing one internal call
Say your orders service calls your payments service to refund an order, and both sit behind one gateway. Review that single call:
- Bypass. From inside the network but outside the gateway, call
paymentsdirectly with no credentials. It should refuse. - Caller. Find how
paymentsknows the call came fromorders: a mutual TLS certificate or a service token. If the answer is "it is on the internal network", that is the first fix. - User. Find how
paymentslearns which user asked for the refund, and confirm it validates that context rather than trusting a plain header. - Authorization. Confirm
paymentsitself checks that this user may refund this order for this tenant, not only that the gateway let the request in. - Token checks. If tokens are used, check how revocation is handled, how long tokens live, and that a failed validation means a refused call.
- Logs. Make one refund in a test environment and find it in the central logs by its correlation ID in both services. Check that no token or card data appears in the lines.
Repeat for each service that changes money, accounts or permissions first, then for the rest.
Frequently asked questions
If my gateway checks every request, do services still need authorization?
Yes. OWASP says each service must enforce access to its own protected operations, including internal calls; gateway checks do not prove a downstream operation is allowed.
Should I use mutual TLS or tokens between services?
The cheat sheet describes both. Mutual TLS identifies both ends at the connection and needs key provisioning, revocation and rotation; tokens work at the application layer and carry the caller's permissions. Either way, the service still authorizes the request.
Is checking a JWT's signature enough?
No. OWASP says local validation must use trusted issuer keys and the applicable token profile, and that signature verification alone is insufficient.
Get started
Pick the internal call that moves money or changes permissions and run the six checks above. If you want an outside review, whitehatstoic's cybersecurity and AI safety testing covers web app and API review, with a written report, fixes and a retest after fixes. whitehatstoic's full-stack development builds on Next.js, Node and Postgres. No test can promise to find every weakness; the work is scoped after a short call.

Building something that has to be safe? Book a meeting with whitehatstoic: tell us the product, the deadline and your biggest worry, and we reply with a plan and a price.
Comments
No comments yet.
Sign in or make an account to comment.