How can you find the right childcare provider center?

After the baby is born, parents can take leave for a certain period of time to take care of their child. But after that, both of them have to start working and get busy in their own lives. This is…

Smartphone

独家优惠奖金 100% 高达 1 BTC + 180 免费旋转




Spring Boot 2 Authorization Service

This is an article describing one of the core services in cloud microservice architecture. It illustrates a detailed step-by-step guide on how to create a production ready authorization service using Spring Boot 2, secure it with JWT, build with Gradle, containerize with Docker, authenticate clients with OAuth2 and store users with a DB, MongoDB in this particular case.

This article helps avoiding possible pitfalls that would be met while setting the new service from scratch and preparing it to be integrated into the cloud infrastructure.

It doesn’t cover any cloud infrastructural stuff like discovery services, load balancers, HTTP REST clients etc.

Authentication service developed here will use probably most popular authorization solution and the securest one: OAuth2 + JWT. This approach allows issuing different tokens for different scenarios, signed JWT will contain OAuth2 scopes, user name and user authorities (roles).

Some use cases showing what auth service issues tokens for:

The service issues a JWT token and signs it with a private key whilst all other resource services will decrypt it with a public key.

The key pair is encoded with the RSA256 encryption algorithm.

The service will also have a db connection, this is an optional feature, because main clients could be stored in memory or in some secure external key storages. In this case service would store users, that’d fit the Spring’s UserDetails interface, in the database thus the authorization database would live separately from other databases satisfying the requirements of microservice architecture.

There are some problems that would make you stuck and block further development until the solution is found. Those are already solved in current realization and are related to:

This project is built with gradle, just because I like the syntax better than XML-styled maven one. We will not focus on the basic steps of how to create a gradle project but on the creation of the secure key pair and required project dependencies.

First of all generate a JWT token keystore.

Then generate the public key for our keystore. This public key will be stored in resource services.

This code is necessary to be able to run the project with versions of Java 9 and higher, if this part is commented out, the project could be run with Java 8. This step may be helpful when integrating this into some old fashioned enterprise solutions.

The list of the next dependencies, that are necessary for this particular project.

This is the basic application.yml properties configuration:

The thing worth mentioning here is the database settings, for proper microservice architecture it’s better to specify a separate database for this service only to make data distributed.

Spring actuator management settings allow to specify the health check of the service as well as the health check of the db, in such a way if a connection to db drops service will notify about it.

Main class initiates the spring boot application and performs all the configurations necessary to be done before the application launch. The only required annotation is @SpringBootApplication one.

This annotation is a syntax sugar for a set of annotations that trigger auto-configuration, scan of spring components across the project and a @Configuration annotation and this lets to declare beans inside the main class.

This interface indicates that beans should run when those are contained inside the spring application. In our case main class implements this interface just for example, and this allows to create default users for testing purposes on the application startup.

This bean describes the creation of default users, careful, this code should not be present even on the dev environment, users should be created in the database independently or through the API, but this article describes the authorization service and this code allows to use any database under the hood without sticking to the implementation. We just create several users for demo purposes.

It’s worth mentioning that UserDetails interface is a part of spring security package and the implementations of this class are intended to store user information which is later encapsulated into {@link Authentication} objects. This allows non-security related user information (such as email addresses, telephone numbers etc) to be stored in a convenient location.

By implementing this interface we make sure that some handful properties are stored as part of a user model such as username, password or authorities.

Username should align with the username field in the JWT token. This username will be used to filter out different data sets. And endpoint will return data related to the requested users out of the box.

This particular method gets information about current logged in user by getting user’s name from Principal object that is a part of javax security.

Please ignore the @PreAuthorize annotations, those will be covered later.

The main part of the authorization service is a package with a set of configuration files that issue tokens, enable OAuth2 and secure all endpoints and add CORS filtering.

This package contains all @Configuration annotated classes that will be processed by the Spring to generate bean definitions and service requests for those beans at runtime.

All configuration classes are processed in the default order and some of those should come first and some after in order not to override each ones definitions but complete one another.

This configuration class enables basic web security for REST endpoints, introduces some handful beans like password encoder or authentication manager one.

It is important to only configure AuthenticationManagerBuilder in a class annotated with either @EnableWebSecurity, @EnableGlobalMethodSecurity, or @EnableGlobalAuthentication. Doing otherwise has unpredictable results.

This is the most important configuration class, it lets authorization service to work with OAuth2.

This is achieved by the @EnableAuthorizationServer.

This annotation verifies that many features of the server can be customized using @Beans of type AuthorizationServerConfigurer (e.g. by extending AuthorizationServerConfigurerAdapter).

Most important endpoint for us — /oauth/token will be automatically secured using HTTP Basic authentication on the client’s credentials with the help of the authentication manager bean created in the WebSecurity configuration class.

Here we create 3 Beans and inject AuthenticationManager bean.

This configuration does a lot.

Let’s review it step-by-step.

