Spring WebFlux and OAuth 2.0

The Spring ecosystem provides extensive support for integrating with OAuth 2.0 complaint providers. In this tutorial we will cover how to create a reactive Spring Boot application that uses a third party provider’s OAuth 2.0 for authentication, and how to use the access token issued to further request protected resources.
The tutorial assumes you are familiar with:
- Spring / Spring Boot
- Project Reactor
- OAuth 2.0
Spring Security comes preconfigured with common OAuth 2.0 providers for Google, Github, Facebook, and Okta. Their configurations can be found in the spring-security
CommonOAuth2Provider class. By providing these configurations, it is incredibly easy for you to integrate with those providers, in-fact all you need to do is configure the client-id
and client-secret
for the provider:
There are many other popular OAuth 2.0 providers whose configuration isn’t included by default. One such example is Reddit, which is the provider this tutorial will focus on.
Register an Application with Reddit
To start, let’s register our application with Reddit. For this you will need an account, if you haven’t already got one go ahead and sign up. Reddit is an outlier on the internet in that you don’t need to enter an email to create an account, you can just click “continue” and it will bypass it.
Once you’ve logged into your account, navigate to https://www.reddit.com/prefs/apps/ and scroll to the bottom. Click on the are you a developer? create an app...
button.
Make sure that web app
is checked, and specify the redirect uri
as http://localhost:8080/login/oauth2/code/reddit
(more on this below). You are free to update the other fields as you see fit.

Once the app is created, you will be able to obtain the client ID and secret, note these down as they will be required later. In my case, the client ID is SVDNR1kmiOVDGg
and secret is BpQxZT5msviUM1GCGvIhu055E_psFQ
:

Generating the Spring Boot Application
Secondly, we need to bootstrap our Spring Boot project. Lets navigate over to Spring Initializr and add the following dependencies:
- Spring Reactive Web
- OAuth2 Client
Alternatively, you can click here for a pre-configured initializr template.

Once the project is downloaded, open it in your IDE of choice.
Bootstrapping the service
To use WebFlux, we need to enable it in our service:
While here, we will also add a simple Hello World endpoint:
If we tried to hit this endpoint right now we would be redirected to a login page, this is because Spring Security is on the class path and Spring Boot is automatically configuring the service to require authentication (although there are no configured users).
Enabling OAuth 2.0
As we want to use Reddit to authenticate, we need to customise the the security configuration to enable OAuth 2.0 for all requests:
If you tried to run the service now, it wouldn’t even start due to IllegalArgumentException: clientRegistrationRepository cannot be null
. This is because we haven’t configured any of the OAuth 2.0 clients.
The configuration for OAuth 2.0 clients is split into two main categories:
spring.security.oauth2.client.registration
— configuration relating to how the OAuth2 client will create the authentication requestspring.security.oauth2.client.provider
— configuration relating to the OAuth2 server
In the Google example mentioned above, all that was required was to specify a couple of the registration
properties. As this is a new provider, it requires both the registration
and provider
to be configured:
Note: you will need to provide your own clientId
and clientSecret
values with the one’s you definitely noted down earlier…
Spring has some great documentation, so if you’re not sure what one of those properties is I will direct you their respective classes:
Although, I would like to highlight the spring.security.oauth2.client.registration.reddit.redirctUri: http://localhost:8080/login/oauth2/code/reddit
property. This is an endpoint in our service, but we haven’t created any controller to handle this request. Spring’s DefaultOAuth2AuthorizationRequestResolver
is being used to intercept and handle the response from Reddit. More information on this can be found here.
Testing Authentication
Start the service in the usual way (e.g. ./mvn spring-boot:run
), and navigate to http://localhost:8080/
. As Spring Security is configured to require authentication for all requests, and OAuth 2.0 login is enable you should be automatically redirected to Reddit where you will be asked to allow access to the app you created. Upon accepting, you we be redirect back to http://localhost:8080
where we are now authorised to get a response from our HelloController
endpoint.

Downstream Authentication
As we now have our authentication working, we have the ability to obtain the access token issued by Reddit. We can use this access token to interact with the Reddit API.
Spring’s WebClient has built-in support for invoking downstream services using the access token that was issued, it just requires some configuration:
Lets break down what the two methods are doing:
redditWebClient
— Instantiates aWebClient
bean, that is configured to usehttps://oauth.reddit.com
as the base URL for all requests. Furthermore, it is configuring thatWebClient
with aServerOAuth2AuthorizedClientExchangeFilterFunction
that uses the Reddit OAuth2 configuration as a default. This filter will be applied before any requests are made, and will add theAuthorization
HTTP header to all requests.authorizedClientManager
— Instantiates aReactiveOAuth2AuthorizedClientManager
, that is used by theServerOAuth2AuthorizedClientExchangeFilterFunction
mentioned above. TheReactiveOAuth2AuthorizedClientManager
allows Spring obtain the access token used in requests to the Reddit API.
The last thing we need to do, is to update the HelloController to use our configured WebClient
to make a request to the Reddit API.
In the above example, the WebClient
is used to invoke the https://oauth.reddit.com/api/v1/me
endpoint that is protected by the identity
scope (that is configured in our application.yml
). It then parses the JSON response into a map, and retrieves the name
attribute.
Restarting our service, and navigating to http://localhost:8080
will trigger the authentication flow again. Once accepted, you will see the updated response with your username.

But.. I’m not using WebClient
There may be a use case where you need to obtain the access token yourself, this is possible to do using the auto configured ReactiveOAuth2AuthorizedClientService
bean. This is the same bean that we are using in the ReactiveOAuth2AuthorizedClientManager
bean we created above.
In the below example, we will replicate what the ReactiveOAuth2AuthorizedClientManager
is doing under the hood, to achieve the same outcome:
In this case, we are required to obtain the SecurityContext
and use the name
retrieved from the Authentication
object held my Spring Security to retrieve the access token from the ReactiveOAuth2AuthorizedClientManager
. We can then use this value to populate the Authorization
header when we make our request.