Spring Boot Keycloak SSO Example (2024)
In this tutorial, will demonstrate how to integrate keycloak single sign on with Spring Boot Application.
Keycloak Tutorial :
- Install Keycloak with MySQL
- Keycloak - Create Users/Roles in Realm
- Spring Boot Keycloak SSO Example
Q: What is Keycloak?
Keycloak is a modern application and service-oriented open source Identity and Access Management system. Single-Sign-On (SSO), Identity Brokering and Social Login, User Federation, Client Adapters, an Admin Console, and an Account Management Console are some of the features offered by Keycloak.
It works with a variety of protocols, including Oauth 2.0, SAML 2.0 and OpenID Connect. User credentials can also be stored locally or via an LDAP or Kerberos backend.
When a user logs in successfully with Keycloak, they are given a token, which is saved as a cookie in the browser, and they are automatically sent back to the service they were trying to access. This token usually includes a username as well as information about the user's permissions.
Q: What is Single Sign On (SSO)?
Single sign-on enables users to log in once and access services without having to re-enter their credentials. Auditing and security are made easier with a central authentication place.
Create Spring Boot application
Create Spring Boot application from Spring Initializr.
Project Structure
Add dependencies
Add keycloak-spring-boot-starter
, spring-boot-starter-security
and web
dependencies in pom.xml
.
<?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 https://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.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.techgeeknext</groupId>
<artifactId>spring-boot-keycloak-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-keycloak-example</name>
<description>Spring Boot + Keycloak Example</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<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>
Take a look at our suggested posts:
Application Properties
Add Keycloak connection detail. Follow steps to Install Keycloak with MySQL and to create client, users and role.
keycloak.auth-server-url=http://localhost:9090/auth
keycloak.realm=TechGeekNextOrg
keycloak.resource=crud-application
keycloak.credentials.secret=GJNgdhjhaBFDSGeLZfYCOwghg
Keycloak Security Configuration
Create KeycloakSecurityConfig
class.
- @KeycloakConfiguration: This annotation has
Configuration
,ComponentScan
forKeycloakSecurityComponents
andEnableWebSecurity
. - Authentication Manager: Set
KeycloakAuthenticationProvider
to the authentication manager. - SimpleAuthorityMapper: It adds the prefix ROLE_ to keycloak roles.
- KeycloakConfigResolver(): It uses
application.properties
instead of defaultWEB-INF/keycloack.json
. - configure(): Override the
configure()
method and set the roles to the rest endpoints, and for invalid roles and exceptions set denied response.
package com.techgeeknext.security;
import org.keycloak.adapters.KeycloakConfigResolver;
import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
import org.keycloak.adapters.springsecurity.KeycloakConfiguration;
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.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;
@KeycloakConfiguration
public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
KeycloakAuthenticationProvider keycloakAuthenticationProvider = new KeycloakAuthenticationProvider();
//SimpleAuthorityMapper adds the prefix ROLE_ to keycloak roles.
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
//use below code for application.properties instead of WEB-INF/keycloack.json
@Bean
public KeycloakConfigResolver KeycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/hello").permitAll()
.antMatchers("/departments").hasRole("ADMIN")
.antMatchers("/employees").hasRole("USER")
.anyRequest().authenticated()
.and().exceptionHandling().accessDeniedPage("/access-denied-response");
}
}
Employee Controller
Create controller class with rest endpoints to test the roles.
package com.techgeeknext.controller;
import com.techgeeknext.model.Department;
import com.techgeeknext.model.Employee;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@RestController
public class EmployeeController {
@GetMapping("/hello")
public String hello() {
return "hello";
}
@GetMapping("/employees")
public ResponseEntity<List<Employee>> getEmployees() {
Employee emp1 = Employee.builder().name("aaa").role("user").id(1).build();
Employee emp2 = Employee.builder().name("bbb").role("user").id(2).build();
List<Employee> emps = new ArrayList<>();
emps.add(emp1);
emps.add(emp2);
return new ResponseEntity<>(emps, HttpStatus.OK);
}
@GetMapping("/departments")
public ResponseEntity<List<Department>> getDeparts() {
Department dept1 = Department.builder().name("HR").id(1).build();
Department dept2 = Department.builder().name("Sales").id(2).build();
List<Department> departments = new ArrayList<>();
departments.add(dept1);
departments.add(dept2);
return new ResponseEntity<>(departments,HttpStatus.NOT_FOUND);
}
@GetMapping("/access-denied-response")
public String accessDenied() {
return "Access Denied... You don't have permission.";
}
}
Test Spring Boot Keycloak SSO
- Start the Keycloak by following the steps from Install Keycloak with MySQL and to create client, users and role.
- Start the Spring Boot Application by running
spring-boot:run
or by running main class. - Without any Role/Authentication: Open the browser and use http://localhost:8080/hello. This rest endpoint will not required any authentication.
- USER Role: The
/employees
rest endpoint has the USER role. Open a browser with URL http://localhost:8080/employees. - USER Role: Enter the username and password.
- USER Role: Since we enabled the reset password option in the Keycloak while registering the user, it will prompt you to reset the password the first time you use it.
- USER Role: We can see the output after logging in.
- Invalid ROLE: If we try to access
/department
rest endpoint with invalid USER Role, will get Access Denied response. - Remember to clear the cache before attempting to login with another user. Use the CTRL + SHIFT + DEL keyboard shortcut. Press the Clear button. Close and reopen the browser.
- ADMIN Role: The
/departments
rest endpoint has the ADMIN role. Open the browser with URL http://localhost:8080/departments, enter the username and password. Since we enabled the reset password option in the Keycloak while registering the user, it will prompt you to reset the password the first time you use it.We can see the output after logging in.
Download Source Code
The full source code for this article can be found below.
- Download it here - Spring Boot Keycloak SSO Example