Home > AI > Backend > SpringBoot >

Intergrate Keycloak in SpringBoot

Part 1: Configure the Keycloak server to get the OAuth2.0 token

Step 1: Download the Keycloak server

https://www.keycloak.org/downloads

Step 2: start the Keycloak server

cd ~/downloads/keycloak-16.1.0/bin 

./standalone.sh -Djboss.socket.binding.port-offset=100

Above command means the Keycloak port will be offset compared to default port

default portoffsetresult port
80801008180
80802008280


Step 3: enter the Keycloak management console to configure

address is localhost:8180

3-1: Administration

Username, password

3-2: Enter the administration portal

Add Client, Role, User

3-3: Get the OAuth token

  1. get the token url Realm / General / Enpoints / OpenID Endpoint Configuration, get token_endpoint

2. Open the Postman

Type Oauth 2.0
scopeopenid
ClientID
Grant typepassword
Username
Password

Part 2: Configure the Keycloak SpringBoot Adapter

Find this offical link for Keycloak SpringBoot Adapter

https://www.keycloak.org/docs/latest/securing_apps/#_spring_boot_adapter

Step 1: Add dependencies at pom.xml

<dependency>
    <groupId>org.keycloak</groupId>
    <artifactId>keycloak-spring-boot-starter</artifactId>
</dependency>


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.keycloak.bom</groupId>
      <artifactId>keycloak-adapter-bom</artifactId>
      <version>16.1.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

Step 2: Keycloak config

keycloak.realm = master

# 127.0.0.1 is different from localhost
keycloak.auth-server-url = http://localhost:8180/auth
keycloak.ssl-required = external

# client-id
keycloak.resource = pte 
#keycloak.credentials.secret = 11111111-1111-1111-1111-1x11111111111
keycloak.use-resource-role-mappings = true

Step 3: SecurityConfig.java

@KeycloakConfiguration
@Import(KeycloakSpringBootConfigResolver.class)
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter
{
    /**
     * Registers the KeycloakAuthenticationProvider with the authentication manager.
     */
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

        KeycloakAuthenticationProvider provider = keycloakAuthenticationProvider();
        provider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        auth.authenticationProvider(provider);
    }

    /**
     * Defines the session authentication strategy.
     */
    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(buildSessionRegistry());
    }

    @Bean
    protected SessionRegistry buildSessionRegistry() {
        return new SessionRegistryImpl();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception
    {
        super.configure(http);
        http
                .csrf().disable() // otherwise will have 403 error for all methods except GET
                .authorizeRequests()
                .antMatchers("/employees*").hasRole("pte-admin")
                .anyRequest().permitAll();
    }
}

Part 3: Configure the SpringBoot Resource Server

Employee.java

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity // This tells Hibernate to make a table out of this class
@Table
public class Employee {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Integer id;

    private String name;

    private String department;
    
}

EmployeeController.java

@RestController
@RequestMapping(path="/employees")
public class EmployeeController {
    @Autowired
    private EmployeeRepository employeeRepository;


    @PostMapping(path="/")
    public ResponseEntity<Employee> save (@RequestBody Employee employee) {

        return ResponseEntity.ok(employeeRepository.save(employee));
    }

    @GetMapping(path="/")
    public ResponseEntity<List<Employee>> findAll () {
        return ResponseEntity.ok((List<Employee>) employeeRepository.findAll());

    }

}

EmployeeRepository.java

import org.springframework.data.repository.CrudRepository;

/**
 * @description
 */
public interface EmployeeRepository extends CrudRepository<Employee, Integer> {

}

Part 4: set Mysql Server for Keycloak

Step 1: Create mysql schema for Keycloak

$ mysql -uroot -p


mysql> CREATE USER 'keycloak'@'%' IDENTIFIED BY 'keycloak';
Query OK, 0 rows affected (0.01 sec)


mysql> CREATE DATABASE keycloak CHARACTER SET utf8 COLLATE utf8_unicode_ci;
Query OK, 1 row affected (0.00 sec)


