In part one of this article, I walked through a recent ThoughtWorks project, exploring how an authentication sidecar pattern helped overcome many of the challenges associated with using self-authentication in a multi-service microservices architecture.
Now, let’s take a closer look at the two distinct sidecars we created to offload authentication workloads — the ingress sidecar, and egress sidecar.
The authentication sidecar pattern
The Kubernetes Pod now includes an ingress sidecar, which is responsible for verifying access tokens. This means the Service no longer needs to use an authentication SDK to authenticate inbound requests. The following illustration shows how the authentication sidecar architecture differs from the self-authentication approach for inbound requests.
The inbound request process is now as follows:
When starting, the ingress sidecar obtains the public key from the OAuth server. The frontend sends a request to the OAuth server to obtain the access token.
The frontend uses the access token to call the Service.
The frontend request flows into the ingress sidecar through the secure API to verify the access token. If the verification fails, the sidecar rejects the request.
If the access token is valid, the request flows to the Service.
The ingress sidecar obtains the public key, caches it, then verifies the access token based on the local cached public key, without accessing the OAuth server through the network. This helps speed up the token verification process.
The Kubernetes Pod now also includes an egress sidecar, which is responsible for obtaining outbound access tokens. Just as with the ingress sidecar, this change means the Service no longer needs to use an authentication SDK to authenticate outbound requests. The following illustration shows how the authentication sidecar architecture differs from the self-authentication approach for outbound requests.
The outbound request process is now as follows:
The Service requests flow to the egress sidecar.
If there is no access token in the egress sidecar cache, the sidecar obtains the access token and stores it. The sidecar supports automatic token refresh. If there is an access token in the sidecar cache, there is no need to send a request to the OAuth server.
The egress sidecar routes the API request carrying the access token to the backend server.
When the Service calls downstream, the egress sidecar adds an access token to the API request. When the access token expires, it is refreshed automatically, accelerating the acquisition of access tokens.
Putting it all together
The diagram below shows the complete lifecycle of a request sent to the Service today.
The upstream service can be a frontend application or backend service consumer. The Service is the application that a single team is responsible for, and the downstream service is a backend service that provides the associated functionality. The ingress and egress sidecars have separate containers and are located in the same Pod as the Service container.
Benefits of the authentication sidecar pattern
Compared with the self-authentication approach, the authentication sidecar pattern offers significant benefits:
Coupling: All coupling between the business system and authentication is removed. Repetitive implementation of identity authentication and authentication token management in the application service is eliminated, and each business service only needs to be configured in the Kubernetes YAML file.
Complexity: The approach reduces the complexity of application systems and delegates authentication to the out-of-process sidecar deployed in the same Pod as the business system. This helps the business system focus more on its own business logic.
Reusability: Using authentication sidecars supports the standardization of identity authentication and token management, independent of the programming language. Teams can easily reuse the sidecar for identity authentication and token management across deployments.
Maintainability: With authentication sidecars, there’s only one code base, so the business only needs to maintain a single authentication SDK instead of one for each Service. The authentication sidecar can be managed as an open source project within the enterprise. It’s also easy to upgrade and replace the OAuth service using only changes in the code base of the authentication sidecar.
The trend towards the adoption of microservices and containerized architectures means, increasingly, systems are being architected as multiple distributed components or services and are frequently run in complex polycloud or hybrid cloud environments.
These types of environments and architectures increase both the surface area requiring authentication and the importance of getting authentication right. The adoption of the seemingly simple self-authentication approach, where microservices are responsible for their own authentication requirements, results in coupled authentication and business logic and the duplication of authentication logic across microservices.
By introducing the authentication sidecar pattern, business logic and authentication logic are decoupled, resulting in more concise and maintainable service code, and the elimination of repeated authentication code across microservices.
The authentication sidecar pattern supports the rapid construction of enduring and scalable microservice systems. It’s also a pattern that can be used for other reusable supporting services, opening the door to a new way of thinking about microservice architecture design.
Disclaimer: The statements and opinions expressed in this article are those of the author(s) and do not necessarily reflect the positions of Thoughtworks.