Secure Communication Between Microservices Without an Identity Server: Product and Order services

DotNet Full Stack Dev
6 min readSep 15, 2024

--

When building microservices, ensuring secure communication between them is crucial. A common approach is to use an Identity Server to issue and manage access tokens for each service. However, when your services are running in the same cluster, using an Identity Server might feel like overkill. The good news is that there are simpler and equally effective ways to secure communication between microservices without relying on an external identity provider.

If you want to go ahead with the Identity server, you can refer to this well-explained article

https://medium.com/@siva.veeravarapu/service-to-service-authentication-using-oauth2-in-net-microservices-product-and-order-services-56c0e00a2086

In this blog post, we’ll explore various strategies to secure communication between two microservices (Product and Order services) within the same cluster, without setting up an Identity Server.

The Problem

Let’s say we have two microservices:

  • Product Service: Manages products in your e-commerce platform.
  • Order Service: Manages customer orders and interacts with the Product service to retrieve product details.

These services need to communicate securely, but since they’re running in the same cluster, you want a solution that doesn’t involve the complexity of setting up and managing an Identity Server. So, what are the alternatives?

Embark on a journey of continuous learning and exploration with DotNet-FullStack-Dev. Uncover more by visiting our https://dotnet-fullstack-dev.blogspot.com reach out for further information.

Alternative Approaches to Secure Communication

1. Mutual TLS (mTLS)

mTLS (Mutual TLS) is one of the most robust ways to secure communication between microservices. With mTLS, both the client (calling service) and the server (receiving service) authenticate each other using certificates. This ensures that only authorized services can communicate with each other.

How It Works:

  • Both the Product and Order services have their own TLS certificates.
  • When the Product service communicates with the Order service, both services authenticate each other during the TLS handshake.
  • This ensures that the communication is secure and only trusted services can interact with each other.

Benefits:

  • Mutual Authentication: Both services must verify each other’s identity.
  • Encryption: Communication is encrypted, ensuring data privacy.
  • No Tokens Required: Authentication is handled through certificates, so there’s no need for tokens.

Implementation:

To implement mTLS, you need to configure certificates for both services and ensure that the client and server validate each other’s certificates. In Kubernetes, you can configure mTLS at the ingress level, or better yet, use a service mesh (which we’ll cover later) to manage this for you.

Here’s a high-level setup:

  1. Generate TLS Certificates: Generate a certificate for each service.
  2. Configure Services to Use Certificates: Configure both services to use their respective certificates for communication.
  3. Validate Certificates: Ensure that each service validates the certificate of the other service before allowing communication.

If you’re using Kubernetes, you can use tools like Cert-Manager to automate certificate generation and renewal.

2. API Gateway with Internal Authentication

An API Gateway can act as a single entry point for all your microservices. While API Gateways are often used for external requests, they can also manage internal communication between services.

How It Works:

  • When the Product service needs to communicate with the Order service, the request passes through the API Gateway.
  • The API Gateway enforces authentication and ensures that only trusted services can communicate with each other.
  • Instead of using complex OAuth2 tokens, you can use a lightweight authentication mechanism like HMAC or a simple JWT (without the need for an Identity Server).

Benefits:

  • Centralized Control: The API Gateway manages security, rate limiting, and routing between services.
  • Simpler Authentication: Instead of OAuth2 or OpenID Connect, you can use lightweight authentication methods like shared secrets or custom tokens.
  • Internal Traffic: The API Gateway can differentiate between internal and external traffic, applying different security policies for each.

Example: HMAC-Based Authentication

You can implement a simple HMAC authentication where both services share a secret key. The calling service (Product) includes a signature in its request, and the receiving service (Order) validates the signature using the shared secret.

// In Product Service (Caller)
var secret = "shared_secret_key";
var message = "order_request_payload";
var signature = GenerateHMACSignature(secret, message);

var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-Signature", signature);
var response = await client.GetAsync("https://api-gateway/orders");

On the Order service side, validate the signature:

// In Order Service (Receiver)
public IActionResult ProcessOrder(HttpRequest request)
{
var receivedSignature = request.Headers["X-Signature"];
var expectedSignature = GenerateHMACSignature("shared_secret_key", "order_request_payload");

if (receivedSignature != expectedSignature)
{
return Unauthorized();
}

// Process the request
}

This setup ensures secure communication using a shared secret, enforced by the API Gateway.

