DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Enterprise AI Trend Report: Gain insights on ethical AI, MLOps, generative AI, large language models, and much more.

2024 Cloud survey: Share your insights on microservices, containers, K8s, CI/CD, and DevOps (+ enter a $750 raffle!) for our Trend Reports.

PostgreSQL: Learn about the open-source RDBMS' advanced capabilities, core components, common commands and functions, and general DBA tasks.

AI Automation Essentials. Check out the latest Refcard on all things AI automation, including model training, data security, and more.

Related

  • 7 Microservices Best Practices for Developers
  • Microservices With JHipster
  • Component Tests for Spring Cloud Microservices
  • Authentication With Remote LDAP Server in Spring Web MVC

Trending

  • The Future of Agile Roles: The Future of Agility
  • Why You Should Move From Monolith to Microservices
  • Integrating Salesforce APEX REST
  • Telemetry Pipelines Workshop: Introduction To Fluent Bit
  1. DZone
  2. Software Design and Architecture
  3. Security
  4. How To Implement OAuth2 Security in Microservices

How To Implement OAuth2 Security in Microservices

Learn to implement OAuth2 Security in microservices distributed systems using OAuth2, Oauth2-Client, Spring Cloud, and Netflix components with full examples.

By 
Amran Hossain user avatar
Amran Hossain
DZone Core CORE ·
Updated by 
Manoj Debnath user avatar
Manoj Debnath
·
Updated Mar. 29, 24 · Tutorial
Like (14)
Save
Tweet
Share
75.7K Views

Join the DZone community and get the full member experience.

Join For Free

What Is OAuth2?

OAuth 2.0 is an authorization protocol. It provides the framework to obtain limited access to a protected resource by a third-party application on behalf of the resource owner. For example, we log in to our LinkedIn account using Google account username and password. The Google authorization (OAuth2.0) server grants a temporary access token to LinkedIn which authorizes the user to access LinkedIn resources. Note that here, LinkedIn trusts Google to validate the user and acts as an authorization proxy. 

What Are Microservices?

A microservice is a service-oriented architecture pattern wherein applications are built as a collection of various smallest independent service units. It is a software engineering approach that focuses on decomposing an application into single-function modules with well-defined interfaces. These modules can be independently deployed and operated by small teams who own the entire life-cycle of the service.

Why Is OAuth2 a Good Solution for Secure Communications With Microservices?

  • This idea of separation of concern leverages microservices security by decoupling the part that does authorization from business logic. The responsibility is delegated to a centralized and trusted authorization server and the actual application is free from security concerns in this regard. 
  • It promotes the granularity of service which microservices typically are all about. Apart from reducing complexity, OAuth 2.0 in microservices provides a platform to implement consistent and standard security policies across the system. 
  • The authorization is flexible, meaning it can be revoked at any time. This helps security management to restrict unnecessary or limited access to resources. 
  • Since access tokens provided by the OAuth 2.0 server are stateless (JSON Web Token - JWT), it eliminates the need for storage and transmission of sensitive credentials or session data between microservices. 
  • Overall, both (OAuth 2.0 and microservices) in combination enhance the performance and scalability of the system.

Purpose

I wanted a solution where we could easily capture OAuth2 and OAuth2 clients for secure communication with all of the microservices, focusing on how to achieve OAuth2 full flavor in a microservices architecture. The user can’t access API without a token. The token will be available when the user is given basic authentication details to generate a token for access API.

All requests will consider one entry point (API Gateway), but service-to-service can communicate. The API Gateway will use dynamic routing with the Zuul Netflix OSS component. Every request will check authorization when the request arrives in the service, and the service will request the authorization server to verify if it is either authenticated or not. The entire Meta configuration settled into the central configuration on GitHub (you can manage it on any repository).

Goal

  • Achieve authentication/authorization, based on Spring Security, OAuth2, and OAuth2 client 
  • Understanding microservices architecture using Spring Cloud and Netflix OSS 
  • Demonstration of microservice architecture based on Java, Spring, and OAuth2 

Spring Cloud and Microservices

Firstly, we do not write a microservice. We write a service that eventually will be called microservice when deployed with other services to form an application.

Having said that, Spring Cloud just gives you abstractions over some set of tools (Eureka, Zuul, Feign, Ribbon, etc.), making it easy for you to integrate with spring applications.

