Spring Boot And Keycloak Integration Example

Keycloak is an open-source identity and access management system. With the help of Keycloak, we can add the required application security, like user authentication, authorization, etc. We can easily integrate the spring boot application with the Keycloak server.

In this article, we will learn how we can integrate the Keycloak server with the Spring boot application. We will also learn how to implement user authentication and authorization.

Version details:

  • Spring boot version: 3.1.0
  • Keycloak docker image version: 21.1.1

Table of Contents

Setting up the Keycloak server

We can download the latest version of the Keycloak server from the official website.

We will use the Keycloak Docker image to set up the server locally.

Running the Keycloak docker container

Run the below command to start the Keycloak docker container in the local machine.

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

The above command will start the Keycloak server in development mode. We can access the Keycloak admin console on port 8080.

Also, we have set the admin credentials(username and password) to admin. Once the container is up, we can log in to the Keycloak admin console, as shown below.

keycloak admin console login page

Creating a realm

A realm allows us to create an isolated group of applications and users. By default, a master realm is available when we start the keycloak server initially.

To create a new realm, click on the realm drop-down and click on Create Realm button.

keycloak create realm

Enter the realm name and click on Create button.

create realm page

Adding the roles

After creating the new realm, let us add roles and users.

We can use the Roles set-up authorization. We can assign these roles to the available users later. To create a new user role, navigate to the Realm roles tab and click the Create role button.

Let us create two roles, called USER and ADMIN. We will assign these roles to the users in the later steps.

realm roles creation

Creating and assigning the roles

Now we have our roles ready, let us create two users and assign these roles to them.

To create a new user, navigate to Users and click on Add user button. Make sure to select option Email verified option to Yes, so that no verification is needed from the user’s end to use the create user account.

create a new user keycloak

Once the user creation, we can add the user credentials by navigating to the Credentials tab.

Click on the Set password button and set the password details.

keycloak user credentials

We can navigate to the Role mapping tab and click the Assign role button to assign a role to the user. Select the ADMIN role to assign the role to the current user.

keycloak user role assignment

Similarly, create another user and assign the USER role to it.

Creating and configuring Spring Boot app

We will create a simple spring boot application that exposes REST APIs. These APIs have restricted access based on the user role.

Creating the spring boot app

Create a new Spring boot application with the following dependencies.

We have added web dependency and other required spring security dependencies.

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-security</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-oauth2-resource-server</artifactId>
</dependency>
<dependency>
	<groupId>org.keycloak</groupId>
	<artifactId>keycloak-spring-boot-starter</artifactId>
	<version>21.1.0</version>
</dependency>
<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
	<optional>true</optional>
</dependency>

Creating client configuration on Keycloak

To register a new client, we can navigate to the Clients tab and click on the Create client button.

Enter the client ID and click on Next button.

create client

Select the Client authentication and Authorization option and click on the Next button.

client id creation

Enter the Root URL as http://localhost:8081, the spring boot application’s base URL running on the local machine.

create client id

Configuring the application properties

Add the below application configurations to integrate the application with the Keycloak server.

server:
  port: 8081

spring:
  security:
    oauth2:
      client:
        registration:
          keycloak:
            client-id: asbnotebook-client-id
            client-secret: AUujktMictvjRPX0IZvmkDhfccHd8gxd
            scope: openid
            authorization-grant-type: authorization_code
        provider:
          keycloak:
            issuer-uri: http://localhost:8080/realms/ASBNotebook
            user-name-attribute: preferred_username
      resourceserver:
        jwt:
          issuer-uri: http://localhost:8080/realms/ASBNotebook
  • We are going to use 8081 as the port for the spring boot app.
  • The client-id property is the Keycloak client ID, that we have created in the previous step.
  • The client-secret value can get from the Keycloak admin console by navigating to the Clients > select the created client > Credentials > Client secret.
  • The issuer-uri value can be found from the Open ID configuration, which is located under the page Realm settings > Endpoints.

Configuring the spring security

Let us create the required configuration classes that define the security configuration of our spring boot app.

