I have configured the use of Keycloak without using a spring adapter. Since it is deprecated. I created in the console of Keycloak: a REALM, a user, and add roles for the user.
- user Then I created a user and added to him the roles that I created earlier here.
- docker
....
keycloak:
container_name: blog
depends_on:
keycloakdb:
condition: service_healthy
environment:
DB_DATABASE: ${POSTGRESQL_DB}
DB_USER: ${POSTGRESQL_USER}
DB_PASSWORD: ${POSTGRESQL_PASS}
KEYCLOAK_USER: ${KEYCLOAK_USER}
KEYCLOAK_PASSWORD: ${KEYCLOAK_PASSWORD}
DB_VENDOR: ${DB_VENDOR}
DB_ADDR: ${DB_ADDR}
DEBUG_PORT: ${DEBUG_PORT}
DB_PORT: ${DB_PORT}
TZ: ${TZ}
DEBUG: ${DEBUG}
image: jboss/keycloak:latest
.....
here is the application configuration
- pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.guide</groupId>
<artifactId>keycloak-postgres-quick-guide</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>keycloak-postgres-quick-guide</name>
<description>keycloak-postgres-quick-guide</description>
<properties>
<java.version>17</java.version>
<testcontainers.version>1.17.6</testcontainers.version>
<snakeyaml.version>1.33</snakeyaml.version>
<keycloak.version>20.0.2</keycloak.version>
</properties>
<dependencies>
....
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</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>
...
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
<version>${keycloak.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
- security
@Configuration
@EnableWebSecurity(debug = true)
@EnableMethodSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final KeycloakLogoutHandler keycloakLogoutHandler;
@Bean
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests()
.requestMatchers("/customers*", "/users*")
.hasRole("READ")
.anyRequest()
.permitAll();
http.oauth2Login()
.and()
.logout()
.addLogoutHandler(keycloakLogoutHandler)
.logoutSuccessUrl("/");
return http.build();
}
}
- controller
@GetMapping(path = "/customers")
public String customers(Principal principal, Model model) {
addCustomers();
Iterable<Customer> customers = customerRepository.findAll();
model.addAttribute("customers", customers);
model.addAttribute("username", principal.getName());
return "customers";
}
- application.yml
spring:
security:
oauth2:
client:
provider:
keycloak:
issuer-uri: http://localhost:28080/auth/realms/SpringBootKeycloak
user-name-attribute: preferred_username
registration:
keycloak:
authorization-grant-type: authorization_code
client-id: loggin-app
scope: openid
however, when trying to access a protected resource, I get an error :
Sending OAuth2AuthenticationToken [Principal=Name: [user-spring-app], Granted Authorities: [[OIDC_USER, SCOPE_email, SCOPE_openid, SCOPE_profile]], User Attributes: [{at_hash=yGjLEXdKSgOC3J8_QfLyrw, sub=26e4c1c7-cb02-4628-bae9-7a370b53c067, email_verified=false, iss=http://localhost:28080/auth/realms/SpringBootKeycloak, typ=ID, preferred_username=user-spring-app, nonce=yzqik3W-aQtCjP6nQGt-N2CbnyI7O7smrt6mLOZNXY8, sid=07dbaa6a-826c-4139-a956-62a477f6eefe, aud=[loggin-app], acr=1, azp=loggin-app, auth_time=2022-12-21T08:22:10Z, exp=2022-12-21T08:27:10Z, session_state=07dbaa6a-826c-4139-a956-62a477f6eefe, iat=2022-12-21T08:22:10Z, jti=93f19918-bc4a-4435-bbcd-578f7ca2ed36}], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=A0B52BA34017AD4C0183CA1DD48420B8], Granted Authorities=[OIDC_USER, SCOPE_email, SCOPE_openid, SCOPE_profile]] to access denied handler since access is denied org.springframework.security.access.AccessDeniedException: Access Denied
I am not observing the roles that I have assigned to the user
Principal=Name: [user-spring-app], Granted Authorities: [[OIDC_USER, SCOPE_email, SCOPE_openid, SCOPE_profile]],
I am trying to understand how keycloak works, but so far there is only fragmentary information. The example that I found is outdated (the spring-boot-Keycloak-adapter deprecated now). In addition, I have seen different approaches, someone uses hasAuthority(), and someone uses hasRole(), however, I did not understand how it works in relation to Keycloak.
Does anyone have an understanding of how to fix this and explain the principle of such work?