However, you can also achieve microservice architecture without using Spring Cloud. You can take advantage of tools like Kubernetes, Docker Swarm, HAProxy, Kong, NGINX, etc. to achieve the same. Using Spring Cloud has its own pros and cons and vice versa.

High-Level Microservice Architecture With Authorizations

High-Level Microservice Architecture With Authorizations

  • Users log in to the system using basic authorization and login credentials. The user will get a token if the user's basic auth and login credentials are matched.
  • Next, the user sends a request to access data from the service. The API gateway receives the request and checks with the authorization server.
  • Every request has one entry point API Gateway.
  • Security checking and dynamic routing to the service
  • Every service has a single database to manipulate data.

Spring Cloud Key Concept and Features

  • Spring Cloud works for microservices to manage configuration.
  • Intelligent routing and services discovery
  • Service-to-service call
  • Load balancing (it properly distributes network traffic to the backend server)
  • Leadership election (the application works with another application as a third-party system)
  • Global lock (two threads are not accessed simultaneously for the same resource at the same time)
  • Distributed configuration and messaging

If you want to avail many services in one application, then the cloud-based application is an easy way. Spring Cloud works in the same way.

Spring Boot Key Concept and Features

  • Spring Boot works to create microservices.
  • Spring application creates a stand-alone Spring application.
  • Web application HTTP embedded (Tomcat, Jetty, or Undertow); no need to deploy WAR file
  • Externalized configuration
  • Security (it is secure inbuilt with basic authentication on all HTTP endpoints)
  • Application event and listener
  • Spring Boot works on product-based web applications. It is used for unit test development and integration test time reduction.

Spring Cloud Advantages

  • Provides cloud service development
  • Microservice-based architecture and configuration
  • Provides inter-service communication
  • Based on the Spring Boot model

Spring Cloud 5 Main Annotations

1. @EnableConfigServer

This annotation converts the application into a server which more applications use to get their configuration.

2. @EnableEurekaServer

This annotation is used for Eureka Discovery Services for other applications that can be used to locate services using it.

3. @EnableDiscoveryClient

This annotation helps an application register in the service discovery and discover other services using it.

4. @EnableCircuitBreaker

Use the circuit breaker pattern to continue operating when related services fail and prevent cascading failure. This annotation is used for Hystrix Circuit Breaker.

5. @HyStrixCommand(fallbackmethod="MethodName")

Hystrix is a latency and fault tolerance library for distributed systems.

4 Common Netflix Components

Spring Cloud Netflix provides Netflix OSS integrations for Spring Boot apps through autoconfiguration and binding to the Spring Environment and other Spring programming model idioms. With a few simple annotations, you can quickly enable and configure the common patterns inside your application and build large distributed systems with battle-tested Netflix components. The patterns provided include Service Discovery (Eureka), Circuit Breaker (Hystrix), Intelligent Routing (Zuul), and Client-Side Load Balancing (Ribbon). 

1. Eureka (Service Registration and Discovery)

  • REST service which registers itself at the registry (Eureka Client)
  • Web application, which is consuming the REST service as a registry-aware client (Spring Cloud Netflix Feign Client)

