• Skip to main content
  • Skip to secondary menu
  • Skip to primary sidebar
  • Skip to footer
  • Home
  • Contact Us

All about code

  • Java
    • Spring
      • Spring Boot
      • Spring Cloud
    • Java Miscellaneous Tips
    • Java Design Patterns
  • Data Structures and Algorithms
    • Algorithms
    • Data Structures
  • Thoughts and Stories
  • AI

How to Integrate OAuth2 in a Spring Cloud System

ai generated cyber security 8070001

Introduction

We have seen in a previous article how to provide basic security to a Spring Cloud system using SSL. We have seen how to encrypt data sent and received by external users and applications, data exchanged between internal services, and how to make these last ones mutually trusted. This article will discuss how to protect web resources and grant access only to trusted users and programs using the OAuth2 standard in a Spring Cloud system.

OAuth2 Generalities

OAuth2 is an authorization protocol. Oauth2 uses access tokens to handle access to protected resources, like REST services or user data. It doesn’t say anything about authentication, but its implementations can also provide this functionality. For example, for our demonstration, we will use Keycloak, which offers both OAuth2 and single sign-on authentication among its features.

OAuth2 can be implemented by several components, with the following roles:

  • Resource Owner: It is the owner of the resource and can grant access to them
  • Client: The client is an application that has to access a resource. It can do it by obtaining an access token
  • Authorization Server: It returns a token to the client if the resource owner grants accessì
  • Resource Server: It hosts resources. It gives clients access to a resource if it finds that the token passed by the client is valid

OAuth2 Sample

We will demonstrate how OAuth2 can be used in a Spring Cloud system. We will consider a simple web application named book-service, hidden behind a Spring Boot gateway, meant to return information about books and use Keycloak as an authorization and authentication server.

In our example, the gateway plays both the roles of the client and the authorization server, backed by Keycloak. As a client, when a request arrives to get a web resource (a REST service in our example), it calls the Keycloak instance to get an access token. If the client is not authenticated, a login page is presented to the user, otherwise the token is forwarded by the gateway to the web application.

Run and Configure Keycloak

To run an instance of Keycloak we can use docker, issuing the following command:

$ docker run -d --name keycloak -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:23.0.7 start-dev

We have to go to http://localhost:8080/admin, and log in with the given user and password, admin/admin. We then have to create a realm, we call it just “example”:

In the realm “example” we create a client, and we call it “gateway-client”, setting the Client authentication property to On. We also set the Valid redirect URIs parameter to “*”.

In the credential section of the client configuration panel, we set a client secret:

Finally, we create a user named “test” with password “test”:

This will be the username that the resource owner uses to authenticate and then authorize the client.

Configure the Gateway with OAuth2

Besides its usual role, the gateway acts as an OAuth2 client and resource server. Therefore we have to add the following dependencies:

		<!-- Gateway -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-gateway</artifactId>
		</dependency>
		
		<!-- Oauth2 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-oauth2-client</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-oauth2-resource-server</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-oauth2-jose</artifactId>
		</dependency>

We have to annotate a configuration class with @EnableWebFluxSecurity, to activate security features based on the reactive version of Spring Web, since the gateway server is based on that. We also define a SecurityWebFilterChain that uses an oauth2Login method to present a login page to the unauthenticated client and oauth2ResourceServer to check the access token before the request is forwarded to the inner services.

@Configuration
@EnableWebFluxSecurity
class AppConfiguration {

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        http.authorizeExchange(auth -> auth.anyExchange()
            .authenticated())
            .oauth2Login(withDefaults())
            .oauth2ResourceServer((oauth2) -> oauth2.jwt(withDefaults()));
        http.csrf(ServerHttpSecurity.CsrfSpec::disable);
        return http.build();
    }
}

In the application.yaml file we set the gateway configuration, as you can see in the following fragment. We set the routes to the two services and add the TokenRelay value to the default-filters section: this ensures that the token is forwarded from the gateway to the services. We have also to set several parameters for the OAuth2 configuration. The jwk-set-uri is set to an endpoint of Keycloak that checks the access token. The issuer-uri parameter contains the URI of the Keycloak provider. Finally, we have the credentials of the client, with the secret id, and the name of the provider.

