Securing Microservices with JWT
- The Tech Platform
- May 31, 2022
- 5 min read
This article explains how to secure your microservices deployment practically with JWT Auth using Ballerina programming language. Ballerina has first-class support for a whole bunch of security features from transport layer security like SSL/TLS, mTLS to application layer security like Basic Authentication (Basic Auth), JWT Authentication, OAuth2, etc. Let’s see how we can apply JWT Auth for microservices deployment.

For the simplicity of this article, let’s consider a hypothetical order management system application, which has microservices and components programmed with Ballerina. Let’s see how to design, implement, test, deploy and observe the system.
Design
The following figure illustrates a high-level design diagram of the complete use case.

Figure 1 — High-level design diagram of order management system
The end-user (customer), in this example, Alice and Bob, interacts with the system using the web/mobile app provided. This web/mobile app acts as a Client on behalf of the user’s actions and calls to the API Gateway. The API Gateway routes the requests to Order Service, which is responsible for processing the order for the customer. The Inventory Service is called by the Order Service to process the inventory-related operations.
The API Gateway intercepts the request from the end-user, extracts the token, and then talks to the STS connected to validate the token.
After validating the token, the STS issues a new JWT signed by itself. This JWT includes the user details.
The API Gateway passes the new JWT to the Order Management Service, and it needs only trust this STS to accept the token as valid. The Order Management Service validates the signature of the JWT to make sure that it’s issued by the STS it trusts. Apart from the signature validation, the Order Management Service also does the issuer and audience validation.
The Order Service talks to Inventory Service with mTLS (mutual TLS).
Implementation
We can get started with the Ballerina service; Order Service, which is a RESTful service that serves the order management requests. We will look at securing multiple resources exposed by Order Service to match with the different security requirements.
Create Order: Order creation should only be allowed for authenticated users.
Retrieve Order: Retrieval of the order details should be allowed for all the users.
Update Order: Updating order details should only be allowed for “admin” users.
Delete Order: Deletion of the order should only be allowed for “admin” users.
Authentication is enabled by setting the auth attribute of http:ServiceConfig or http:ResourceConfig. If we configure the auth attribute of http:ServiceConfig it will be applied to all the resources of the configured HTTP Service. Also, the security enforcement that is done for the service using the http:ServiceConfig can be overridden by the http:ResourceConfig annotation for a specific API(s).
For this example Order Service, we need to configure the auth attribute of all the resources except the “Retrieve Order” resource, since we need to allow that for all the users.
Ballerina uses the concept of ‘scope’ as the way of expressing authorization. Multiple scopes can be assigned to a user, and scopes can then be validated while enforcing authorization. To express that a certain service or resource require a scope, we have used the scopes annotation attribute of the auth annotation attribute.
For this example Order Service, we need to configure the scopes attribute for all the resources except the “Retrieve Order” resource, since we need to allow that for all the users.
Testing
We can run the Order Service that we developed above, in our local environment. To complete the design diagram illustrated above, we have to run the Mock STS, and the Inventory Service first.
Open the terminal and navigate to examples/order-management-service/sts directory and execute the following command.
$ bal run
The successful execution of the service should show us the following output.
Compiling source
jwt/sts:1.0.0
Running executable
Now, navigate to examples/order-management-service/inventory_service directory and execute the same command. The successful execution of the service should show us the following output.
Compiling source
jwt/inventory_service:1.0.0
Running executable
Now, navigate to examples/order-management-service/order_service directory and execute the same command. The successful execution of the service should show us the following output.
Compiling source
jwt/order_service:1.0.0
Running executable
Now, we can test authentication and authorization checks being enforced on different functions of the Order Service by sending HTTP requests. For example, we have used the CURL commands to test each operation of the Order Service as follows.
Create Order
Without authentication
$ curl -k -v -H "Content-Type: application/json" \
-d '{"id": "100500", "name": "Sample order", "items": [{"category": "electronics", "code": "SOWH1000XM4", "qty": 2}, {"category": "books", "code": "978-1617295959", "qty": 1}]}' \
"https://localhost:9090/order"
Output:
< HTTP/1.1 401 Unauthorized
< content-length: 0
< server: ballerina
< date: Tue, 24 Aug 2021 06:33:52 +0530
Authenticating as the ‘counter’ user, who has ‘add_order’ permission
$ curl -k -v -H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsICJ0eXAiOiJKV1QiLCAia2lkIjoiTlRBeFptTXhORE15WkRnM01UVTFaR00wTXpFek9ESmhaV0k0TkRObFpEVTFPR0ZrTmpGaU1RIn0.eyJpc3MiOiJ3c28yIiwgInN1YiI6ImNvdW50ZXIiLCAiYXVkIjoiYmFsbGVyaW5hIiwgImV4cCI6MTk0NTIzODg5NCwgIm5iZiI6MTYyOTg3ODg5NCwgImlhdCI6MTYyOTg3ODg5NCwgImp0aSI6ImY1YWRlZDUwNTg1YzQ2ZjJiOGNhMjMzZDBjMmEzYzlkIiwgInNjb3BlIjoiYWRkX29yZGVyIn0.FMDL-Y8zMtAW7vBVeEbwf_8ynSKdjAkuEBVJpoGds06Z2cOrL3WPZYswnbUOzULBnOXQJQEnK-P-QmypvqP0NWGpzfoC5QMqg0FhPvxyglP1QNYbrS_5tZFM_7Nn7tBFZxiBq666AzjDyhZ2jc39X9rftV0m8p4yyFdSI4KFiEzQ8eOWVVOIg3ejQ0ruDlSVvwx3lXe03XYmrhQp0m-_KYm-SGV3HTZttbo00A250pVY1QL137WDgeeDtGchOfjvM9G-UL8t3sw1Lyoq4OzblHEJJQOJnfRLM_nFKeULuAtt5k_UwmQRlV-XrgxMk0lu6KvYt1-Sa1HMiS8aIvrwig" \
-d '{"id": "100500", "name": "Sample order", "items": [{"category": "electronics", "code": "SOWH1000XM4", "qty": 2}, {"category": "books", "code": "978-1617295959", "qty": 1}]}' \
"https://localhost:9090/order"
Output:
< HTTP/1.1 201 Created
< Location: http://localhost:9090/order/100500
< content-type: application/json
< content-length: 36
< server: ballerina
< date: Tue, 24 Aug 2021 06:34:05 +0530
{"status":"Order '100500' created."}
Retrieve Order
$ curl -k -v "https://localhost:9090/order/100500"
Output:
< HTTP/1.1 200 OK
< content-type: application/json
< content-length: 70
< server: ballerina
< date: Tue, 24 Aug 2021 06:34:20 +0530
{"id":"100500", "name":"Sample order", "items":[{"category":"electronics", "code":"SOWH1000XM4", "qty":2}, {"category":"books", "code":"978-1617295959", "qty":1}]}
Update Order
Without authentication
$ curl -k -v -X PUT -H "Content-Type:application/json" \
-d '{"name": "Updated order", "items": [{"category": "electronics", "code": "SOWH1000XM4", "qty": 1}]}' \
"https://localhost:9090/order/100500"
Output:
< HTTP/1.1 401 Unauthorized
< content-length: 0
< server: ballerina
< date: Tue, 24 Aug 2021 06:34:32 +0530
Authenticating as ‘counter’ user, who has ‘add_order’ permission
$ curl -k -v -X PUT -H "Content-Type:application/json" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsICJ0eXAiOiJKV1QiLCAia2lkIjoiTlRBeFptTXhORE15WkRnM01UVTFaR00wTXpFek9ESmhaV0k0TkRObFpEVTFPR0ZrTmpGaU1RIn0.eyJpc3MiOiJ3c28yIiwgInN1YiI6ImNvdW50ZXIiLCAiYXVkIjoiYmFsbGVyaW5hIiwgImV4cCI6MTk0NTIzODg5NCwgIm5iZiI6MTYyOTg3ODg5NCwgImlhdCI6MTYyOTg3ODg5NCwgImp0aSI6ImY1YWRlZDUwNTg1YzQ2ZjJiOGNhMjMzZDBjMmEzYzlkIiwgInNjb3BlIjoiYWRkX29yZGVyIn0.FMDL-Y8zMtAW7vBVeEbwf_8ynSKdjAkuEBVJpoGds06Z2cOrL3WPZYswnbUOzULBnOXQJQEnK-P-QmypvqP0NWGpzfoC5QMqg0FhPvxyglP1QNYbrS_5tZFM_7Nn7tBFZxiBq666AzjDyhZ2jc39X9rftV0m8p4yyFdSI4KFiEzQ8eOWVVOIg3ejQ0ruDlSVvwx3lXe03XYmrhQp0m-_KYm-SGV3HTZttbo00A250pVY1QL137WDgeeDtGchOfjvM9G-UL8t3sw1Lyoq4OzblHEJJQOJnfRLM_nFKeULuAtt5k_UwmQRlV-XrgxMk0lu6KvYt1-Sa1HMiS8aIvrwig" \
-d '{"name": "Updated order", "items": [{"category": "electronics", "code": "SOWH1000XM4", "qty": 1}]}' \
"https://localhost:9090/order/100500"
Output:
< HTTP/1.1 403 Forbidden
< content-length: 0
< server: ballerina
< date: Tue, 24 Aug 2021 06:34:55 +0530
Authenticating as ‘admin’ user, who has ‘add_order, update_order, cancel_order’ permissions
$ curl -k -v -X PUT -H "Content-Type:application/json" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsICJ0eXAiOiJKV1QiLCAia2lkIjoiTlRBeFptTXhORE15WkRnM01UVTFaR00wTXpFek9ESmhaV0k0TkRObFpEVTFPR0ZrTmpGaU1RIn0.eyJpc3MiOiJ3c28yIiwgInN1YiI6ImFkbWluIiwgImF1ZCI6ImJhbGxlcmluYSIsICJleHAiOjE5NDUyMzY1OTksICJuYmYiOjE2Mjk4NzY1OTksICJpYXQiOjE2Mjk4NzY1OTksICJqdGkiOiJkMWI4NjNlNjc1N2M0ZjJlYjViMjM3YjI5ZmRhOGZhZSIsICJzY29wZSI6WyJhZGRfb3JkZXIiLCAidXBkYXRlX29yZGVyIiwgImNhbmNlbF9vcmRlciJdfQ.XxThNFztJTpn9FIk-9JfEm_xF8sbTwGnNa5bOl-l4lb3KfeV5ojAKEmjenpQR_2YctT2GM68mxunXP4CTxXoAVHAYWDmV10wkR4r7R6LO3wDJDqr7POC3zwtM-n9Ro-gWJEio-SLYw04kxExvjsE1aFa7pRJFuAFDIdAqnXkEaHLXshmOCgxYhAMzdgBQzUtBo7QmjQZf_0kPUioPpNNsDV4bGLQTeZo-SCZhfhvbHBrUsY2VVleUg0_gNVMmT0ySFQ8Jci4CaiglYrxQN9byS38_9qXtWINYEMbtApHaeyl4-0YvY5p8EbJes2ep_r0Q_Od6FQzGekFAVO4gSE6Zw" \
-d '{"name": "Updated order", "items": [{"category": "electronics", "code": "SOWH1000XM4", "qty": 1}]}' \
"https://localhost:9090/order/100500"
Output:
< HTTP/1.1 200 OK
< content-type: application/json
< content-length: 36
< server: ballerina
< date: Tue, 24 Aug 2021 06:35:07 +0530
{"status":"Order '100500' updated."}
Cancel Order
Authenticating as ‘admin’ user, who has ‘add_order, update_order, cancel_order’ permissions
$ curl -k -v -X DELETE \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsICJ0eXAiOiJKV1QiLCAia2lkIjoiTlRBeFptTXhORE15WkRnM01UVTFaR00wTXpFek9ESmhaV0k0TkRObFpEVTFPR0ZrTmpGaU1RIn0.eyJpc3MiOiJ3c28yIiwgInN1YiI6ImFkbWluIiwgImF1ZCI6ImJhbGxlcmluYSIsICJleHAiOjE5NDUyMzY1OTksICJuYmYiOjE2Mjk4NzY1OTksICJpYXQiOjE2Mjk4NzY1OTksICJqdGkiOiJkMWI4NjNlNjc1N2M0ZjJlYjViMjM3YjI5ZmRhOGZhZSIsICJzY29wZSI6WyJhZGRfb3JkZXIiLCAidXBkYXRlX29yZGVyIiwgImNhbmNlbF9vcmRlciJdfQ.XxThNFztJTpn9FIk-9JfEm_xF8sbTwGnNa5bOl-l4lb3KfeV5ojAKEmjenpQR_2YctT2GM68mxunXP4CTxXoAVHAYWDmV10wkR4r7R6LO3wDJDqr7POC3zwtM-n9Ro-gWJEio-SLYw04kxExvjsE1aFa7pRJFuAFDIdAqnXkEaHLXshmOCgxYhAMzdgBQzUtBo7QmjQZf_0kPUioPpNNsDV4bGLQTeZo-SCZhfhvbHBrUsY2VVleUg0_gNVMmT0ySFQ8Jci4CaiglYrxQN9byS38_9qXtWINYEMbtApHaeyl4-0YvY5p8EbJes2ep_r0Q_Od6FQzGekFAVO4gSE6Zw" \
"https://localhost:9090/order/100500"
Output:
< HTTP/1.1 200 OK
< content-type: application/json
< content-length: 36
< server: ballerina
< date: Tue, 24 Aug 2021 06:35:26 +0530
{"status":"Order '100500' removed."}
Deployment
Once we are done with the development, we can deploy the service using any of the methods that are listed below.
Deploying Locally
As the first step, we can build Ballerina executable files (.jar) of the microservices that we developed above. Open the terminal and navigate to examples/order-management-service/sts, examples/order-management-service/inventory_service and examples/order-management-service/order_service directories, and execute the following command for each of them.
$ bal build
The successful execution of the above command should show us the following outputs in order.
Compiling source
jwt/sts:1.0.0
Generating executable
target/bin/sts.jar
Compiling source
jwt/inventory_service:1.0.0
Generating executable
target/bin/inventory_service.jar
Compiling source
jwt/order_service:1.0.0
Generating executable
target/bin/order_service.jar
Once the *.jar files are created inside the target/bin directories, we can run the microservices with the following commands in order.
$ bal run target/bin/sts.jar
$ bal run target/bin/inventory_service.jar
$ bal run target/bin/order_service.jar
Deploying Code to Cloud
Ballerina code to cloud supports generating the deployment artifacts of the Docker and Kubernetes. Refer to Code to Cloud guide for more information.
Observability
HTTP/HTTPS based Ballerina services and any client connectors are observable by default. Observing Ballerina Code guide provides information on enabling Ballerina service observability with some of its supported systems.
Summary
In this article we focussed how to secure your microservices deployment practically with JWT Auth using Ballerina programming language.
Resource: Medium - Chanaka Lakmal
The Tech Platform
Loved the real-world use case with the Order and Inventory Service. Makes it easier to follow. If you're as curious as I am about solutions blogs, I strongly suggest taking a look at my latest post. In today’s digital world, a stable and secure WiFi connection is essential for work, entertainment, and staying connected with friends and family. At Callroutersupport, we specialize in providing reliable technical assistance for all router-related issues, including ATT devices. Whether you want to know att reset wifi password or need detailed guidance on how to reset wifi password att, our expert support team is here to help.
This blog will walk you through the step-by-step process of resetting your ATT WiFi password, explain why it’s important, and…
Good to know Ballerina supports scopes and role-based access natively. This is great for secure APIs. If you're as curious as I am about solutions blogs, I strongly suggest taking a look at my latest post. Yahoo Mail remains one of the most popular email services globally, but like any platform, users sometimes face challenges that can disrupt their email experience. Whether you are dealing with a yahoo account hacked, experiencing yahoo email not receiving issues, struggling with spam settings yahoo mail problems, need help to set up yahoo account, or encountering yahoo mail issues on iphone, the experts at Callcontactsupport are here to help.
In this blog, we will walk you through the most common Yahoo Mail problems and how Callcontactsupport can assist you…
Thanks for walking through authentication and authorization with clear code examples. Really useful! If you're as curious as I am about solutions blogs, I strongly suggest taking a look at my latest post. Are you facing issues like Nest Doorbell not connecting or struggling with Nest Doorbell setup? Maybe your Nest Camera not connecting to wifi or dealing with Nest Camera offline errors? Don’t worry — you’re not alone. These are common issues that many Nest users face, and at Callhelpsupport, we specialize in providing easy-to-follow solutions to get your devices back online.
Nest smart home devices are popular for their sleek design, advanced features, and reliability. However, even the best technology can sometimes run into connectivity or setup issues. Whether you’ve just purchased…
Very informative post! I appreciate how you included practical CURL commands to test the service. If you're as curious as I am about solutions blogs, I strongly suggest taking a look at my latest post. Experiencing issues with your HP printer not printing can be incredibly frustrating, especially when you're in a rush or working from home. Whether you're dealing with an hp 3830 not printing issue, an hp 2700 printer not printing error, or your hp envy 6000 not printing anything on paper, or even the stubborn hp envy 7640 will not print problem—Callhelpcenter has the right troubleshooting solutions for you.
Modern HP printers are designed to be user-friendly, yet sometimes they fail to perform as expected. In this comprehensive guide, we’ll look into…
This guide helped me understand how token validation works in a microservices setup. Thanks for the detailed explanation! If you're as curious as I am about solutions blogs, I strongly suggest taking a look at my latest post. Smart home technology has made significant strides in recent years, and Techhelpsupport is dedicated to helping users make the most of their devices. One of the most popular smart devices for home security is the Ring Doorbell. While it offers convenience, safety, and peace of mind, users often face technical issues that disrupt its performance. Common problems include the Ring Doorbell not working when pressed, Ring Doorbell connection issues, and messages indicating that the Ring Doorbell says offline.
This blog will guide you through these…