Marcus da Coregio

Microservices with Spring Boot and Spring Cloud. From config server to OAuth2 server (without inMemory things) — Part 1

04 Aug 2020

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:

Config server creation

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 View of Eureka dashboard

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.