Partner – Orkes – NPI EA (cat=Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag=Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – LambdaTest – NPI EA (cat=Testing)
announcement - icon

Accessibility testing is a crucial aspect to ensure that your application is usable for everyone and meets accessibility standards that are required in many countries.

By automating these tests, teams can quickly detect issues related to screen reader compatibility, keyboard navigation, color contrast, and other aspects that could pose a barrier to using the software effectively for people with disabilities.

Learn how to automate accessibility testing with Selenium and the LambdaTest cloud-based testing platform that lets developers and testers perform accessibility automation on over 3000+ real environments:

Automated Accessibility Testing With Selenium

Course – LSS – NPI (cat=Spring Security)
announcement - icon

If you're working on a Spring Security (and especially an OAuth) implementation, definitely have a look at the Learn Spring Security course:

>> LEARN SPRING SECURITY

1. Introduction

In this tutorial, we’ll show to use PKCE in a Spring Boot confidential client application.

2. Background

Proof Key for Code Exchange (PKCE) is an extension to the OAuth protocol that initially targeted public clients, usually SPA web applications or mobile apps. It is used as part of the Authorization Code Grant flow and helps to mitigate some attacks by a malicious third party.

The main vector for those attacks is the step that happens when the provider has already established the user’s identity and sends the authorization code using an HTTP redirect. Depending on the scenario, this authorization code can leak and/or be intercepted, allowing the attacker to use it to obtain a valid access token.

Once in possession of this access token, the attacker can use it to access a protected resource and use it as if it was the legitimate owner. For example, if this access token is associated with a banking account, they can then access statements, portfolio values, or other sensitive information.

3. PKCE Modifications to OAuth

The PKCE mechanism adds a few tweaks to the standard authorization code flow:

  • The client sends two additional parameters in the initial authorization request: code_challenge and code_challenge_method
  • In the last step, when the client exchanges an authorization code for an access token, there’s also a new parameter: code_verifier

A PKCE-enabled client takes the following steps to implement this mechanism:

First, it generates a random string to use as the code_verifier parameter. According to RFC 7636, the length of this string must be at least 43 octets but less than 128 octets. The key point is to use a secure random generator, such as the JVM’s SecureRandom or equivalent.

Besides its length, there’s also a restriction on the range of allowed characters: only alphanumeric ASCII characters are supported, along with a few symbols.

Next, the client takes the generated value and transforms it into the code_challenge parameter using a supported method. Currently, the specification mentions just two transformation methods: plain and S256.

  • plain is just a no-op transformation, so the transformed value is the same as the code_verifier
  • S256 corresponds to the SHA-256 hashing algorithm, whose result is encoded in BASE64

The client then builds the OAuth authorization URL using the regular parameters (client_id, scope, state, etc.) and adds the resulting code_challenge and code_challenge_method.

3.1. Code Challenge Verification

In the last step of an OAuth authorization code flow, the client sends the original code_verifier value along with the regular ones as defined by this flow. The server then validates the code_verifier according to the challenge’s method:

  • For the plain method, code_verifier and the challenge must be the same
  • For the S256 method, the server calculates the SHA-256 of the supplied value and encodes it in BASE64 before comparing it with the original challenge.

So, why is PKCE effective against authorization code attacks? As we mentioned before, those usually target the redirect sent from the authorization server, which contains the authorization code, to work. However, with PKCE, this information is no longer sufficient to complete the flow, at least for the S256 method. The code-for-token exchange only happens if the client provides both the authorization code and the verifier, which is never present in the redirects.

Of course, when using the plain method, the verifier and challenge are the same, so there’s no point in using this method in real-world applications.

3.2. PKCE for Secret Clients

In OAuth 2.0, PKCE is optional and mostly used with mobile and web applications. The upcoming OAuth 2.1 version, however, made PKCE mandatory not only for public clients but also for secret ones.

Just to remember, a secret client is usually a hosted application running in a cloud or on-premises server. Such clients also use the authorization code flow, but since the final code exchange step happens between the backend and the authorization servers, the user agent (web or mobile) never “sees” the access token.

Other than that, the steps are exactly the same as in the public client case.

4. Spring Security Support for PKCE

As of Spring Security 5.7, PKCE is fully supported for both servlet and reactive flavored web applications. However, this feature is not enabled by default since not all identity providers support this extension yet. Spring Boot applications must use version 2.7 or above of the framework and rely on standard dependency management. This ensures the project picks the correct Spring Security version, along with its transitive dependencies.

PKCE support lives in the spring-security-oauth2-client module. For a Spring Boot application, the easiest way to bring this dependency is using the corresponding starter module:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>

The latest versions of those dependencies can be downloaded from Maven Central.

With the dependencies in place, we now need to customize the OAuth 2.0 login process to support PKCE. For reactive applications, this means adding a SecurityWebFilterChain bean that applies this setting:

@Bean
public SecurityWebFilterChain pkceFilterChain(ServerHttpSecurity http,
  ServerOAuth2AuthorizationRequestResolver resolver) {
    http.authorizeExchange(r -> r.anyExchange().authenticated());
    http.oauth2Login(auth -> auth.authorizationRequestResolver(resolver));
    return http.build();
}

The key step is setting a custom ServerOAuth2AuthorizationRequestResolver in the login specification. Spring Security uses an implementation of this interface to build an OAuth authorization request for a given client registration.

Fortunately, we don’t have to implement this interface. Instead, we can use the readily available DefaultServerOAuth2AuthorizationRequestResolver class, which allows us to apply further customizations:

@Bean
public ServerOAuth2AuthorizationRequestResolver pkceResolver(ReactiveClientRegistrationRepository repo) {
    var resolver = new DefaultServerOAuth2AuthorizationRequestResolver(repo);
    resolver.setAuthorizationRequestCustomizer(OAuth2AuthorizationRequestCustomizers.withPkce());
    return resolver;
}

Here, we instantiate the request resolver, passing a ReactiveClientRegistrationRepository instance. Then, we use OAuth2AuthorizationRequestCustomizers.withPkce(), which provides the required logic to add the additional PKCE parameters to the authorization request URL.

5. Testing

To test our PKCE-enabled application, we need an authorization server that supports this extension. In this tutorial, we’ll use the Spring Authorization Server for this purpose. This project is a recent addition to Spring’s family that allows us to quickly build an OAuth 2.1/OIDC-compliant authorization server.

5.1. Authorization Server Setup

In our live test environment, the authorization server runs as a separate process from the client. The project is a standard Spring Boot web application to which we’ve added the relevant maven dependency:

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

The latest version of the starter and  Spring Authorization Server can be downloaded from Maven Central.

To work properly, the Authorization Server requires us to provide a few configuration beans, including a RegisteredClientRepository and a UserDetailsService. For our testing purposes, we can use in-memory implementations of both containing a fixed set of test values. For this tutorial, the former is more relevant:

@Bean 
public RegisteredClientRepository registeredClientRepository() {      
    var pkceClient = RegisteredClient
      .withId(UUID.randomUUID().toString())
      .clientId("pkce-client")
      .clientSecret("{noop}obscura")
      .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
      .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
      .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
      .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
      .scope(OidcScopes.OPENID)          
      .scope(OidcScopes.EMAIL)          
      .scope(OidcScopes.PROFILE)
      .clientSettings(ClientSettings.builder()
        .requireAuthorizationConsent(false)
        .requireProofKey(true)
        .build())
      .redirectUri("http://127.0.0.1:8080/login/oauth2/code/pkce")
      .build();
    
    return new InMemoryRegisteredClientRepository(pkceClient);
}

The key point is using the clientSettings() method to enforce the use of PKCE for a particular client. We do this by passing a ClientSettings object created with the requireProofKey() set to true.

In our test setup, the client will run on the same host as the authorization server, so we’re using 127.0.0.1 as the hostname part of the redirect URL. It is worth noting that using “localhost” is not allowed here, hence the use of the equivalent IP address.

To complete the setup, we’ll also need to modify the default port setting in the application’s properties file:

server.port=8085

5.2. Running Live Tests

Now, let’s run a live test to verify that all is working as intended. We can run both projects straight from the IDE or open two shell windows and issue the command mvn spring-boot:run for each module. Regardless of the method, once both applications are up, we can open a browser and point it to http://127.0.0.1:8080.

We should see Spring Security’s default login page:

pkce sign in

Notice the URL in the address bar: http://localhost:8085. This means that the login form came from the authorization server through a redirect. To verify this statement, we can open Chrome’s DevTools (or the equivalent in your browser of choice) while on the login form and reenter the initial URL in the address bar:

pkce challenge

We can see PKCE parameters in the Location header present in the response generated by our client application to the request made to http://127.0.0.1:8080/oauth2/authorization/pkce:

Location: http://localhost:8085/oauth2/authorize?
  response_type=code&
  client_id=pkce-client&
  scope=openid email&
  state=sUmww5GH14yatTwnv2V5Xs0rCCJ0vz0Sjyp4tK1tsdI=&
  redirect_uri=http://127.0.0.1:8080/login/oauth2/code/pkce&
  nonce=FVO5cA3_UNVVIjYnZ9ZrNq5xCTfDnlPERAvPCm0w0ek&
  code_challenge=g0bA5_PNDxy-bdf2t9H0ximVovLqMdbuTVxmGnXjdnQ&
  code_challenge_method=S256

To complete the login sequence, we’ll use “user” and “password” as credentials. If we continue to follow the requests, we’ll see that neither the code verifier nor the access token is ever present, which was our goal.

6. Conclusion

In this tutorial, we’ve shown how to enable OAuth’s PKCE extension in a Spring Security application with just a few lines of code. Furthermore, we’ve also shown how to use the Spring Authorization Server library to create a tailor-made server for testing purposes.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

Partner – Orkes – NPI EA (cat = Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag = Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Course – LSS – NPI (cat=Security/Spring Security)
announcement - icon

I just announced the new Learn Spring Security course, including the full material focused on the new OAuth2 stack in Spring Security:

>> CHECK OUT THE COURSE

eBook Jackson – NPI EA – 3 (cat = Jackson)