Authentifizierung und Autorisierung selbst zu implementieren ist fehlerträchtig und aufwendig. Keycloak, der Open-Source-Identity-Provider von Red Hat, übernimmt diese Aufgaben — vom Login über Social-Logins bis hin zum feingranularen Rechte-Management. In diesem Artikel zeige ich, wie Keycloak nahtlos in eine Spring-Boot-Anwendung integriert wird.

Was Keycloak kann

Keycloak ist ein IAM-System (Identity and Access Management) mit folgenden Kernfunktionen:

  • Single Sign-On (SSO) — eine Anmeldung für mehrere Anwendungen
  • OAuth 2.0 und OpenID Connect (OIDC) — standardisierte Protokolle
  • Social Login — Anmeldung per Google, GitHub, Facebook etc.
  • Benutzerverwaltung — inklusive Rollen, Gruppen und Berechtigungen
  • Identity Brokering — Delegation an externe Identity Provider

Keycloak mit Docker starten

Für die lokale Entwicklung starten wir Keycloak am einfachsten per Docker:

docker run -d -p 127.0.0.1:8080:8080 \
  -e KC_BOOTSTRAP_ADMIN_USERNAME=admin \
  -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \
  quay.io/keycloak/keycloak:26.6.3 start-dev

Danach ist die Admin-Konsole unter http://localhost:8080/admin erreichbar. Dort legen wir einen Realm namens meine-anwendung an, einen Client spring-boot-client und einen Testbenutzer.

Hinweis zur Keycloak-Distribution: Seit Keycloak 17 basiert die Server-Distribution auf Quarkus, einem Kubernetes-nativen Java-Stack. Die WildFly-basierte Distribution wurde mit Version 20 endgültig entfernt. Der Docker-Befehl oben verwendet die Quarkus-Konfiguration (KC_BOOTSTRAP_ADMIN_*).

Spring Boot konfigurieren

Die Integration auf Spring-Seite erfolgt über den standardisierten Spring Security OAuth2-Client. Der veraltete keycloak-spring-boot-adapter wurde mit Keycloak 19+ endgültig durch OIDC/OAuth2-basierte Adapter abgelöst und ist nicht mehr zu verwenden. Die moderne Konfiguration sieht so aus:

<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>
Code-Sprache: HTML, XML (xml)
<em># application.yml</em>
spring:
  security:
    oauth2:
      client:
        registration:
          keycloak:
            client-id: spring-boot-client
            client-secret: abc123def456
            scope: openid, profile, email
            authorization-grant-type: authorization_code
            redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
        provider:
          keycloak:
            issuer-uri: http://localhost:8080/realms/meine-anwendung
            user-name-attribute: preferred_username
Code-Sprache: PHP (php)

Security-Konfiguration

Die SecurityFilterChain-Bean definiert, welche Pfade geschützt sind und wie authentifiziert wird:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/public/**").permitAll()
                .requestMatchers("/api/admin/**").hasRole("admin")
                .anyRequest().authenticated()
            )
            .oauth2Login(oauth2 -> oauth2
                .defaultSuccessUrl("/dashboard", true)
            )
            .logout(logout -> logout
                .logoutSuccessUrl("/")
            );
        return http.build();
    }
}
Code-Sprache: JavaScript (javascript)

Rollenbasierte Zugriffskontrolle

Keycloak-Rollen werden automatisch als Spring-Security-Authorities abgebildet. Mit @PreAuthorize lassen sich Methoden granular schützen:

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @GetMapping("/api/admin/dashboard")
    @PreAuthorize("hasRole('admin')")
    public String adminDashboard() {
        return "Willkommen im Admin-Bereich!";
    }

    @GetMapping("/api/user/profile")
    @PreAuthorize("hasAnyRole('user', 'admin')")
    public String userProfile() {
        return "Ihr Benutzerprofil";
    }
}
Code-Sprache: CSS (css)

Benutzerinformationen auslesen

Über @AuthenticationPrincipal lassen sich die OIDC-Benutzerdaten direkt in Controller-Methoden injizieren:

import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;

@GetMapping("/whoami")
public Map<String, Object> whoami(@AuthenticationPrincipal OidcUser user) {
    return Map.of(
        "name", user.getFullName(),
        "email", user.getEmail(),
        "roles", user.getAuthorities()
    );
}
Code-Sprache: CSS (css)

Fazit

Keycloak in Kombination mit Spring Boot und Spring Security 7 bietet eine produktiv getestete Lösung für Authentifizierung und Autorisierung. Statt Passwort-Hashing, Session-Management und Rollen-Logik selbst zu bauen, konzentriert man sich auf die Fachdomäne — Keycloak erledigt den Rest. Die Konfiguration ist dank Spring-Security-Autokonfiguration und standardisiertem OIDC-Protokoll in wenigen Minuten erledigt.