In Spring5 microservices you will be able to find a base to develop a microservice architecture with several of the requisites you are looking for:
- Registry server using Eureka.
- Gateway server with Zuul.
Regarding to security, I have developed two different microservices:
- Spring Oauth2 with Jwt
- Spring Jwt multi-application security service to work with access and refresh Jwt tokens, with several customizations like: definition of the content of every one, work with JWS or JWE, etc
Most important ones are well documented using Swagger, as you can see here, and all documented APIs are accessible using an unique gateway Url.
For all classes of every microservice, Junit tests were developed.
Security
At this point, I took several decisions:
1. Is not the gateway the microservice that verifies the security.
Because use the gateway as "firewall" is a less flexible approach. I wanted to decide which microservices need security and every one should manage internally the roles can access to every endpoint. In summary, every microservice has to work with the authorization/authentication but it don't need to know how that functionality is done.
2. Specific microservice to deal with the security
As I told you, I developed 2 different ones, because I wanted to "play" with different options/approaches. The most important advantage is the encapsulation, if "tomorrow" I decide to change Jwt by any other option, I will only need to modify those ones, the microservices that use them will keep the same code (I will explain you soon how the integration was done)
Security integration example
I will explain how the security functionality was integrated between:
- Pizza service easy microservice developed as part of the architecture.
- Spring Jwt
1. Every application that manages user and roles, will include in the security microservice a folder similar to the next one, to define its models, repositories to get the required information, etc
2. Global endpoints of the security microservice are defined here. As you can see, they work basically with 2 Dtos:
- AuthenticationInformationDto
- UsernameAuthoritiesDto
The main advantage, only the security microservice knows the details about how that functionality was done, the other ones that use it will receive a well known Dtos with the required information.
3. In pizza-service, the security integration is mainly defined in the next 3 classes:
- SecurityContextRepository to get authorization token from the header and send it to the
SecurityManager
.
- SecurityManager call to
security-jwt-service
with the provided "authorization token" (it doesn't know if it is Jwt or any other thing) and receives a well know UsernameAuthoritiesDto
(transforming it into an object of the Spring class UsernamePasswordAuthenticationToken
)
- WebSecurityConfiguration global security configuration.
Now you can include in your endpoints the required role based security:
- Controller example
- Custom PreAuthorize annotation
Final considerations
pizza-service
was developed using Webflux, you can see an equivalent integration based on a MVC microservice one in order-service
here (in this case I used the "other security service" but is easy to adapt it).
To improve the security and follow the "Oauth approach", the requests to security-jwt-service
need to include the Basic authentication too. As you can see in SecurityManager
class:
private String buildAuthorizationHeader(String username, String password) {
String auth = username + ":" + password;
byte[] encodedAuth = Base64.getEncoder().encode(auth.getBytes());
return "Basic " + new String(encodedAuth);
}
The table in database to store that information is the same one used to manage the security configuration of every application: security.jwt_client_details