Search

Suggested keywords:
  • Java
  • Docker
  • Git
  • React
  • NextJs
  • Spring boot
  • Laravel

Spring Boot and KeyCloak integration

  • Share this:

post-title

Keycloak is an open source identity and access management system which offers both administrator and account management consoles for centralized management. Users can manage their profiles and active sessions using the account management console, while administrators can configure Keycloak fully. Keycloak provides user federation, strong authentication, user management and fine-grained authorization. Refer to the article to learn about how to setup and configure Keycloak

In this article, we will learn about how to integrate Spring Boot with Keycloak using session based authentication.

You will need the following dependencies to create your maven project. The following is the complete pom.xml with explanations. You can use the IDE or Spring Initializr to bootstrap your application.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>2.7.1</version>
                <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.example</groupId>
        <artifactId>KeyCloakIntegrationWithSpringBoot</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>KeyCloakIntegrationWithSpringBoot</name>
        <description>Demo project for integrating KeyCloak and Spring Boot</description>
        <properties>
                <java.version>17</java.version>
        </properties>
        <dependencies>
                <dependency>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-security</artifactId>
                </dependency>
                <dependency>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-devtools</artifactId>
                        <scope>runtime</scope>
                        <optional>true</optional>
                </dependency>
                <dependency>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-test</artifactId>
                        <scope>test</scope>
                </dependency>
                <dependency>
                        <groupId>org.springframework.security</groupId>
                        <artifactId>spring-security-test</artifactId>
                        <scope>test</scope>
                </dependency>
                <dependency>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-web</artifactId>
                </dependency>
                <!-- https://mvnrepository.com/artifact/org.keycloak/keycloak-spring-boot-starter -->
                <dependency>
                        <groupId>org.keycloak</groupId>
                        <artifactId>keycloak-spring-boot-starter</artifactId>
                        <version>15.0.2</version>
                </dependency>
        </dependencies>

        <build>
                <plugins>
                        <plugin>
                                <groupId>org.springframework.boot</groupId>
                                <artifactId>spring-boot-maven-plugin</artifactId>
                        </plugin>
                </plugins>
        </build>
</project>

 

Application Configuration

keycloak.realm=blackslate
keycloak.auth-server-url=http://localhost:8080
keycloak.resource=blackslate-client
keycloak.credentials.secret=xxxxxxxxxxxx
keycloak.use-resource-role-mappings=true
server.port=8084

 

Where,

  1. Realm: It is the name of the realm we created in Keycloak
  2. Auth-server-url: Refers to the URL of the keycloak server
  3. resource : refers to the client-id which is blackslate in our case
  4. credentials.secret: Can be found at Clients-> blackslate-client -> Credentials like in the image below

screenshot

KeycloakController.java

package com.keycloak.application.controller;

import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
import org.keycloak.representations.AccessToken;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.security.Principal;

@RestController
public class KeyCloakController {

   @GetMapping("/login")
   public String login() {
       return "Welcome to the login page";
   }

   @GetMapping("/homepage")
   public String homepage(Principal principal) {
       KeycloakAuthenticationToken token = (KeycloakAuthenticationToken) principal;
       AccessToken accessToken = token.getAccount().getKeycloakSecurityContext().getToken();
       return "Welcome to the homepage, " +accessToken.getPreferredUsername()+" successfully logged in";
   }
}

The login page will be accessible without authentication, while the homepage will require authentication.

Keycloak authentication token is used to read username from Keycloak and display it

KeycloakSecurity.java

package com.keycloak.application.security;

import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;

@Configuration
public class KeycloakSecurity extends KeycloakWebSecurityConfigurerAdapter {

   @Bean
   @Override
   protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
       return new RegisterSessionAuthenticationStrategy(
               new SessionRegistryImpl());
   }

   @Override
   protected void configure(HttpSecurity http) throws Exception {
       super.configure(http);
       http.authorizeRequests()
           .antMatchers("/homepage").hasRole("user")
           .anyRequest().permitAll();
       http.csrf().disable();
   }

   @Autowired
   public void configureGlobal(AuthenticationManagerBuilder auth, KeycloakAuthenticationProvider keycloakAuthenticationProvider) {
       auth.authenticationProvider(keycloakAuthenticationProvider);
   }
}

The above code extends the KeycloakWebSecurityConfigurerAdapter class and overrides methods to set up authentication and authorization. It defines a session authentication strategy using the RegisterSessionAuthenticationStrategy, specifies access rules for different endpoints (allowing access to "/homepage" only for users with the "user" role), and disables CSRF protection. Additionally, it injects a KeycloakAuthenticationProvider into the authentication manager to handle authentication using Keycloak.

KeyCloakConfigurationResolver.java

package com.keycloak.application.security;

import org.keycloak.adapters.KeycloakConfigResolver;
import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class KeycloakConfigurationResolver {

   @Bean
   public KeycloakConfigResolver KeycloakConfigResolver() {
       return new KeycloakSpringBootConfigResolver();
   }
}

The above code provides a configuration class for resolving Keycloak configurations in a Spring Boot application. It declares a bean named KeycloakConfigResolver of type KeycloakSpringBootConfigResolver, which is a class provided by the Keycloak Spring Boot Starter to resolve Keycloak configurations specifically for Spring Boot. This bean is responsible for resolving the Keycloak configuration during the application startup, ensuring proper integration between the Spring Boot application and the Keycloak identity and access management system.

KeyCloakAuthenticationConfig.java

package com.keycloak.application.security;

import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;

@Configuration
public class KeyCloakAuthenticationConfig {

   @Bean
   public KeycloakAuthenticationProvider keycloakAuthenticationProvider() {
       KeycloakAuthenticationProvider provider = new KeycloakAuthenticationProvider();
       provider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
       return provider;
   }
}

The above code defines a configuration class for setting up the Keycloak authentication provider in a Spring Boot application. It declares a bean named keycloakAuthenticationProvider of type KeycloakAuthenticationProvider and configures it by setting a SimpleAuthorityMapper as the granted authorities mapper. The KeycloakAuthenticationProvider is a component provided by the Keycloak Spring Security integration to handle authentication within the Spring Security framework. The SimpleAuthorityMapper is used to map Keycloak roles to Spring Security authorities. This configuration ensures that Keycloak authentication is properly configured with the specified authority mapping in the Spring Boot application.

Demo ScreenShots

Start the application and go to login screen

screenshot

 

There is no need for authentication or authorization.

Try to access homepage, which requires users to have roles - user and to be authenticated. localhost:8084/homepage automatically redirects to keycloak login when we try it where we have to enter the credentials

screenshot

We can see the following message once we have successfully logged in:

screenshot

 

Now let's test whether the application works with the role by unassigning the "user" role from my-first-user's keycloak.

screenshot

 

Once we click that unassign button we would get a warning message, Are you sure want to remove that role? click yes and you would be landed in below page

screenshot

As a result, when we try to access the homepage, we no longer see the successfully logged in message and instead we would see a error page

screenshot

Conclusion

In this article, we explained what KeyCloak is and how it can be integrated with Spring Boot using an example.

Muthu Annamalai

About author
Technical Writer | Pre-Final Year Student | Code & Community | Developer who works everyday to improve himself.