MicroProfile makes it easier to secure your important microservices apps
Cloud-native applications have many challenges. Among them, security is one of the most important areas. When the user is trying to access your application, do you trust the client? Better to verify! Do you think the incoming request coming from the upstream service is safe and secure? Of course, not. Do you know who is accessing it and do they have the right permissions? Hopefully! Of course, programmers are more likely to apply security measures consistently if the required code is standardized and simple.
Securing the data from REST services is very important while building cloud-native applications. Since the data flows across different services, we need to make sure that the data is clean and secure. Also, to allow different users to access the application, we want to verify the user’s identity and their access rights. For MicroProfile applications, you can easily secure your REST API endpoints using a token-based approach with MicroProfile JSON Web Token (JWT) Propagation. To know the basics about JWT, have a look here, and to know more about MicroProfile JWT, have a look at here.
In this blog series, we’re covering how to handle the factors below when handling scalability for Liberty’s MicroProfile-based microservices:
In our last blog post, we covered how to externalize your microservice’s configuration using MicroProfile Config. In today’s entry, you’ll learn how to secure the REST APIs using MicroProfile JWT Propagation. You can learn how we implemented them in our simple storefront application.
For those who may have joined late, this blog series is based on my team’s experience migrating our simple storefront application from a Spring Boot-based microservices to MicroProfile, an optimized microservices programming model for enterprise Java. It was originally coded using Spring Boot (source code) and migrated to MicroProfile (source code). Both the projects are hosted on GitHub with source code and full documentation.
Spring Boot – Authentication and Authorization
Spring Security: For user authorization and authentication, Spring Security Authentication and Authorization server is used. All the RESTful services are protected using OAuth 2.0. The communication client is Spring Feign Client. We used signed JWT Bearer tokens for identity propagation. The flow diagram below shows how we implemented it for the Spring Boot version of BlueCompute:
When a client wishes to acquire an OAuth token to call a protected API, it calls the Auth microservice(OAuth Provider) token endpoint with valid credentials and required scope.
Auth microservice, in turn, calls the identity provider to validate credentials. In our sample application, the Customer microservice is the identity provider. The login credentials are validated with the identity provider using Spring Feign Client.
If the credentials are valid, it returns a JWT signed using a HS256 shared secret in the JSON response under
access_token, which contains the customer ID of the user passed in the
The client uses the JWT in the Authorization header as a bearer token to call other Resource Servers that have OAuth protected APIs. These services verify the JWT and extract the
user_nameclaim from the JWT to identify the caller. The JWT is encoded with the required scope and the expiry time.
Once the token is generated, there is no additional interaction between the Resource Server and the OAuth server until the token expires. This is how the security mechanism works in our simple storefront applicationfor Spring Boot implementation.
For more details, check out how we implemented our Auth service in Spring Boot here.
MicroProfile – Authentication and Authorization
OpenID Connect: For user authorization and authentication in our MicroProfile implementation, the Auth microservice is set up as an OpenID Connect Provider. OpenID Connect is built on top of OAuth 2.0.
In OAuth 2.0, authentication is not done immediately. For this to be done, it contacts the resource provider to acquire the user information. In OpenID Connect, both authorization and authentication are available at the same time. The user information is provided as a set of claims from the UserInfo endpoint. The client receives the user information along with the access token, which is a MicroProfile JWT in our case here, generated from the Token endpoint.
MicroProfile Json Web Token (JWT) Propagation: This feature allows the developers to secure their microservices and propagate user identities using JWTs. This token-based security approach helps in securing the RESTful APIs by generating tokens which consist of the user identity, claims, grants, expiry time, and other useful information. Whenever a user requests a service, they will be permitted to use it if the token is valid. Once the token is generated, there is no need of going back to the Auth server. But if the token expires, the user access will be denied and they will be redirected to the Auth server.
The flow diagram below depicts how we implemented it on the MicroProfile version of BlueCompute:
Initially, the client interacts with the Auth service, which validates the user credentials. Later, when the client wishes to call a protected API:
The client requests an access token to call a protected API by calling the Auth microservice (OpenID Connect Provider) token endpoint with valid credentials and required scope.
The Auth microservice will then perform the validation. If the credentials are valid, it returns a MicroProfile JWT as an
The client uses the access token in the Authorization header as a bearer token to call other Resource Servers having the REST endpoints secured with MicroProfile JWT Propagation. These services verify the MicroProfile JWT in the request and extract the required claims from the MicroProfile JWT to identify the caller.
The MicroProfile JWT contains the required scope and the expiry time. Once the token is generated, there is no additional interaction between the Resource Server and the OpenID Connect Server unless the token expires. This is how the security mechanism works in our simple storefront application for MicroProfile implementation.
Define an authentication server that handles user authentication and authorization using Liberty’s OpenID Connect 1.0 feature.
Use MicroProfile JWT Propagation to secure the REST services. This MicroProfile JWT Bearer token helps us to validate the user identity as well as the permissions associated with the user.
For more details, check out how we implemented our Auth Service for our sample application here.
Contrasting MicroProfile and Spring Boot security implementations
Let us now dive further into the technical details. In order to access protected resources in your application, Authorization and Authentication are required.
Authentication: Verifying the user has the right to access the system based on their identity.
Authorization: Verifying the user has the rights to perform specific actions.
Configuring the Auth server: In a Spring Boot application, code does mostly everything. In a Liberty application, we configured WebSphere Liberty as our Auth Server using the OpenID Connect feature and server configuration does most of it. Personally, I felt Liberty’s declarative approach is a lot easier because the server takes care of the details and there is no need for the developer to worry about the code.
REST services consuming JWTs: In the Spring Boot application, REST APIs are secured using OAuth2.0. The access token used is a JWT token signed using a HS256 shared secret. In the MicroProfile application, REST APIs are secured using MicroProfile JWT Propagation. The access token used is MicroProfile JWT.
The REST APIs are now all secured. For more details on how the Auth service is built, refer to the project introduction on GitHub. To run the whole application together, please check out the BlueCompute – MicroProfile implementation on GitHub.
Microservices have many benefits, and given their strategic importance, securing them is critical. Using MicroProfile, you can safely secure your RESTful services with MicroProfile JWT Propagation. When working on securing our services with MicroProfile, the guide from Open Liberty Securing microservices with JSON Web Tokens was very helpful.
This blog demonstrates how we migrated the security of our reference application from Spring Boot to MicroProfile. In our previous blog posts, we covered some interesting topics like RESTful APIs, Dependency Injection, REST Client, JSON-B, and externalizing configurations. In the next installment, we’ll close on the final subject of scaling microservices, fault tolerance.