@Configuration — declares the class that would be scanned by Spring’s component scanner and treated as the configuration one.

@EnableResourceServer — this convenient annotation for OAuth2 resource servers, enabling a Spring Security filter that authenticates requests via an incoming OAuth2 token. It’s important to mention that this annotation creates WebSecurityConfigurerAdapter with Order(3). This is important to understand hence this configuration will be applied after SimpleCorsFilter.java and OAuth2Configuration.java and after WebSecurityConfig.java.

@EnableGlobalMethodSecurity(prePostEnabled = true) — this annotation is necessary for @PreAuthorize annotation to work.

It’s important that combination of @EnableResourceServer and @EnableGlobalMethodSecurity annotations come together on this config for #oauth2.hasScope to work or else just hasAuthority() will work inside the @PreAuthorize annotation.

This filter should be initiated first in the filter chain and set the headers and process the requests for CORS. Basically this is necessary for requests from localhost from browsers to work, since modern browsers use fetch to do the requests and fetch has OPTIONS HTTP method under the hood. If this filter is not initiated the requests from localhost to the remote service will fail.

CORS requires the set of following HTTP headers to be set on response as well.

There’s not so many constants in this particular example, just for convenience there’s only 1 class that contains the conditions restricting the access to controller methods that will be injected into @PreAuthorize annotation.

The preconditions here are divided into 2 types: the ones restricting the access by the OAuth2 token’s scope and the other one by authority aka role that is defined as a part of the User model.

The repository classes are provided by the spring-boot-starter-data-mongodb package, these are interfaces that are automatically implemented by Spring framework during compilation.

Custom repository interfaces provide the methods that couldn’t be implemented by default spring data mechanism and hence require custom implementation classes.

This particular method findAndUpdateByUsernames allows to make bulk updated of the Users with nested collections as properties.

This is a useful service interface that assures that MVC pattern is used it describes default CRUD actions for this authorization service to behave as a resource one and work with User models. Without this service, this authorization server would just issue and verify OAuth2 tokens but now it allows to add new users and issue tokens for them.

Interesting thing worth mentioning here is the passwordEncoder that allows introducing sign up functionality and encode passwords to be stored securely encrypted inside the DB otherwise user original passwords would be saved open and in case of database exposure would be stolen.

This is classic REST controller implementing the CRUD principal for our User resource service. Where either whole controller or like here for example each and every endpoint would be secured separately. Different combinations of scope and authority authorizations will be used.

Production ready service should have a proper monitoring configured. Spring provides a variety of possibilities to integrate with different monitoring systems like Elastic, New Relic, Prometheus and others. The point of this article to provide basic health check endpoint sufficient to monitor the service state either manually or programmatically by Docker.

Spring boot actuator package will expose 2 endpoints in our case: /actuator/healthcheck and /actuator/status.

We will rely on healthcheck one thoroughly.

Based on the application.yml settings the healthcheck endpoint will return the disclosed detailed response.

This endpoint has not only the service status but the MongoDB status as well.

Most probably your application will be running inside a container and most probably the docker one.

Here is a simple Dockerfile with a basic functionality, docker-compose.yml file and updated build.gradle one to get it working.

Simple docker ps command will show the status of the service inside the container as well.

The service can be booted up manually with a few simple steps.

Separate docker container can be built and launched as well.

2. Run the container and specify the host of the container with mongo db in it.

This is the most convenient and simplest flow by running the standard docker-compose commands docker will attempt to build the image on its own, download the MongoDB image and run both containers in the same docker network.

This docker-compose file builds the docker image from the current context and names it your-docker-repo/spring-boot-auth-service. Then it sets environment variables for service to connect to the mongo container in the same docker network. After that it boots mongo and service containers and straight after the service container waits for the mongo one to be healthy since it depends on it.

It’s important on first launch to create separate docker network that is described in docker-compose file.

Then everything is launched with 1 simple command.

docker-compose up -d

It’s convenient to specify the d flag just to run containers in the background in case service grows.

docker-compose down -v

Then after everything is up and running, all the containers can be easily stopped. Specify a -v flag to remove all the named volumes declared in the volumes section of the compose file.

Next article will describe the resource service and peculiarities that would be met when integrating with the authorization service.

UPD: don’t hesitate to read it here Spring Boot 2 Resource Service.

Add a comment

Related posts:

Poema de gelo e fogo

Me disseram que preciso Ser bem fria e calculista Medir todos os meus passos Sumir sem deixar pistas Devo agir com muita calma Pensar bem no que for dito Não posso deixar a alma Transparecer em meu…

8 Film Exposition Examples

To explain why I think the exposition (the first 10–12 minutes) is all about the Warrior →Fool archetype, I will now show you how all of the characters in the beginning of several classic movies are…

Keep Rollin! How to Gain and Sustain a Productive Day

When we think of motivation, The Myth of Sisyphus probably does not come to mind. For those of you not familiar with the story, Sisyphus is a conniving, cunning Greek mythological figure who did…