2. Ribbon (Dynamic Routing and Load Balancer)

  • Ribbon primarily provides client-side load-balancing algorithms.
  • APIs that integrate load balancing, fault tolerance, caching/batching on top of other Ribbon modules and Hystrix
  • REST client built on top of Apache HttpClient integrated with load balancers (deprecated and being replaced by ribbon module
  • Configurable load-balancing rules

3. Hystrix (Circuit Breaker)

Hystrix is a fault-tolerance Java library. This tool is designed to separate points of access to remote services, systems, and 3rd-party libraries in a distributed environment like microservices. It improves the overall system by isolating the failing services and preventing the cascading effect of failures.

4. Zuul (Edge Server)

  • Zuul is the front door for all requests from devices and websites to the backend of the Netflix streaming application.
  • Zuul will serve as our API gateway.
  • Handle dynamic routing
  • Built to enable dynamic routing, monitoring, resiliency, and security

What Is a Feign Client?

Netflix provides Feign as an abstraction over REST-based calls, by which microservices can communicate with each other, but developers do not have to bother about REST internal details.

Feign Client, which works on the declarative principle. We must create an interface/contract, then Spring creates the original implementation on the fly, so a REST-based service call is abstracted from developers. Not only that — if you want to customize the call, like encoding your request or decoding the response in a custom object, you can do it with Feign in a declarative way. Feign, as a client, is an important tool for microservice developers to communicate with other microservices via Rest API.

The Feign Client uses a declarative approach for accessing the API. To use it, we must first enable the Spring Cloud support for it on our Spring Boot Application with the @EnableFeignClients annotation at the class level on a @Configuration class.

Server Side Load Balancing

In JavaEE architecture, we deploy our WAR/EAR files into multiple application servers, then we create a pool of servers and put a load balancer (Netscaler) in front of it, which has a public IP. The client makes a request using that public IP, and Netscaler decides in which internal application server it forwards the request by round robin or sticky session algorithm. We call it server-side load balancing.

Technology Stack

  1. Java 8+
  2. Spring latest
  3. Spring Security
  4. OAuth2, OAuth2 Client
  5. Spring Cloud
  6. Netflix OSS
  7. PostgreSQL
  8. IntelliJ

How To Implement OAuth2 Security in Microservices

ehealth-central-configuration project file tree

Step 1: Create Project "central configuration" for All Services

With microservices, we create a central config server where all configurable parameters of microservices are written and version-controlled. The benefit of a central config server is that if we change a property for a microservice, it can reflect that on the fly without redeploying the microservice.

You can create a project using spring initializr.

application.properties:

Properties files
 




xxxxxxxxxx
1
13



1
spring.application.name=ehealth-central-configuration
2
server.port=8888
3
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
4
# available profiles of the application
5
spring.profiles.active=local,development,production
6
spring.cloud.config.server.git.uri=https://github.com/amran-bd/cloud-config
7
spring.cloud.config.server.git.clone-on-start=true
8
spring.cloud.config.server.git.search-paths=patient-management-service,ehealth-api-gateway,eureka-service-discovery,clinic-management-service
9
management.security.enabled=false
10
#To remove WAR - Could not locate PropertySource: None of labels [] found
11
health.config.enabled=false
12
# To remove I/O Issue Could not locate PropertySource: I/O error on GET request for
13
spring.cloud.config.enabled=false



Hint: You can use your Git server or local machine. A new service name will be added if a new service is introduced.

Here is the link to my GitHub repository if you would like to use it.

EhealthCentralConfigurationApplication.Java Class Example:

Java
 




xxxxxxxxxx
1
15



1
package com.amran.central.config;
2

          
3
import org.springframework.boot.SpringApplication;
4
import org.springframework.boot.autoconfigure.SpringBootApplication;
5
import org.springframework.cloud.config.server.EnableConfigServer;
6

          
7
@EnableConfigServer
8
@SpringBootApplication
9
public class EhealthCentralConfigurationApplication {
10

          
11
    public static void main(String[] args) {
12
        SpringApplication.run(EhealthCentralConfigurationApplication.class, args);
13
    }
14

          
15
}



You must include an annotation @EnableConfigServer. 

Example of Creating a Central Configuration for Services:

Central configuration for services

Hint: Create folder <projectName>/<projectName-development.properties>.

Step 2: Create a Project "Discovery Server" for All Discoverable Services

We have already discussed the discovery server in this article.

bootstrap.properties:

Properties files
 




xxxxxxxxxx
1



1
spring.application.name=eureka-service-discovery
2
spring.profiles.active=development
3
# ip and port of the config server
4
spring.cloud.config.uri=http://localhost:8888
5
# expose actuator endpoints
6
management.endpoints.web.exposure.include=refresh
7

          
8
management.security.enabled=false
9
spring.cloud.config.fail-fast=true



Here, we can enable and disable other actuator endpoints through property files.
If you want to enable all actuator endpoints, then add the following property:
management.endpoints.web.exposure.include=*. To enable only specific actuator endpoints, provide the list of endpoint IDs:

  • management.endpoints.web.exposure.include=health,info,
  • beans,env

In some cases, it may be desirable to fail the startup of a service if it cannot connect to the Config Server. If this is the desired behavior, set the bootstrap configuration property spring.cloud.config.fail.Fast=true and the client will halt with an exception.

EurkeaServiceDiscoveryApplication.java Class Example:

Java
 




xxxxxxxxxx
1
15



1
package com.amran.service.discovery;
2

          
3
import org.springframework.boot.SpringApplication;
4
import org.springframework.boot.autoconfigure.SpringBootApplication;
5
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
6

          
7
@SpringBootApplication
8
@EnableEurekaServer
9
public class EurekaServiceDiscoveryApplication {
10

          
11
    public static void main(String[] args) {
12
        SpringApplication.run(EurekaServiceDiscoveryApplication.class, args);
13
    }
14

          
15
}



You must include an annotation @EnableEurekaServer. 

Step 3: Create Project "API Gateway" for All Services Entry Points

This is the most valuable portion. Here, we write the authorization server in the same project.

API Gateway Project Structure

API Gateway Project Structure

application.yml

Properties files
 




xxxxxxxxxx
1
19



1
#hystrix:
2
#  command:
3
#    default:
4
#      execution:
5
#        isolation:
6
#          thread:
7
#            timeoutInMilliseconds: 5000
8
hystrix:
9
  command:
10
    clinic-management-service:
11
      execution:
12
        isolation:
13
          thread:
14
            timeoutInMilliseconds: 5000
15
    patient-management-service:
16
      execution:
17
        isolation:
18
          thread:
19
            timeoutInMilliseconds: 5000



Here, define timeout for every separate service; you can use the default. 

bootstrap.properties

Properties files
 




xxxxxxxxxx
1



1
spring.application.name=ehealth-api-gateway
2
spring.profiles.active=development
3
# ip and port of the config server
4
spring.cloud.config.uri=http://localhost:8888
5
# expose actuator endpoints
6
management.endpoints.web.exposure.include=refresh
7

          
8
management.security.enabled=false
9
spring.cloud.config.fail-fast=true



Central Configuration Example

ehealth-api-gateway-development.properties:

Properties files
 




x



1
spring.application.name=ehealth-api-gateway
2
server.port=8080
3
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
4

          
5
## PostgreSQL
6
spring.datasource.url=jdbc:postgresql://localhost:3307/ehealth-security
7
spring.datasource.username=postgres
8
spring.datasource.password=test1373
9
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
10
# Hikari will use the above plus the following to setup connection pooling
11
spring.datasource.hikari.minimumIdle=3
12
spring.datasource.hikari.maximumPoolSize=500
13
spring.datasource.hikari.idleTimeout=30000
14
spring.datasource.hikari.poolName=SpringBootJPAHikariCP
15
spring.datasource.hikari.maxLifetime=2000000
16
spring.datasource.hikari.connectionTimeout=30000
17
spring.datasource.pool-prepared-statements=true
18
spring.datasource.max-open-prepared-statements=250
19
spring.jpa.hibernate.connection.provider_class=org.hibernate.hikaricp.internal.HikariCPConnectionProvider
20
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQL82Dialect
21

          
22
#Hibernate Configuration
23
spring.jpa.generate-ddl = true
24
spring.jpa.hibernate.ddl-auto=update
25
spring.jpa.show-sql=true
26

          
27
server.error.include-stacktrace=never
28

          
29

          
30
#feign.hystrix.enabled=true
31
#hystrix.shareSecurityContext=true
32

          
33
#All url come with prefix/api will interpret
34
zuul.prefix=/api
35

          
36
#Dynamic Service Registration in Eureka Server (API Gateway)
37
zuul.routes.patient-management-service.path=/patient-management-service/**
38
#zuul.routes.patient-management-service.url=http://localhost:8081
39
zuul.routes.patient-management-service.sensitive-headers
40
zuul.routes.patient-management-service.service-id=patient-management-service
41

          
42
zuul.routes.clinic-management-service.path=/clinic-management-service/**
43
#zuul.routes.patient-management-service.url=http://localhost:8082
44
zuul.routes.clinic-management-service.sensitive-headers
45
zuul.routes.clinic-management-service.service-id=clinic-management-service



Zuul filtered 4-types while doing dynamic routing.

Zuul filters store request and state information in (and share it using) the RequestContext. You can use that to get to the HttpServletRequest and then log the HTTP method and URL of the request before it is sent on its way.

ErrorFilter, PreFilter, PostFilter, and RouteFilter

Java
 




xxxxxxxxxx
1
30



1
package com.amran.api.gateway.filter;
2

          
3
import com.netflix.zuul.ZuulFilter;
4

          
5
/**
6
 * @Author : Amran Hosssain on 6/27/2020
7
 */
8
public class RouteFilter extends ZuulFilter {
9

          
10
    @Override
11
    public String filterType() {
12
        return "route";
13
    }
14

          
15
    @Override
16
    public int filterOrder() {
17
        return 1;
18
    }
19

          
20
    @Override
21
    public boolean shouldFilter() {
22
        return true;
23
    }
24

          
25
    @Override
26
    public Object run() {
27
        System.out.println("Inside Route Filter");
28
        return null;
29
    }
30
}



EhealthApiGatewayApplication.java Class Example

Java
 




xxxxxxxxxx
1
42



1
package com.amran.api.gateway;
2

          
3
import com.amran.api.gateway.filter.PostFilter;
4
import com.amran.api.gateway.filter.PreFilter;
5
import com.amran.api.gateway.filter.ErrorFilter;
6
import com.amran.api.gateway.filter.RouteFilter;
7
import org.springframework.boot.SpringApplication;
8
import org.springframework.boot.autoconfigure.SpringBootApplication;
9
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
10
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
11
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
12
import org.springframework.cloud.openfeign.EnableFeignClients;
13
import org.springframework.context.annotation.Bean;
14

          
15
@EnableFeignClients
16
@EnableCircuitBreaker
17
@EnableDiscoveryClient
18
@EnableZuulProxy
19
@SpringBootApplication
20
public class EhealthApiGatewayApplication {
21

          
22
    public static void main(String[] args) {
23
        SpringApplication.run(EhealthApiGatewayApplication.class, args);
24
    }
25

          
26
    @Bean
27
    public PreFilter preFilter() {
28
        return new PreFilter();
29
    }
30
    @Bean
31
    public PostFilter postFilter() {
32
        return new PostFilter();
33
    }
34
    @Bean
35
    public ErrorFilter errorFilter() {
36
        return new ErrorFilter();
37
    }
38
    @Bean
39
    public RouteFilter routeFilter() {
40
        return new RouteFilter();
41
    }
42
}



AsEhealthApiGatewayApplication.java class annotation has been already discussed, see above if it is not clear.

Spring Security and Oauth2 Implementation in Microservices Architecture

Spring Security and Oauth2 Implementation in Microservices Architecture

I have done OAuth2 implementation based on Spring Security.

Step 4: Create a Project "patient-management-service"

Patient-related data will be manipulated.

POM.xml

XML
 




xxxxxxxxxx
1
114



1
<?xml version="1.0" encoding="UTF-8"?>
2
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4
    <modelVersion>4.0.0</modelVersion>
5
    <parent>
6
        <groupId>org.springframework.boot</groupId>
7
        <artifactId>spring-boot-starter-parent</artifactId>
8
        <version>2.3.1.RELEASE</version>
9
        <relativePath/> <!-- lookup parent from repository -->
10
    </parent>
11
    <groupId>com.amran.patient.management</groupId>
12
    <artifactId>patient-management-service</artifactId>
13
    <version>0.0.1-SNAPSHOT</version>
14
    <name>patient-management-service</name>
15
    <description>patient-management-service project for Spring Boot</description>
16

          
17
    <properties>
18
        <java.version>1.8</java.version>
19
        <spring-cloud.version>Hoxton.SR5</spring-cloud.version>
20
    </properties>
21

          
22
    <dependencies>
23
        <dependency>
24
            <groupId>org.springframework.boot</groupId>
25
            <artifactId>spring-boot-starter-actuator</artifactId>
26
        </dependency>
27
        <dependency>
28
            <groupId>org.springframework.boot</groupId>
29
            <artifactId>spring-boot-starter-data-jpa</artifactId>
30
        </dependency>
31
        <dependency>
32
            <groupId>org.springframework.cloud</groupId>
33
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
34
        </dependency>
35
        <dependency>
36
            <groupId>org.springframework.boot</groupId>
37
            <artifactId>spring-boot-starter-web</artifactId>
38
        </dependency>
39

          
40
        <dependency>
41
            <groupId>org.springframework.cloud</groupId>
42
            <artifactId>spring-cloud-config-client</artifactId>
43
        </dependency>
44

          
45
        <dependency>
46
            <groupId>org.springframework.boot</groupId>
47
            <artifactId>spring-boot-starter-security</artifactId>
48
        </dependency>
49
        <dependency>
50
            <groupId>org.springframework.security.oauth</groupId>
51
            <artifactId>spring-security-oauth2</artifactId>
52
            <version>2.5.0.RELEASE</version>
53
            <scope>compile</scope>
54
        </dependency>
55
        <dependency>
56
            <groupId>org.postgresql</groupId>
57
            <artifactId>postgresql</artifactId>
58
            <scope>runtime</scope>
59
        </dependency>
60
        <dependency>
61
            <groupId>org.springframework.boot</groupId>
62
            <artifactId>spring-boot-configuration-processor</artifactId>
63
            <optional>true</optional>
64
        </dependency>
65
        <dependency>
66
            <groupId>org.projectlombok</groupId>
67
            <artifactId>lombok</artifactId>
68
            <optional>true</optional>
69
        </dependency>
70
        <dependency>
71
            <groupId>org.springframework.boot</groupId>
72
            <artifactId>spring-boot-starter-test</artifactId>
73
            <scope>test</scope>
74
            <exclusions>
75
                <exclusion>
76
                    <groupId>org.junit.vintage</groupId>
77
                    <artifactId>junit-vintage-engine</artifactId>
78
                </exclusion>
79
            </exclusions>
80
        </dependency>
81
    </dependencies>
82

          
83
    <dependencyManagement>
84
        <dependencies>
85
            <dependency>
86
                <groupId>org.springframework.cloud</groupId>
87
                <artifactId>spring-cloud-dependencies</artifactId>
88
                <version>${spring-cloud.version}</version>
89
                <type>pom</type>
90
                <scope>import</scope>
91
            </dependency>
92
        </dependencies>
93
    </dependencyManagement>
94

          
95
    <build>
96
        <finalName>${project.artifactId}</finalName>
97
        <plugins>
98
            <plugin>
99
                <groupId>org.springframework.boot</groupId>
100
                <artifactId>spring-boot-maven-plugin</artifactId>
101
            </plugin>
102
        </plugins>
103
        <resources>
104
            <resource>
105
                <filtering>true</filtering>
106
                <directory>src/main/resources</directory>
107
                <includes>
108
                    <include>*.properties</include>
109
                </includes>
110
            </resource>
111
        </resources>
112
    </build>
113

          
114
</project>



bootstrap.properties

Properties files
 




x



1
server.url = Patient Management Service Working...
2
spring.application.name=patient-management-service
3
spring.profiles.active=development
4
# ip and port of the config server where we can get our central configuration.
5
spring.cloud.config.uri=http://localhost:8888
6
# expose actuator endpoints
7
management.endpoints.web.exposure.include=refresh
8

          
9
management.security.enabled=false
10
spring.cloud.config.fail-fast=true
11

          
12

          
13
##Security parameter for request verification ##
14
#we consider basic authorization and Token. In auth server verified this token generated by authorization server (Self) based below criteria. 
15
client_id=kidclient
16
client_credential = kidsecret
17
check_authorization_url = http://localhost:8080/oauth/check_token
18
resources_id = ehealth



PatientManagementServiceApplication.java Class Example

Java
 




xxxxxxxxxx
1
14



1
package com.amran.patient.management;
2

          
3
import org.springframework.boot.SpringApplication;
4
import org.springframework.boot.autoconfigure.SpringBootApplication;
5
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
6

          
7
@EnableDiscoveryClient
8
@SpringBootApplication
9
public class PatientManagementServiceApplication {
10

          
11
    public static void main(String[] args) {
12
        SpringApplication.run(PatientManagementServiceApplication.class, args);
13
    }
14
}



You must annotate @EnableDiscoveryClient in the class so the Eureka server will be discovered as a service or client.

Security OAuth2-Client: ResourceServerConfig.java, WebSecurityConfig.Java Class Example

You need a WebSecurityConfigurerAdapter to secure the /authorize endpoint and to provide a way for users to authenticate. A Spring Boot application would do that for you (by adding its own WebSecurityConfigurerAdapter with HTTP basic auth). It creates a filter chain with order=0 by default and protects all resources unless you provide a request marcher.

The @EnableResourceServer does something similar, but the filter chain it adds is at order=3 by default. WebSecurityConfigurerAdapter has an @Order(100) annotation. So first the ResourceServer will be checked (authentication), and then your checks in your extension of WebSecurityConfigureAdapter will be checked.

Java
 




xxxxxxxxxx
1
38



1
package com.amran.patient.management.security;
2

          
3
import org.springframework.beans.factory.annotation.Value;
4
import org.springframework.context.annotation.Configuration;
5
import org.springframework.http.HttpMethod;
6
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
7
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
8
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
9
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
10

          
11
/**
12
 * @Author : Amran Hosssain on 6/27/2020
13
 */
14
@Configuration
15
@EnableResourceServer
16
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
17

          
18
    @Value("${resources_id}")
19
    private String resourceId;
20

          
21
    @Override
22
    public void configure(HttpSecurity http) throws Exception {
23
        http
24
                .headers().frameOptions().disable()
25
                .and()
26
                .csrf().disable()
27
                .authorizeRequests()
28
                .antMatchers("/eureka/**").permitAll()
29
                .anyRequest()
30
                .authenticated();
31
    }
32

          
33
    @Override
34
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
35
        resources.resourceId(resourceId);
36
    }
