Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Building Scalable Container-Ready and Secure Microservices Using Spring Boot, Netflix OSS, and Spring OAuth2

DZone's Guide to

Building Scalable Container-Ready and Secure Microservices Using Spring Boot, Netflix OSS, and Spring OAuth2

Learn how to build production-ready microservices with Spring Boot 2 and Netflix OSS and secure your resources using OAuth2.

· Microservices Zone ·
Free Resource

Learn how modern cloud architectures use of microservices has many advantages and enables developers to deliver business software in a CI/CD way.

In this article, I’d like to demonstrate how to design and implement production-ready microservices using Spring Boot 2 and Netflix OSS (Eureka and Zuul) as the big picture, and more in-depth, how to implement HATEOAS-based REST APIs, and how to secure your resources using OAuth2 as a protocol for authentication and authorization issuing JWT. Last but not least, we are wrapping things up by adding a Dockerfile to each of our projects and a recipe to spawn them all together using Docker Compose.

Let’s first talk about the components of this project.

Table of Contents

  1. Introduction
  2. Game of Thrones API
  3. OAuth 2.0 Server
  4. Securing our Resources
  5. Eureka Discovery Server
  6. Zuul Edge Server (API Gateway)
  7. Docker Compose

Introduction

As a high-level architecture of this system, assume that we are building multiple REST API servers, each one for a different TV series or movie of your liking. Shall we start with Game of Thrones? Yes, we shall. This application is designed based on my previous experiences and your architecture may vary according to your requirements.

Game of Thrones API

This is a simple, yet powerful, API meant to expose data we know about people and houses from Game of Thrones. Do you think it’s only meant to show you how to plug a REST project as a microservice to Netflix OSS? You’re wrong… partially. In this particular project, you will find out how to implement Spring AOP to build annotations to monitor your APIs execution and how to implement HATEOAS compliant APIs using a DTO layer to traffic only data we need and lazily fetching our entities relationships, since we have HATEOAS links to avoid querying the entire database when we don’t even want to access all our child attributes. Since we are talking about Eureka as a discovery server, we might as well tell our services how to connect themselves to Eureka. This can be easily accomplished by setting Eureka’s information in our application.yml file.

Hint: In a serious production project, keep your Spring Data entities and repositories in a separate common project as well as your DTO layer (in a different project, of course). This way, all you have to do is import its dependency to your Maven or Gradle file to achieve a reusable module.

OAuth 2.0 Server

The auth-server is responsible for handling the authentication and authorization process of our microservices. It connects with the User, Role, and Permission from our database and issues JWT tokens containing auth-user main attributes and granted authorities and persists them in the database to avoid losing sessions in case our server goes down. In this example, I used MySQL.

Do you feel like you need to enhance the payload of your JWT token? Not a problem. Take a look at the OAuth2Configuration.java file:

Once your server is up and running, you can try to sign in.

$ curl -X POST \
http://localhost:9092/uaa/oauth/token \ 
-H 'authorization: Basic YWRtaW5hcHA6cGFzc3dvcmQ=' \
-H 'content-type: application/x-www-form-urlencoded' \
    -d 'grant_type=password&username=admin&password=password'

And you should get a payload just like this:

{  
   "access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsibXMvYWRtaW4iLCJtcy91c2VyIiwibXcvYWRtaW5hcHAiXSwidXNlcl9uYW1lIjoiYWRtaW4iLCJzY29wZSI6WyJyb2xlX2FkbWluIl0sImV4cCI6MTUyNzY0NDQwMSwiYXV0aG9yaXRpZXMiOlsicm9sZV9hZG1pbiIsImNhbl91cGRhdGVfdXNlciIsImNhbl9yZWFkX3VzZXIiLCJjYW5fY3JlYXRlX3VzZXIiLCJjYW5fZGVsZXRlX3VzZXIiXSwianRpIjoiNTBmYTE0N2EtNDIxYi00NmE5LWI2MDEtMThhOGJlMWQ5OTAzIiwiZW1haWwiOiJhZG1pbkBleGFtcGxlLmNvbSIsImNsaWVudF9pZCI6ImFkbWluYXBwIn0.6P8lhBiFYnsIuNoUi75hUPClGIggbMiuMmlFlzUiqCk",
   "token_type":"bearer",
   "refresh_token":"<refresh_token>",
   "expires_in":899,
   "scope":"role_admin",
   "email":"admin@example.com",
   "jti":"50fa147a-421b-46a9-b601-18a8be1d9903"
}