spring:
   application:
      name: gateway-service
   cloud:
    gateway:
      default-filters:
        - TokenRelay=
      routes:
        - id: author-service
          uri: http://localhost:8091
          predicates:
            - Path=/authors/**
        - id: book-service
          uri: http://localhost:8092
          predicates:
            - Path=/library/**
   security:
    oauth2:
      resourceserver:
        jwt:
          jwk-set-uri: http://localhost:8080/realms/test/protocol/openid-connect/certs
      client:
        provider:
          keycloak:
            issuer-uri: http://localhost:8080/realms/test
        registration:
          gateway-client:
            provider: keycloak
            client-id: gateway-client
            client-secret: VvQXimbn43QmNLljL7f4EvWiBdXTLtRa
            authorization-grant-type: authorization_code
            scope: openid

We can make the gateway return the access token by using an OAuth2AuthorizedClient instance with an endpoint like the following:

    @GetMapping(value = "/getAccessToken")
    public String getHome(@RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient) {
        return authorizedClient.getAccessToken()
            .getTokenValue();
    }

Configure the Web Application with OAuth2

We need the same OAuth2 dependencies as the gateway for the web application. In addition, we add the web and security starters.

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>	
		<dependency>
		  <groupId>org.springframework.boot</groupId>
		  <artifactId>spring-boot-starter-security</artifactId>
		</dependency>
		<dependency>
		  <groupId>org.springframework.security</groupId>
		  <artifactId>spring-security-oauth2-resource-server</artifactId>
		</dependency>
		<dependency>
		    <groupId>org.springframework.security</groupId>
		    <artifactId>spring-security-oauth2-client</artifactId>
		</dependency>
		<dependency>
		  <groupId>org.springframework.security</groupId>
		  <artifactId>spring-security-oauth2-jose</artifactId>
		</dependency>

We use the @EnableWebSecurity annotation since the service uses a standard, not reactive web module. Like we did for the gateway, we set a filter with the oauth2ResourceServer method, but we don’t need the oauth2Login one, because it is the responsibility of the gateway to redirect the client to the login page.

@Configuration
@EnableWebSecurity
public class AppConfiguration {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(authorize -> authorize.anyRequest()
            .authenticated())
            .oauth2ResourceServer((oauth2) -> oauth2.jwt(Customizer.withDefaults()));
        return http.build();
    }
}

The OAuth2 configuration in the application.yaml file is the same as the gateway. To test the application we define a REST endpoint:

@RestController
@RequestMapping("/library")
public class BookController {
    Logger logger = LoggerFactory.getLogger(BookController.class);

    @GetMapping(value = "/bookOfTheMonth")
    public String getBookOfTheMonth() {
        return "The naked sun";
    }
}

Run the Demo

We can test the example by running the gateway and the service with the mvn spring-boot:run command and making sure that Keycloak is running with the settings described in this article. We then call the http://localhost:8090/library/bookOfTheMonth endpoint. A login page will be presented. We will log in using the user and password we gave as credentials to the Kaycloak realm. If the login succeeds, we expect to see the string “bookOfTheMonth”.

Conclusion

OAuth2 is a widely adopted standard in securing web applications. In this article, we have seen the basics of integrating it into a Spring Cloud system using a Keycloak authorization and authentication server. You can find the source code of the example of this article on GitHub.

Primary Sidebar

Social

  • Facebook
  • LinkedIn
  • Twitter

Archives

  • May 2026
  • April 2026
  • March 2026
  • August 2025
  • July 2025
  • June 2025
  • May 2025
  • April 2025
  • March 2025
  • December 2024
  • October 2024
  • August 2024
  • July 2024
  • March 2024
  • February 2024
  • January 2024
  • December 2023
  • September 2023
  • May 2023
  • March 2023
  • January 2023
  • November 2022
  • September 2022
  • August 2022

Recent Posts

  • Better Avoid Spring Boot Lazy-initialization @PostConstruct Trap
  • How To Handle Large Datasets in Spring Boot
  • How to Log HTTP Incoming Requests in Spring Boot
  • How to Reliably Implement Post-Commit Actions in Spring
  • Brief and Easy Explanation of HATEOAS

TAGS

Algorithms Apache POI Backtracking Date Structures Dynamic Programming engineering Graphs Greedy Horror Stories HSSF Java Java New Features Java Principles Java tips real life Sorting Spring Boot Spring Cloud Strings Trees

Footer

Privacy Policy Cookie Policy Terms and Conditions