Keycloak with Spring Boot #2 – Spring Security instead of Keycloak in tests

featured image

Configuring our Spring Boot API to use Keycloak as an authentication and authorization server can greatly simplify our codebase. However, it adds another external dependency that will complicate the integration testing. As a remedy, we can switch to native Spring Security when executing tests to verify only the business rules for access control instead of cluttering the code with Keycloak dependencies.

Prerequisites

  • I’m working on a Spring Boot REST API that you can find in my keycloak-spring-boot repository. If you want to run the app locally, visit the project repository on GitHub and follow the directions in the README.md file.

Why we need to overwrite configuration in tests

For example, after we add Keycloak config to a project, Spring MVC tests will fail to load the ApplicationContext due to the following error:

Currently, there is no default way to disable Keycloak protection (note that the property keycloak.enabled=false is not supported).

While we could provide just enough Keycloak configuration to run the tests, it would introduce irrelevant details into the code. Therefore, we need to ensure a security config that keeps the test code clean and still allows API access rules to be verified.

Configure integration tests to use Spring Security instead of Keycloak

First, we’ll make the Keycloak setup dependent on a custom application property. Then we’ll configure our tests to use just Spring Security.

Make the Keycloak config load dependent on a custom property

We’re going to create a custom application property to control the loading of the security config. An important point to remember is that I want Keycloak to be used by default. In other words, I only want to turn it off in testing.

Create the application.properties file in the test/resources directory and copy the following property:

When executing tests, Spring Boot will only see the properties defined in this file. If you have any properties that should also be used in your tests, be sure to copy them to this file as well. The advantage of this approach is that it removes all irrelevant properties from the testing context and also provides a clear view of our testing setup.

Next, we need to configure our app to use Keycloak either when our custom property explicitly says so or when it hasn’t been specified at all (by default). Therefore, we’re going to aply the ConditionalOnProperty annotation to all Keycloak-related configuration classes (there are two in my project):

Thanks to specifying the matchIfMissing attribute, the Keycloak configuration is our default security configuration. However, it won’t be used when running tests because we explicitly disabled it in the test/resources/application.properties file.

Define common security rules

As you may have noticed, we don’t have any security setup for our testing at the moment. Ideally, we want to test the business rules for API security without duplicating it in the tests. Therefore, I’m going to extract the common configuration into a static method so that I can reuse it in my tests:

As a result, I can reuse the SecurityConfig::configureApiSecurity method outside of the Keycloak configuration class.

Apply security configuration in tests

Consequently, we can now provide a separate security configuration for the tests. Create a class in the test package that:

  • uses the @Configuration annotation,
  • is enabled when the security.conifg.use-keycloak property is set to false,
  • uses the SecurityConfig::configureApiSecurity method we defined earlier.

You can see my conifg class below:

This is all I need to apply my security config in tests without coupling it with an external authorization server.

Finally, by running tests from my ProductControllerTest class, I can verify the actual configuration in logs:

logs showing that Spring Security was used instead of Keycloak in tests

As we can see, a user password is generated automatically according to the default Spring Security specification and there is no mention of any Keycloak configuration.

More on using Spring Security instead of Keycloak in tests

Photo by ELEVATE from Pexels

Leave a Reply

Your email address will not be published.