Keycloak provides simple integration with Spring applications. As a result, we can easily configure our Spring Boot API security to delegate authentication and authorization to a Keycloak server.
- Docker Engine and Docker Compose (for running an example Keycloak instance), JDK and Maven (for running an example Spring Boot project).
- I’m working on a Spring Boot REST API that you can find in my
keycloak-spring-bootrepository. If you want to run the app locally, visit the project repository on GitHub and follow the directions in the README.md file.
- My project contains Spring MVC tests that allow me to verify the security configuration. However, you can learn how to authorize Postman requests in Keycloak or configure Swagger UI to comply with the security setup to manually test your API.
- The solution that I’ll show works for the following sample client configuration:
Securing Spring Boot applications with Keycloak
I’m going to add maven dependencies and required properties for Keycloak integration. Then, before I actually restrict access to my API endpoints, I will define a basic security configuration and test that both tools work together properly.
First, I’m going to add the required dependencies to my project. In addition to the Keycloak and Spring Security starters for Spring Boot, I’ll add the Keycloak bom for adapters:
Add application properties
I’m running my Keycloak instance in a Docker container. For my sample client configuration, see the screenshot from the Prerequisites section.
I’m going to copy some information from my Keycloak client setup to the
Below is a brief explanation of the properties:
realm– my example realm name;
resource– my example client name;
auth-server-url– you can get the value from the Keycloak OIDC URI endpoint list by visiting the realm settings, clicking the
OpenID Endpoint Configurationand copying the
credentials.secret– my example client has the
confidentialaccess type. Therefore, I have to copy the
secretvalue from the
If you want to access user roles at the client level and not user roles at the realm level, add the following property:
However, in my example I’m using realm roles for users.
Add security config
I’m going to create two configuration classes to handle my Keycloak setup.
The first one provides the ability to resolve my Keycloak config based on the
application.properties file. I’m going to enclose it in a separate file to avoid the circular dependency issue (described in Javadoc in the snippet below):
Next, I’m going to add the following class containing a Keycloak-based Spring security configuration:
There are a few things to note:
@KeycloakConfiguration– this metadata annotation provides all annotations that are needed to integrate Keycloak in Spring Security (e.g. for enabling Spring Security or configuring component scanning);
KeycloakWebSecurityConfigurerAdapter– by extending this class we gain a useful base class for creating a WebSecurityConfigurer instance secured by Keycloak;
SecurityConfig::configure– we’re going to overwrite the basic Spring Security behaviour, first by calling the parent implementation and then by adding our own csrf and endpoint protection config;
SecurityConfig::configureGlobal– furthermore, we have to register the KeycloakAuthenticationProvider with the authentication manager;
SecurityConfig::getKeycloakAuthenticationProvider– my auxiliary method for customising the authentication provider. Namely, I’m providing a simple one-to-one GrantedAuthoritiesMapper which adds the
ROLE_prefix and converts the authority value to upper case (e.g. a
chief-operating-officerrole from Keycloak realm becomes
ROLE_CHIEF-OPERATING-OFFICERin my Spring Boot app);
SecurityConfig::sessionAuthenticationStrategy– the session authentication strategy bean has to be of type
Test basic Keycloak configuration for Spring Security
Although I haven’t restricted access to any endpoint in my API, I’m still going to test the current setup. I’m going to enable the DEBUG log lever for security by adding the following property to my
As a result, I can verify the configuration details and see that Keycloak filters are present in the filter chain:
Moreover, Spring Security doesn’t create a user password which would be its default behaviour without the Keycloak configuration.
At this point, my Spring Boot application is delegating authentication and authorization processes to Keycloak. However, I am still free to call the endpoints as they are not explicitly secured.
Next, I’m going to restrict access to the API endpoints by replacing
anyRequest().permitAll() with the
After restarting the application, I can see in its logs that all endpoints are protected:
As a result, my Postman setup and Swagger UI config require additional configuration to allow me to make API calls.
Update tests after configuring Spring Security to use Keycloak
Configuring security in a project will break existing Spring MVC tests. Therefore, below you will find some details that require updating.
Disable Keycloak in tests and use plain Spring Security
I don’t want to clutter tests with the configuration of an external authorization service. Therefore, I’m going to configure my Spring MVC tests to use Spring Security instead of Keycloak. For full instructions on how to apply a different security configuration in tests, see the Keycloak with Spring Boot #2 – Spring Security instead of Keycloak in tests post.
Mock an authenticated user
Fortunately, Spring Security provides the @WithMockUser annotation. We can apply it to a specific test or an entire class. In the following example test method, we can see how to use this annotation in a single test while keeping the default user data:
Additionally, we can customise the
authorities (the latter two are exclusive) that our mocked user will receive:
Include csrf protection
As you may have noticed, my security configuration uses csrf protection. Therefore, I have to add the
SecurityMockMvcRequestPostProcessors::csrf method that automatically populates a valid CSRF token in my POST request:
Read more on integrating Spring Security with Keycloak
- Keycloak with Spring Boot #2 – Spring Security instead of Keycloak in tests
- Keycloak with Spring Boot #3 – How to authorize requests in Swagger UI
- Kecloak in Docker #7 – How to authorize requests via Postman
- Securing Spring Boot with Keycloak documentation for Keycloak 16.1.1 and Keycloak 17.0.0.
- Keycloak in Docker #1 – How to run Keycloak in a Docker container article.
- Spring Security and Keycloak to Secure a Spring Boot Application – A First Look