Hint: You can always go to https://jwt.io/ to decode your JWT payload.

Securing Our Resources

We can easily connect our ms-got server to our OAuth2 server by adding Spring Security’s @EnableResourceServer annotation.

By doing so, we can now secure our resources depending on the users’ granted authorities.

As mentioned above, all our issued access tokens are persisted in our JdbcTokenStore, which means every request made to our Resource Servers has to verify the token passed in the Authorization header. Simply add a ResourceServerTokenServices bean to your ResourceServerConfigurationclass and point the auth-server endpoint for remote check.

Since we can have our application running on different hosts and ports, authEndpoint is externalized as an application property in our application.yml file.

Eureka Discovery Server

As for our services above, and any other you feel like adding to the pile, they are independent services. Some of them are deployed inside a single server machine and others may deploy another server machine. How do we know where everyone is and how do communicate with another service if we don’t know where it is? That’s when you say Eureka! Time to shine.

Eureka works as a catalog, much likely to a Service Registry from SOA world. A sample @EnableEurekaServer in your SpringBoot Application turns your app in a Eureka Server while adding @EnableEurekaClient to your API projects and adding the correct properties to its application.yml file and there you go, your services are federated to Eureka and it now knows exactly where to go to find you.

As soon as your server is up, you can access http://localhost:9091/ and check all services registered in Eureka’s catalog.

Zuul Edge Server (API Gateway)

Here’s the actual entrance to our microservices world, through which external clients (web apps, mobile, third-party APIs) reach our resources. Netflix Zuul is a quite simple and light application which mainly holds Eureka’s endpoint and routes to our microservices. Suppose you have your Zuul hosted at zuul.example.com and your GoT API hosted at ms-got.example.com/v1/; everytime an external client wants to access a GoT info, it will reach zuul.example.com/v1/resource. Then, Zuul will ask Eureka where to find the desired microservice, and finally will reach its endpoint for completing its destiny.

More useful tips about filtering and routing services with Zuul can be found here.

Docker Compose

Nowadays, we have to be fast, be it for deployment, disaster recovery, or migrations. For a modern application, this project wouldn’t be complete if we weren’t ready to deploy our entire stack within a single command line on Docker. In this project’s GitHub repository, you can find a docker-compose file and it’s usage instructions.

All projects (Eureka, Zuul, Auth Server and GoT API) have a Dockerfile within:

FROM openjdk:8-jdk-alpine

#Expose volumes where application.log and application.yml will be generated/replaced.
VOLUME ["/tmp", "/tmp/config", "/tmp/logs"] 

#Set your current Timezone to make sure SLF4J logs the correct timestamp.
ENV TIME_ZONE America/Sao_Paulo

RUN apk --no-cache add \
 tzdata \
    # Set timezone
    && echo "${TIME_ZONE}" > /etc/timezone \ 
 && ln -sf /usr/share/zoneinfo/${TIME_ZONE} /etc/localtime

ADD /target/*.jar app.jar

#Expose the same port set in our application.yml file
EXPOSE 9093

#As soon as the container starts, it will run our .jar application and look for an application.yml file at /tmp/config/ to override the one packaged with its jar.
ENTRYPOINT ["java","-Dspring.profiles.active=docker","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar", "--spring.config.location=classpath:/application.yml,file:/tmp/config/application.yml"]


$ docker-compose up -d
## Check your containers are up and running
$ docker ps


Conclusion

I hope this will help for your future projects. This is the GitHub source project and you can follow the instructions written in each submodule in the readme files to run everything integrated, independently, in a container or not. Follow this recipe to deploy your services wherever it suits you better, from your on-premises datacenter to AWS EC2, Heroku, Cloud Foundry, or Pivotal WebServices. Good luck.

Discover how to deploy pre-built sample microservices OR create simple microservices from scratch.

Topics:
microservices ,rest api ,oauth2 ,jwt ,netflix oss ,eureka ,spring boot ,zuul ,docker ,tutorial

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}