3. Shared Secret Token

A shared secret token is one of the simplest ways to secure communication between two microservices. In this approach, both services agree on a pre-shared secret that is passed along with each request to verify the identity of the calling service.

How It Works:

  • You generate a shared secret (e.g., a token or a key) that both the Product and Order services use.
  • When the Product service makes a request to the Order service, it includes the secret token in the headers.
  • The Order service verifies the token before processing the request.

Benefits:

  • Simplicity: No need for complex token generation or management.
  • Low Overhead: No need for external identity management or token issuers.
  • Security: Communication is secured using a simple shared secret.
// In Product Service (Caller)
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer shared_secret_token");
var response = await client.GetAsync("https://order-service/orders");

On the Order service side, validate the token:

// In Order Service (Receiver)
public IActionResult ProcessOrder(HttpRequest request)
{
var token = request.Headers["Authorization"].ToString().Replace("Bearer ", "");
if (token != "shared_secret_token")
{
return Unauthorized();
}

// Proceed with the request
}

This method works well when you have a limited number of services and need a straightforward approach to secure communication.

4. Service Mesh (Istio, Linkerd)

A Service Mesh is an infrastructure layer that handles service-to-service communication, including security, observability, and traffic management. With a service mesh, you get mTLS and other security features automatically without needing to modify your application code.

How It Works:

  • The service mesh (e.g., Istio or Linkerd) manages secure communication between microservices.
  • It automatically handles mTLS, traffic routing, retries, and access policies between your services.
  • Security policies can be enforced to ensure that only authorized services can communicate with each other.

Benefits:

  • Built-in Security: No need to manage certificates manually or add authentication logic to your code.
  • mTLS by Default: mTLS is automatically applied between services, securing communication at the network level.
  • Observability: Service meshes provide insights into service communication, including traffic patterns, retries, and errors.

Implementation:

  1. Deploy the Service Mesh: Install Istio, Linkerd, or another service mesh in your Kubernetes cluster.
  2. Enable mTLS: Configure mTLS policies for your microservices. This will ensure that only authorized services can communicate with each other, and all communication is encrypted.
  3. Traffic Management: Use the service mesh to route traffic between services, handle retries, and enforce security policies.

Detailed explanation on service mesh with linkerd

https://medium.com/@siva.veeravarapu/service-mesh-with-linkerd-in-a-net-microservice-architecture-e87d3d406b06

5. Kubernetes Network Policies

If your services are running in a Kubernetes cluster, you can use Network Policies to restrict which services can communicate with each other. This approach secures communication at the network level.

How It Works:

  • You define Network Policies to control which services (pods) can talk to each other.
  • For example, you can create a policy that allows the Product service to communicate with the Order service, but no other services can interact with Order.

Benefits:

  • Network-Level Security: Communication is secured at the network layer, making it harder for unauthorized services to access sensitive endpoints.
  • Simple to Implement: Network Policies are declarative and easy to configure within Kubernetes.

Example:

Here’s a sample Network Policy that allows only the Product service to communicate with the Order service:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-product-to-order
namespace: your-namespace
spec:
podSelector:
matchLabels:
app: order-service
ingress:
- from:
- podSelector:
matchLabels:
app: product-service

Conclusion

When your microservices (Product and Order) are running within the same cluster, you have several secure alternatives to using an Identity Server. Depending on your needs and infrastructure, you can choose from:

  • mTLS for robust, certificate-based security.
  • API Gateway for centralized routing and lightweight internal authentication.
  • Shared Secret Tokens for simplicity and ease of use.
  • Service Mesh for fully managed communication and security with minimal manual configuration.
  • Kubernetes Network Policies for network-level communication control.

Each option has its trade-offs in terms of complexity, security, and scalability. For smaller projects, shared secret tokens or API Gateway authentication may suffice, while larger, more complex environments might benefit from a service mesh or mTLS.

Choosing the right approach will depend on your specific architecture, security requirements, and operational complexity. Regardless of the method, securing microservice communication is essential to ensuring a reliable and trusted system.

--

--

DotNet Full Stack Dev
DotNet Full Stack Dev

Written by DotNet Full Stack Dev

Join me to master .NET Full Stack Development & boost your skills by 1% daily with insights, examples, and techniques! https://dotnet-fullstack-dev.blogspot.com

Responses (1)