It ensures that in the complex mesh of services comprising your API, every party handles requests securely and performs informed authorization decisions.
Behind today’s APIs, it’s common to have many services processing a single request. Gone are the days when a monolithic application was exposed directly on the internet and was responsible for handling an entire API request. Now the process is usually more complex — a request comes through a load balancer to an API gateway, and then is forwarded to a service responsible for the concrete endpoint called. To process the request, that service will often call other data sources or services, which might call even more services and so on.
As you can see, much communication occurs inside the modern mesh of software services. But to adhere to zero trust standards, companies must properly secure the communication of all of these requests. Because in this new age of cloud-based services and rising vulnerabilities, enforcing security policies only at the perimeter is no longer sufficient.
Services must receive adequate information to implement proper security solutions inside the mesh. This comes in the form of identity data to perform authorization decisions. With this data in hand, the service can know who is requesting what and on whose behalf the request is made. However, this opens a new set of problems that identity distribution attempts to solve.
What Is Identity Distribution?
Identity distribution helps ensure that in the complex mesh of services comprising your API, every party handles requests securely and performs informed authorization decisions. It enables identity data to be verified continuously, not only at the perimeter.
However, identity must be securely distributed among all system components. Also, performing authorization based on plain values set in the request’s headers or body is not recommended. Instead, signed tokens or certificates should be used for this task, as they offer ways of verifying the authenticity of the data.
It’s Not Just About Authenticating the User
When considering identity information in a request, one instantly thinks about the authenticated user who initiates the request. However, identity distribution is not only about the user. A service that receives a request should validate the origin of the request. It should verify the external application that originally sent the request and use an allowlist of callers. The service should also be able to verify the direct internal caller, such as an API gateway or another service that has forwarded the request, through mechanisms that can limit unnecessary communication between parties.
Mitigating API Security Risks
When distributing the user’s identity, a simple solution may first come to mind: Take the user’s credentials at the perimeter (like a session ID or an access token) and pass it to all the other services.
This solution, however, introduces two problems. First, it breaks the least-privilege principle. Suppose you pass the original credentials to all the services. In that case, it now means that every service that handles the request has all the permissions that the original caller (the frontend application) has. This could create a security breach if you have a rogue actor operating inside your organization. It could also create a vulnerability if one of your services sends the privileged token to an external service.
The second issue is that the original credentials can contain important information about an entity, such as a user. Some of this information may be sensitive and shouldn’t be shared with every party, especially when a single request crosses organizational boundaries.
These two issues can be illustrated with the following example. Suppose that during a checkout transaction in an e-commerce system, the access token contains the user’s sensitive payment information, like a credit rating, or has permission to handle payments. Then the token is used to call the stock service to verify whether all ordered products are available. Now the stock service has a token that allows it to perform payments on the user’s behalf. It also has sensitive information that it shouldn’t have access to. All this can be avoided by using proper identity distribution techniques.
Identity Distribution Is an Organizational Issue
The security benefits of identity distribution depend on the technology choices and implementation used. Ultimately, it’s all about tokens or certificates being passed around and verified according to established algorithms. Authorization decisions are made using software tools, such as entitlement management systems or code that validates tokens. Still, the problem of identity distribution is in no way purely technological — it is an organizational issue.
Organizations should take time to decide what services should get which identity data to handle authorization decisions properly. You have to know which information about a user can safely cross organizational boundaries. This will determine how data may appear in tokens and when tokens should be exchanged. For example, some services require the user’s Social Security number to properly authorize a request, so tokens will contain it as a claim. However, this is a sensitive piece of information, and any services that do not require it should receive tokens without this claim.
On the one hand, you will want to verify which information about a user or client can be safely shared with which services. On the other hand, you need to concretely identify what pieces of information these services need to perform fully informed authorization decisions.
Identity Distribution Techniques
Different techniques and technologies can help you implement identity distribution correctly. Once you know what information should be passed along with the credentials and which parties should receive it, you can consider the following solutions to adequately distribute identity in your service mesh.
1. Secure All Traffic
Nowadays, Transport Layer Security (TLS) is used nearly ubiquitously on the internet. This is a good approach and a must when sending requests that contain credentials (tokens or sessions) from applications to APIs. However, it’s still common to terminate TLS at the perimeter. A load balancer or an API gateway will often receive an encrypted request, but then forward it unencrypted over a plain HTTP connection. This is not considered best practice — TLS should be used end-to-end, even between services in your mesh. This allows your services to control which other services are calling them, helping you lock down the infrastructure.
2. Lock Down Infrastructure
Using an encrypted connection among all the services in your mesh allows you to introduce control over that communication. Through mutual TLS (mTLS) and frameworks like SPIFFE or Kubernetes ingress settings, you can make sure that services are only called by specific services. This can even replace other forms of traditionally used credentials. For example, a service can authenticate to a database with mTLS instead of a hard-coded password. mTLS can also protect traffic between services located in different clusters or data centers. This kind of protection does not replace business-level authorization but plays an important part in creating a secure service mesh.
3. Use Well-Established Standards
Services need a way to securely and reliably obtain identity data to make authorization decisions. This data can be delivered in many forms, but it’s recommended to use established standards. OAuth and JSON Web Tokens (JWTs) are examples of battle-tested standards well suited for this purpose. Companies should make sure to issue tokens adhering to OAuth flows and security best practices instead of developing bespoke solutions. JWTs are very reliable for distributing identity data among services if used according to current best practices.
4. Claim-Based Authorization
OWASP lists broken authorization as the №1 API vulnerability in its API security vulnerabilities ranking. This highlights how vital identity distribution is to deliver the correct identity data to the right services so they can perform proper authorization decisions. Services should use claims-based authorization instead of relying on API keys or scopes, as it provides the best solution for complex authorization. Using claims allows services to easily externalize authorization to entitlement management systems like Open Policy Agent (OPA).
5. Opaque Tokens as a Privacy Enhancement
To better protect the identity data within access tokens, it’s recommended to use opaque tokens. Unlike JWTs, opaque tokens do not reveal any information to frontend applications or eavesdroppers. This is especially important when tokens are issued to third-party applications, as your organization has no control over what happens with the token. However, using JWTs is more convenient for services. Being self-contained tokens, JWTs don’t require the recipient to constantly query a central service to check the token’s validity or read the associated identity information. To get the best of these two worlds, companies should consider implementing the Phantom Token approach, where an opaque token is used outside your infrastructure, and the associated JWT is distributed inside your service mesh.
6. Use Token-Sharing Techniques
Services that call other services when handling a single request should make sure to pass the correct token down the chain. In some situations, it’s acceptable to share the same token that the original service received. This might make sense when the services are conceptually close. But for others, the original service should send a token that contains as few details as possible. It should have just enough details to perform an authorization decision and adhere to the least-privilege principle. This can be achieved with the following token-sharing techniques:
- Embedding tokens so that the original token contains other tokens with less information.
- Exchanging tokens, where the original service exchanges the token for another that contains only the relevant information.
Conclusion
APIs need identity data to perform authorization decisions. In a modern service mesh, this data must be distributed so that all parties involved in the request processing can maintain the same level of security. Implementing proper techniques for identity distribution is vital to keeping APIs and user data safe. Remember that identity distribution should be designed with your organization in mind, and that data and credentials should be shared among services only when necessary. This will prevent exposing it to unnecessary risks.