Keycloak is a secret weapon for securing Java APIs, and it’s way more powerful than just a simple login screen.

Imagine you’ve got a fleet of microservices, each with its own API. You want to make sure only authorized users can access sensitive data, but you don’t want to bake authentication and authorization logic into every single service. That’s where Keycloak shines. It acts as a central Identity and Access Management (IAM) provider, handling all the heavy lifting of user registration, login, and token management, so your Spring Boot applications can focus on their core business logic.

Let’s see this in action. We’ll set up a minimal Spring Boot app that requires authentication via Keycloak.

First, you need a running Keycloak instance. For local development, Docker is your best friend:

docker run -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:18.0.0 start-dev

Once Keycloak is up, access it at http://localhost:8080. Log in with admin/admin. Create a new realm, let’s call it myrealm. Inside myrealm, create a new client named my-spring-app. Set the Client Protocol to openid-connect and enable Valid Redirect URIs to http://localhost:8081/login/oauth2/code/keycloak. This tells Keycloak where to send users back after they authenticate.

Now, for the Spring Boot application. You’ll need a pom.xml with these dependencies:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity6</artifactId>
    <version>3.1.1</version>
</dependency>

Your application.properties should look like this:

server.port=8081

spring.security.oauth2.client.registration.keycloak.client-id=my-spring-app
spring.security.oauth2.client.registration.keycloak.client-secret=YOUR_CLIENT_SECRET # Generate this in Keycloak
spring.security.oauth2.client.registration.keycloak.scope=openid
spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.keycloak.redirect-uri=http://localhost:8081/login/oauth2/code/keycloak

spring.security.oauth2.client.provider.keycloak.issuer-uri=http://localhost:8080/realms/myrealm

In Keycloak, under your my-spring-app client, go to Credentials and copy the Secret. Paste it into client-secret in your application.properties.

Here’s a simple Spring Security configuration:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(authorize -> authorize
                .requestMatchers("/").permitAll()
                .anyRequest().authenticated()
            )
            .oauth2Login(oauth2Login -> oauth2Login
                .loginPage("/oauth2/authorization/keycloak")
                .permitAll()
            );
        return http.build();
    }
}

And a basic controller:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @GetMapping("/")
    public String publicEndpoint() {
        return "Hello, Public!";
    }

    @GetMapping("/secure")
    public String secureEndpoint() {
        return "Hello, Authenticated User!";
    }
}

When you run this Spring Boot app (on port 8081) and navigate to http://localhost:8081/secure, you’ll be redirected to the Keycloak login page. After successful authentication, you’ll be redirected back to your app and see "Hello, Authenticated User!".

The mental model here is that Spring Security, configured with OAuth2 client support, intercepts requests. If a request to a protected endpoint (/secure) comes in and there’s no valid session or token, it initiates the OAuth2 Authorization Code flow. It redirects the user’s browser to Keycloak’s authorization endpoint. Keycloak handles the login, and upon success, redirects back to your app’s specified redirect-uri with an authorization code. Spring Security then exchanges this code with Keycloak for an access token and an ID token. These tokens are used to establish a session and verify the user’s identity for subsequent requests.

The magic happens in how Spring Boot’s OAuth2 client auto-configures based on your application.properties. It automatically sets up an OAuth2RestTemplate and an AuthenticationManager that can validate tokens issued by the issuer-uri. Your Spring Security configuration then simply tells it which endpoints require authentication.

What most people miss is how to leverage the scopes and roles defined in Keycloak to implement fine-grained authorization. While authenticated() grants access to any logged-in user, you can restrict access to specific roles or groups defined in Keycloak by using .requestMatchers(...).hasRole("admin") or .requestMatchers(...).hasAuthority("my-custom-permission") within your HttpSecurity configuration. Spring Security, when configured correctly with Keycloak, can automatically map Keycloak roles and groups to Spring Security authorities, allowing you to enforce complex access control policies centrally managed in Keycloak.

This integration allows you to delegate user management and authentication to Keycloak, and then use the issued JWT (JSON Web Token) to verify user identity and permissions in your Spring Boot applications without needing to store passwords or manage user sessions yourself.

The next challenge is handling token refresh and managing multiple clients securely.

Want structured learning?

Take the full Keycloak course →