In this guide, we will build a working app who will create users and authenticate/authorize users and clients in a microservices architecture using Spring Boot, Spring Cloud, and MongoDB.
I won’t use the inMemory configuration that we always see in the most guides.
This guide will be composed of 3 parts:
- First part: Creating the config, registry and gateway services;
- Second part: Create the auth service, the one who will authenticate the users;
- Third part: Create the account service, the one who will register new users;
I’ll assume you already have some familiarity with microservices and Spring Boot.
Creating the Config Service
The config application will be responsible to serve the spring configuration to every service. With it, you can centralize your configuration files and separate them by the environment that you are working, like dev, QA or production. Here is a more detailed explanation of the config server.
I’ll use the Spring Initializr to generate the project, and it will be available in the GitHub repo. The configuration will be like this:
Generating the config-service
We will need to add the annotation @EnableConfigServer
in ConfigServerApplication
class.
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
This annotation tells Spring that this application will act as a config server.
Now we will rename the application.properties
file to application.yml
and add these configurations to it:
spring:
cloud:
config:
server:
native:
search-locations: classpath:/shared #tells spring where to locate the config files
profiles:
active: native #we are using native because the config server uses a git repo by default
security:
user:
password: 1234 #the password which apps will use to access its configurations
server:
port: 8888 #the port where the config-server will be acessible
Create the folder shared inside the resources folder. Create another application.yml
in the folder you have just created with this content:
#This configuration file will hold common configs to be shared among all files
eureka:
instance:
prefer-ip-address: false
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/ #where our registry server is located
security:
oauth2:
resource:
user-info-uri: http://auth-service/uaa/users/current #which uri will be used to find the user
Let’s run the application and access http://localhost:8888/actuator/health. You should see a message like this:
{"status": "UP"}
Creating the Registry Service
Now we will build the registry service using the Netflix Eureka. This service is responsible for the registration and discovery of the many services we should build. This way we don’t need to know the IP address of each service we create, we just know their names and the discovery do the rest.
Let’s generate the project using the Spring Initializr:
Image for post
Generating the registry-service
Open the RegistryServiceApplication
class and add the @EnableEurekaServer
annotation, like this:
@SpringBootApplication
@EnableEurekaServer
public class RegistryServiceApplication {
public static void main(String[] args) {
SpringApplication.run(RegistryServiceApplication.class, args);
}
}
This annotation tells Spring to activate the Eureka Server related configuration.
Delete the file application.properties
and create one called bootstrap.yml
in the resources folder, with this content:
#This file is the entrypoint for spring to know where to look for the configuration file and hold the initial configuration
spring:
application:
name: registry-service #name of the application
cloud:
config:
uri: http://localhost:8888 #where the config-service is running
fail-fast: true #the service will not run if it can't reach the config-service
password: 1234 #password of the config-service
username: user #username of the config-service
eureka:
instance:
prefer-ip-address: true #when the application registers with eureka, it uses its IP address rather than its hostname
client:
registerWithEureka: false #tells the built-in eureka client to not register itself with eureka, because we should act as a server
fetchRegistry: false
We told registry service to look at http://localhost:8888 to find its configuration, so we need to create a configuration file for it on config service.
In the config-service/resources/shared folder, let’s create a file named registry-service.yml
with the following content:
server:
port: 8761 #the default port used for eureka servers
Now run the config-service and the registry-service, and access http://localhost:8761/. You should see a page like this:
Image for post
There is where you will find the services registered with the Eureka Server. When looking for its configuration, the services will search for the configuration with the same name defined in spring.application.name property in the bootstrap.yml file.
You can even access http://localhost:8888/registry-service/default, authenticate with user as the username and 1234 as the password to see the configuration.
Creating the Gateway Service
Now we will build the gateway service using the Spring Netflix Zuul. This service is responsible to map the incoming requests to specific microservices, it can act as a load balancer too.
Let’s generate the project using the Spring Initializr: Image for post
Generating the gateway-service
We need to add two annotations to our main class GatewayServiceApplication
:
@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulProxy
public class GatewayServiceApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayServiceApplication.class, args);
}
}
@EnableDiscoveryClient
tells Spring to enable the discovery client implementation.
@EnableZuulProxy
sets up a Zuul Server so it can forward requests to other services. This services can be configured manually through configuration or via Discovery (Eureka) Server.
Create the bootstrap.yml
file in the place of application.properties with this content, almost the same as the registry service:
spring:
application:
name: gateway-service
cloud:
config:
uri: http://localhost:8888
fail-fast: true
password: 1234
username: user
Now we need to create the configuration file for gateway-service.
In the config-service/resources/shared
folder, let’s create a file named gateway-service.yml
with the following content:
zuul:
ignoredServices: '*'
host:
connect-timeout-millis: 20000
socket-timeout-millis: 20000
routes:
auth-service:
path: /uaa/** #path that will be intercepted
url: auth-service #which url the request will e mapped to
stripPrefix: false #if zuul should replace the "/uaa/" segment
sensitiveHeaders:
account-service:
path: /accounts/**
serviceId: account-service
stripPrefix: false
sensitiveHeaders:
server:
port: 8080
I let some configurations that we will need later in this guide.
Now, you can run your gateway service application and access http://localhost:8761/ to see if the service is registered in Eureka Server. You should see something like this:
Image for post View of the Eureka Server with Gateway Service instance running
And that’s it, we are done with the first part of this guide. We have created the basics of our microservices architecture.
In the second part, we will create the auth service, the one which will do the authentication and authorization of users and clients. I’m looking forward to hearing from you guys any questions. Let me know if this guide did help you.
Remember that the code is available on GitHub.
The second part is available here.
The third part is available here.