37

          
38
}



Java
 




xxxxxxxxxx
1
44



1
package com.amran.patient.management.security;
2

          
3
import org.springframework.beans.factory.annotation.Value;
4
import org.springframework.context.annotation.Bean;
5
import org.springframework.context.annotation.Configuration;
6
import org.springframework.security.authentication.AuthenticationManager;
7
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
8
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
9
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationManager;
10
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
11
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
12

          
13
/**
14
 * @Author : Amran Hosssain on 6/27/2020
15
 */
16
@Configuration
17
@EnableWebSecurity
18
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
19

          
20
    @Value("${client_id}")
21
    private String clientId;
22

          
23
    @Value("${client_credential}")
24
    private String clientSecret;
25

          
26
    @Value("${check_authorization_url}")
27
    private String checkAuthUrl;
28

          
29
    @Bean
30
    public ResourceServerTokenServices tokenServices() {
31
        RemoteTokenServices tokenServices = new RemoteTokenServices();
32
        tokenServices.setClientId(clientId);
33
        tokenServices.setClientSecret(clientSecret);
34
        tokenServices.setCheckTokenEndpointUrl(checkAuthUrl);
35
        return tokenServices;
36
    }
37

          
38
    @Override
39
    public AuthenticationManager authenticationManagerBean() throws Exception {
40
        OAuth2AuthenticationManager authenticationManager = new OAuth2AuthenticationManager();
41
        authenticationManager.setTokenServices(tokenServices());
42
        return authenticationManager;
43
    }