First, we will create a custom authorities converter class. This class helps convert the user roles defined in the Keycloak to spring supported format.

In spring security, every user role should have a ROLE_ prefix. The below class helps to convert the user roles into spring security’s supported format by adding the required prefix.

public class AuthoritiesConverter implements Converter<Jwt, Collection<GrantedAuthority>> {

    @Override
    public Collection<GrantedAuthority> convert(Jwt source) {
        Map<String, Object> realmAccess = source.getClaimAsMap("realm_access");

        if (Objects.nonNull(realmAccess)) {
            List<String> roles = (List<String>) realmAccess.get("roles");

            if (Objects.nonNull(roles)) {
                return roles.stream()
                        .map(rn -> new SimpleGrantedAuthority("ROLE_" + rn))
                        .collect(Collectors.toList());
            }
        }
        return List.of();
    }
}

We will apply this custom authority converter class to the spring security configuration. For this, create a custom spring security class, as shown below.

This spring configuration class defines the SecurityFilterChain bean that authenticates every request received by the spring boot application.

We are also applying the custom AuthoritiesConverter class that we created in the earlier step.

The @EnableMethodSecurity annotation helps in enabling the method-level security validation for our spring application.

@Configuration
@EnableWebSecurity
@EnableMethodSecurity(jsr250Enabled = true)
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(authorizationManagerRequestMatcherRegistry ->
                authorizationManagerRequestMatcherRegistry
                        .anyRequest()
                        .authenticated()
        );

        http.oauth2ResourceServer(oauth2ResourceServer ->
                oauth2ResourceServer.jwt(jwt ->
                        jwt.jwtAuthenticationConverter(jwtAuthenticationConverter())
                )
        );

        return http.build();
    }

    private JwtAuthenticationConverter jwtAuthenticationConverter() {
        JwtAuthenticationConverter jwtConverter = new JwtAuthenticationConverter();
        jwtConverter.setJwtGrantedAuthoritiesConverter(new AuthoritiesConverter());
        return jwtConverter;
    }
}

Creating a test resource

Now our spring boot application is configured with the required security configurations. Let us create some REST API endpoints and apply the method-level security configurations.

Create a Rest controller class as shown below.

@RestController
public class TestResource {

    @GetMapping("/common")
    public String getEveryoneText() {
        return "Both ADMIN and USER can access this!!";
    }

    @GetMapping("/user")
    @RolesAllowed("USER")
    public String getUserText() {
        return "hello USER";
    }

    @GetMapping("/admin")
    @RolesAllowed("ADMIN")
    public String getAdminText() {
        return "hello ADMIN";
    }
}

Here, we have defined three REST APIs.

The /common REST point can be accessed by both of the users having either the role USER or ADMIN.

The /user endpoint allows access to users having role USER and the /admin endpoint allows the users having the role ADMIN.

Testing the app

To access the REST endpoints, we need to pass the authentication token in the request header.

Adding the authentication details in postman

We can get the token from the Keycloak using the Postman application, as shown below.

Under the Authorization section, select the Type value as OAuth 2.0 and enter configuration details like Grant Type, Client ID, Client secret, user name, and password.

postman oauth token generation

Click on the Generate Token button to generate the access token.

postman oauth token generation

We can use the generated token in our request by clicking the Use Token button.

postman oauth token generation

Testing the endpoints

Run the spring boot application.

When we invoke the /common endpoint, with any of the users we have created earlier, we get the response as shown below.

spring boot keycloak oauth2 example

Invoke the /admin endpoint with the user having the role ADMIN  should get the successful response as shown below.

spring boot keycloak example

If we try to invoke the /user endpoint with the user having the role USER, we should get the success response as shown below.

spring boot keycloak example

When we try to invoke the /admin endpoint now with the same user, we get the forbidden error.

Conclusion

In this article, we learned how to integrate keycloak with the Spring boot application.

We also learned how to restrict resources based on the roles assigned to the user.

The example code is available on GitHub.

Spring Boot And Keycloak Integration Example

Leave a Reply

Scroll to top

Discover more from ASB Notebook

Subscribe now to keep reading and get access to the full archive.

Continue reading