- Lab
- Core Tech

Guided: Security Best Practices in Microservices Integration
Microservices often need to exchange sensitive data internally. In some cases, using OAuth or external identity providers is not feasible due to infrastructure constraints. This hands-on lab walks you through a secure integration between two microservices using internal mechanisms such as API keys, request signing with HMAC, and message encryption. By the end of this lab, you will have practical experience securing services without relying on external authentication systems.

Path Info
Table of Contents
-
Challenge
Introduction
In this lab, you will secure the internal communication between two Spring Boot microservices , an
order-service
and aninventory-service
. Initially, these services communicate over HTTP with no security, which poses significant risks. You will incrementally add security measures (API keys, HMAC signatures, and payload encryption) to protect their interactions. By the end, you’ll understand how to enforce authentication and integrity for internal API calls and ensure confidentiality of data even if TLS is compromised.Learning Objectives
- Recognize the risks of unsecured internal microservice communication (e.g. unauthorized access and data interception).
- Implement API key authentication to restrict access to trusted services.
- Apply HMAC signatures to ensure message integrity and authenticity.
- Encrypt sensitive data using AES to maintain confidentiality in transit. >If you get stuck on a task, you can view the solution in the
solution
folder in your Filetree, or click the Task Solution link at the bottom of each task after you've attempted it.
-
Challenge
Assessing Risks in Unsecured Microservice Communication
You are a developer responsible for securing an Order Management system built with two microservices:
order-service
: Handles incoming order requests (product ID and quantity) and delegates stock updates toinventory-service
inventory-service
: Processes inventory updates and returns the remaining stock for the specified product
Observe Unsecured Communication
At this stage, the system allows any service to call the inventory API without authentication, and order data is transmitted in plain JSON format. In this lab, you will begin by examining this unsecured interaction and then progressively enhance its security.
order-service
runs on port8081
.inventory-service
runs on port8082
.
To begin, start the
order-service
andinventory-service
in the first and second Terminal tabs respectively.In first Terminal start
order-service
:cd order-service mvn spring-boot:run
In second Terminal start
inventory-service
:cd inventory-service mvn spring-boot:run
Now trigger an order by sending a request to the
order-service
. It will internally forward the request to theinventory-service
athttp://localhost:8082/api/inventory/
. You should receive the following response:Inventory updated for product P123. New stock: 98
You can also observe the logs in the other Terminals:
Order Service:
Sending Order to Inventory Service {"productId":"P123","quantity":2}
Inventory Service:
Received Order In Inventory Service - {"productId":"P123","quantity":2}
Notice that the call succeeds without any authentication, and the JSON data (product ID and quantity) is transmitted in plaintext.
Risks of Unsecure Communication
1. Unauthorized Access
Without authentication mechanisms like API keys, any service or external client can call sensitive internal APIs. This opens the door to abuse, such as unauthorized inventory updates or data leaks.
2. Data Tampering
If requests are not signed or verified, an attacker could intercept and modify the payload (e.g., changing product quantity or ID) during transit, leading to incorrect updates or malicious actions in the system.
3. Lack of Confidentiality
Transmitting plain JSON over the network exposes sensitive business data (like inventory levels or pricing) to on-path attackers. Anyone snooping the traffic can read and misuse this information.
These are serious vulnerabilities that you will address in the coming steps.
-
Challenge
Securing Access with API Keys
Addressing Unauthorized Access
In this step, you will implement a simple API key mechanism to ensure that only the
order-service
can access theinventory-service
API.An API key is a unique token that the client (
order-service
) sends with each request to identify itself. Theinventory-service
will check for this key and reject requests that don’t have it or have the wrong value. This is a basic form of authentication suitable for service-to-service communication when a full OAuth flow is undesired.info> Note: Why API keys? Using a static API key in internal calls provides a lightweight authentication layer. It’s essentially a shared secret that identifies trusted callers. While not as robust as user-based authentication, it helps ensure only authorized services (with the key) can invoke the API. Now, you will update the order service to send an API key header (
X-API-KEY
) in all outgoing requests. --- Next, in the inventory service, receive the incoming API key. Now, validate the API key by matching it with the expected API key stored in the inventory service. To test the APIs, restart both the order and inventory services using the first and second Terminals.You can stop a running service by pressing
Control+C
in its Terminal tab.Then, use the command
mvn spring-boot:run
in each service directory to start them again. To test how the system handles invalid API keys, modify theapplication.properties
file inorder-service
with an incorrect key. After saving the change, restart the service and send a request. Theinventory-service
will respond with a401 Unauthorized
error.
In this step, you have added a basic authentication layer: only
order-service
(knowing the key) can talk toinventory-service
. However, the data in transit is still unprotected and an attacker could intercept or alter it. You will address that next step. -
Challenge
Adding HMAC-based Signature Validation
Preventing Data Tampering
While an API key restricts access to trusted services, it doesn't protect the contents of the request from being altered in transit. To address this, you will implement Hash-Based Message Authentication Code (HMAC) to detect any tampering.
An HMAC is a secure hash generated from the request payload and a shared secret key. The sender (
order-service
) generates this hash and includes it in a custom header. The receiver (inventory-service
) recalculates the HMAC using the received data and the same shared key. If the two signatures differ, the request is considered modified or untrusted and is rejected.This mechanism ensures that:
- The request was not altered during transit (data integrity)
- It was sent by a trusted source that knows the shared secret (authenticity)
You will start by updating the
OrderService
to enable generation of HMAC signature in the header. --- Now, you will update theInventoryController
to receive and validate the HMAC signature. > Note: Make sure you restart the order and inventory services in order for changes to be applicable. With this implementation, theinventory-service
verifies the HMAC signature to ensure the message hasn’t been tampered with. Even a small change in the JSON causes a mismatch, and the request is rejected as "Unauthorized: Invalid HMAC signature". This confirms both integrity and authenticity of the request.
At this point, you have authentication (API key) and integrity protection (HMAC). But the data itself, however, is still in plaintext JSON.
If the traffic is not encrypted at the transport layer (or an attacker somehow breaks TLS), sensitive information could be exposed. In the next step, you will encrypt the request payload for confidentiality.
-
Challenge
Encrypting Request Bodies
Addressing Lack of Confidentiality
The final security enhancement is to encrypt the data exchanged between services. You will use Advanced Encryption Standard (AES), a symmetric-key cipher, to encrypt the JSON payload in the order-service and decrypt it in the inventory-service.
AES uses the same secret key for both encryption and decryption. By encrypting the request body, even if an attacker intercepts the HTTP call, the content will be unintelligible without the AES key. This adds a strong confidentiality layer on top of our existing integrity checks.
In practice, before sending the request, the order service will transform the JSON (e.g.
{"productId":"P123","quantity":5}
) into an encrypted string using a secret key. The inventory service will decrypt it back to JSON after receiving the request.info> Note: You will use a shared AES key known to both services. For simplicity, you’ll use a static key. In real systems, keys should be securely generated and rotated.
Now, you will update the order service to initialize a cipher and send encrypted order to inventory service. --- Since
EncryptedOrder
is now being sent from the order service, the inventory service must receive and processEncryptedOrder
instead ofOrder
. Now, you will test the endpoint.Note: Please make sure to restart the order and inventory services. With encryption enabled, the order service now sends an encrypted payload and the inventory service decrypts it transparently. The HMAC signature implemented in Step 4 continues to work on the encrypted data (signature is generated after encryption in the order service). This means the integrity check is now protecting the ciphertext. The inventory service verifies the HMAC on the ciphertext, then decrypt to get the plaintext JSON for processing. info> Note: In a real-world implementation, you would use a more secure mode than ECB for AES (e.g., CBC with an IV, or GCM mode which also ensures integrity). Also, secrets like API keys and HMAC/AES keys should be stored securely (not hard-coded) and rotated periodically.
At this stage, the two services trust each other (via API key), any tampering is detectable (via HMAC), and the data is confidential (via AES encryption) all achieved without an OAuth server or user identity, suitable for internal microservice-to-microservice protection.
-
Challenge
Conclusion and Next Steps
Congratulations!
You have successfully implemented layered security across microservices using:
- API keys to restrict access to trusted callers
- HMAC signatures to ensure message integrity
- AES encryption to protect sensitive data during transmission
Together, these mechanisms help ensure that:
- Only authorized services can communicate
- Payloads are protected from tampering
- Data remains confidential throughout its journey
What to Explore Next
To strengthen your setup further, consider the following enhancements:
-
Rate Limiting and Monitoring - Protect services from abuse and detect anomalies by monitoring API usage and enforcing request limits.
-
Key Rotation - Regularly update API keys and encryption secrets to minimize risks from accidental leaks or misuse.
-
Mutual TLS (mTLS) - Add two-way certificate authentication to validate both the client and the server at the transport layer.
This lab demonstrated how internal service-to-service communication can be secured without relying on OAuth or external identity providers. By layering simple yet effective techniques, you have built a solid foundation for secure microservice integration.
Continue to evolve this model by combining these patterns with transport-level protections and service mesh capabilities. Security is most effective when applied in layers, each reinforcing the other to keep your systems resilient and trustworthy.
What's a lab?
Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.
Provided environment for hands-on practice
We will provide the credentials and environment necessary for you to practice right within your browser.
Guided walkthrough
Follow along with the author’s guided walkthrough and build something new in your provided environment!
Did you know?
On average, you retain 75% more of your learning if you get time for practice.