44
}



Check How It Works

1. Generate Token

  • Project run sequence:
    • CentralConfigServer->DiscoveryServer->API Gateway Server-> Others Service

Project run sequence


2. Client Details In Database

Client details in database


3. User Record

User record


4. Generate Token

Generate token


5. Call Patient Management Service (Zuul Dynamic Routing)

Call Patient Management Service (Zuul Dynamic Routing):


6. Direct Call Patient Service (Token Verify From Auth Server) 

Note: Without a token, you can't call.

Direct Call Patient Service


7. Call Clinic Management Service (Zuul Dynamic Routing)

Call Clinic Management Service


Conclusion

I am trying to show OAuth2 implementation in microservice architecture with secure communication, single entry point, dynamic routing, fail-back solutions, centralized configurations, and OAuth2-client implementation in service to secure every API and every request to ensure authorization. 

Source Code

The full source code can be found here.

Spring Security microservice Spring Framework authentication Spring Cloud Web Service application

Opinions expressed by DZone contributors are their own.

Related

  • 7 Microservices Best Practices for Developers
  • Microservices With JHipster
  • Component Tests for Spring Cloud Microservices
  • Authentication With Remote LDAP Server in Spring Web MVC

Partner Resources


Comments

ABOUT US

  • About DZone
  • Send feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: