How to build an Oauth server to secure the micro services

The OAuth 2.0 is a mechanism to expose OAuth 2.0 protected resources. The configuration involves establishing the OAuth 2.0 clients that can access its protected resources independently or on behalf of a user. OAuth 2.0  splits between Authorization Service and Resource Service. To configure the Authorization Server, we need to consider the grant type that the client is to use to obtain an access token from the end-user (e.g. authorization code, user credentials, refresh token). The configuration of the server is used to provide implementations of the client details service and token services and  enable or disable certain aspects of the mechanism globally. The @EnableAuthorizationServer annotation is used to configure the OAuth 2.0 Authorization Server mechanism. Let’s build a Oauth Server using Spring Boot  step by step.

  1. Create a new Spring boot project using IDE or https://start.spring.io.
  2. Make sure “MySql” is up and running in your system. You can use any other database. Change “hibernate.dialect” accordingly.
  3. Add the below dependencies in the project :
    <dependencies>
    
       <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-actuator</artifactId>
       </dependency>
       <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-oauth2</artifactId>
       </dependency>
       <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-security</artifactId>
       </dependency>
       <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
       </dependency>
    
       <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-test</artifactId>
          <scope>test</scope>
       </dependency>
    
       <dependency>
          <groupId>org.projectlombok</groupId>
          <artifactId>lombok-maven</artifactId>
          <version>1.16.16.0</version>
       </dependency>
    
       <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-jpa</artifactId>
       </dependency>
       <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
       </dependency>
    </dependencies>
  4. Delete the “application.properties” . ( Can ignore the step, if prefer  *.properties files instead of yml)
  5. Create an “application.yml” file with the below configuration
    ---
    server:
      port: 9000
    security:
    
      oauth2:
        client:
          client-id: clientamisoft
          client-secret: clientamisoftsecret
          authorized-grant-types: authorization_code,refresh_token,password,client_credentials
          scope: read,report
    spring:
      datasource:
        url: jdbc:mysql://xxx.y.z.a:3306/amisoft  #your database url. Replace "xxx.y.z.a" with your ip address.
        username: root #database schema user name
        password: root #database schema password
      jpa:
        show-sql: true
        hibernate:
          ddl-auto: update
          naming:
            strategy: org.hibernate.cfg.ImprovedNamingStrategy
    
    
    spring.jpa.properties.hibernate.dialect: org.hibernate.dialect.MySQL5Dialect

    Note : During first run keep “ddl-auto=create” . It will automatically create the “t_employee” table in database. Immediately after that change “ddl-auto=update”. Else you will lose store data.

  6. create a package for java entity for database and create the class Employee:
    package com.amisoft.entity;
    
    import javax.persistence.*;
    
    
    @Entity
    @Table(name = "t_employee")
    public  class Employee {
    
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private int id;
        private String name;
        private String password;
        private String role;
    
    
        public Employee() {
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public String getRole() {
            return role;
        }
    
        public void setRole(String role) {
            this.role = role;
        }
    }
  7. Create a package for DAO and create an interface “EmployeeDao” as:
    package com.amisoft.Dao;
    
    import com.amisoft.entity.Employee;
    import org.springframework.data.repository.CrudRepository;
    
    import javax.transaction.Transactional;
    
    
    
    @Transactional
    public interface EmployeeDao extends CrudRepository<Employee, Long> {
    
        Employee findEmployeeByName(String name);
    }
  8. Create a package for service and create a class “EmployeeServiceImpl” as:
  9. package com.amisoft.service;
    
    import com.amisoft.Dao.EmployeeDao;
    import com.amisoft.entity.Employee;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.authority.SimpleGrantedAuthority;
    import org.springframework.security.core.userdetails.User;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.stereotype.Service;
    
    import java.util.HashSet;
    import java.util.Set;
    
    
    
    @Service("employeeService")
    public class EmployeeServiceImpl implements UserDetailsService {
    
        @Autowired
        EmployeeDao employeeDao;
    
        @Override
        public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {
    
            Employee employee = employeeDao.findEmployeeByName(name);
    
    
            Set<GrantedAuthority> grantedAuthority = new HashSet<>();
            grantedAuthority.add(new SimpleGrantedAuthority(employee.getRole()));
    
            return new User(employee.getName(), employee.getPassword(), true, true, true, true, grantedAuthority);
    
    
        }
    }

    Note : Need to implement “UserDetailsService” and need to implemnt “loadUserByUsername”. This is a Spring provided interface.

  10. Create a package “config” and create a file “ServiceConfig” as
    package com.amisoft;
    
    import com.amisoft.service.EmployeeServiceImpl;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.security.crypto.password.PasswordEncoder;
    
    
    @Configuration
    public class ServiceConfig  extends GlobalAuthenticationConfigurerAdapter{
    
        @Autowired
        EmployeeServiceImpl employeeService;
    
        @Override
        public void init(AuthenticationManagerBuilder auth) throws Exception {
    
            auth.authenticationProvider(authProvider());
    
    
    
        }
    
    
        @Bean
        public PasswordEncoder passwordEncoder(){
            return new BCryptPasswordEncoder();
        }
    
    
        public DaoAuthenticationProvider authProvider(){
    
            DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
            authenticationProvider.setUserDetailsService(employeeService);
           // authenticationProvider.setPasswordEncoder(passwordEncoder());
            return authenticationProvider;
        }
    }

    Note : “ServiceConfig” extends a Spring provided class “GlobalAuthenticationConfigurerAdapter”. Ignore the “passwordEncoder” now, we shall discuss it later.

  11. Go to the main Spring boot application class , e.g. “AmisoftApplication.java” and add the method “user”. Also add the annotation @EnableAuthorizationServer.
    package com.amisoft;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.security.Principal;
    
    @SpringBootApplication
    @EnableAuthorizationServer
    @RestController
    public class AmisoftApplication {
    
       public static void main(String[] args) {
          SpringApplication.run(AmisoftApplication.class, args);
       }
    
    
       @RequestMapping("/user")
       public Principal user(Principal user){
          return user;
       }
    
    }
  12. Run the main Spring Boot Application class  e.g. “AmisoftApplication.java”.
  13. Application should be available at port 9000. ( or the port mentioned in “server.port” in “application.yml”).
  14. Access the URL  “http://localhost:9000/health” 
  15. Browser will show a health status up. A Oauth Server build using Spring Boot.
    {"status":"UP"}
  16. Insert the data in the “t_employee” table.   INSERT INTO `amisoft`.`t_employee` (`id`, `name`, `password`, `role`) VALUES (‘2’, ‘jonny’, ‘jonnypass’, ‘read’). We shall use the data during later example when we secure “ResourceServer” using OAuth token.
  17. Go to “Postman” in your system. Enter the data as shown in the below image, the token should be generated.Oauth Server build using Spring Boot to generate token
  18. Congrats. Oauth Server build using Spring Boot to generate token.

Git location:

  1. OAuth server.

Next:  Since a Oauth Server build using Spring Boot , next we create a standalone application to get token from OAuth server.

 

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.