mysql> GRANT ALL PRIVILEGES ON keycloak.* TO 'keycloak'@'%';
Query OK, 0 rows affected (0.00 sec)


mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

Step 2: JDBC setup

download the mysql connector jar https://dev.mysql.com/downloads/connector/j/. My version is mysql-connector-java-8.0.27.jar

Put the jar under keycloak/modules/system/layers/keycloak/com/mysql/main

$ sudo mkdir -p ~/Downloads/keycloak/modules/system/layers/keycloak/com/mysql/main

$ sudo cd ~/Downloads/keycloak/modules/system/layers/keycloak/com/mysql/main

$ sudo cp ~/Downloads/mysql-connector-java-5.1.42/mysql-connector-java-5.1.42-bin.jar .

$ sudo touch module.xml

module.xml

<?xml version="1.0" ?>
<module xmlns="urn:jboss:module:1.3" name="com.mysql">
 <resources>
  <resource-root path="mysql-connector-java-5.1.42-bin.jar" />
 </resources>
 <dependencies>
  <module name="javax.api"/>
  <module name="javax.transaction.api"/>
 </dependencies>
</module>

Step 3: Declare and Load JDBC Driver

standalone.xml

~/Downloads/keycloak-16.1.0/standalone/configuration/standalone.xml 

<subsystem xmlns="urn:jboss:domain:datasources:4.0">
    <datasources>
        ...
        <drivers>



            <!-- new -->
            <driver name="mysql" module="com.mysql">
                  <driver-class>com.mysql.cj.jdbc.Driver</driver-class>
            </driver>      




              <driver name="h2" module="com.h2database.h2">
                  <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
              </driver>
          </drivers>
      </datasources>
    </subsystem>

Note:

  • name is set to mysql, but can be everything we want
  • we specify the module the attribute which points to the module the package we created earlier for the driver JAR
  • finally, we specify the driver’s Java class, which in case of MySQL is com.mysql.cj.jdbc.Driver

Step 4: Datasource setup

We are going to change KeycloakDS bloak

<datasource jndi-name="java:jboss/datasources/KeycloakDS" pool-name="KeycloakDS" enabled="true" use-java-context="true" statistics-enabled="${wildfly.datasources.statistics-enabled:${wildfly.statistics-enabled:false}}">

    <connection-url>jdbc:mysql://localhost:3306/keycloak</connection-url>
        <driver>mysql</driver>
        <pool>
            <min-pool-size>5</min-pool-size>
            <max-pool-size>15</max-pool-size>
        </pool>
        <security> 
            <user-name>keycloak</user-name>
            <password>keycloak</password>
        </security>
</datasource>

Note

  • we’ve searched for datasource definition for KeycloakDS.
  • we modified the connection-url to point to the MySQL server
  • we defined the driver we use for the connection; this is the logical name of the JDBC driver we declared in the previous section (mysql)
  • it is expensive to open a new connection to a database every time you want to perform a transaction. To compensate, the datasource implementation maintains a pool of open connections. The max-pool-size specifies the maximum number of connections it will pool. We may want to change the value of this depending on the load of the system.
  • finally, we need to define the database user-name and password, that is needed to connect to the database.

Step 5: Load module for MySQL Driver

$ cd ~/downloads/keycloak-16.1.0/bin 

$ ./jboss-cli.sh

You are disconnected at the moment. Type 'connect' to connect to the server or 'help' for the list of supported commands.

[disconnected /] module add --name=com.mysql --resources=~/Downloads/keycloak-16.1.0/modules/system/layers/keycloak/com/mysql/main/mysql-connector-java-8.0.27.jar --dependencies=javax.api,javax.transaction.api

[disconnected /] 

Step 6: Booting up Keycloak

./standalone.sh -Djboss.socket.binding.port-offset=100

Part 5: Test

GET http://localhost:8081/employees/

References:

https://medium.com/@pratik.dandavate/setting-up-keycloak-standalone-with-mysql-database-7ebb614cc229

Leave a Reply