In a recent article, we shared why we believe that combining OAuth with mTLS is one of the newest methods for securing API communications. It works by enhancing bearer tokens with verifiable certificates for increased security compared to using the tokens on their own. But it is important to note that, as with any solution, incorporating mTLS has tradeoffs that could pose adoption challenges. Some applications are critical enough that the extra verification is worthwhile, such as internal services that rely on tight security. For other applications, the effort to lock things down with OAuth mTLS might be overkill. Read on to determine if OAuth mTLS is right for you and your use cases.
One potential disadvantage of mTLS is that it requires significantly more code to implement than basic TLS. Creating and implementing this extra code requires additional labor and may require knowledge that your team does not have. The added complexity of the required additional checks on tokens can potentially slow things down if not implemented well, extending total execution time of your programs.
The increase in overhead can also extend into the maintenance stage, as mTLS does not lend itself to a “set it and forget it” approach. mTLS can be especially risky for client-to-server connections and is seldom recommended for this use case because once authentication is achieved, it is assumed that the channel is always authenticated, which is not a safe assumption. This is part of the reason that experts often recommend combining mTLS with some other identification protocol that works on a different level, such as OAuth. But even in that situation, it is still important to ensure that previously verified connections are not exposed to compromise. Carefully planning your implementation of OAuth mTLS is essential to achieve a secure system that doesn’t introduce new security flaws.
Since mTLS is frequently recommended to secure service meshes, we will discuss it in that context. mTLS implementations typically offer strict and permissive modes, with permissive mode as the default. In strict mode, only mTLS traffic is accepted. Permissive mode allows a mix of mTLS and plain text traffic. While permissive mode is easier to implement, it can make the overall system less secure. And while it might be tempting to use strict mode, it’s worth noting that:
- Some microservices don’t support mTLS.
- The increased effort to implement the necessary checks for strict mode can be extensive.
One popular workaround is to attach a sidecar to each microservice, which handles the authentication and authorization steps without affecting the microservice code directly. As an analogy, this could be likened to posting a security guard in front of each area instead of implementing security procedures inside the areas themselves. Sidecars also have the advantage of making application design more modular, which is often a priority with service meshes. But sidecars have to be created and implemented separately, which further increases the overhead as described in the previous section.
While mTLS can be a key component of an effective security strategy, it’s necessary to decide if it’s the right tool for the job. If the application is not mission-critical, the extra effort required to implement this level of security might be overkill. Consider carefully whether compromise of the service would be a critical risk and whether it would be worth the additional effort to implement the required mTLS checks.