{"id":673,"date":"2026-05-23T00:29:49","date_gmt":"2026-05-22T23:29:49","guid":{"rendered":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/?p=673"},"modified":"2026-06-17T00:30:39","modified_gmt":"2026-06-16T23:30:39","slug":"keycloak-in-spring-boot-authentifizierung-autorisierung-leicht-gemacht","status":"publish","type":"post","link":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/?p=673","title":{"rendered":"Keycloak in Spring Boot \u2014 Authentifizierung &amp; Autorisierung leicht gemacht"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Authentifizierung und Autorisierung selbst zu implementieren ist fehlertr\u00e4chtig und aufwendig. Keycloak, der Open-Source-Identity-Provider von Red Hat, \u00fcbernimmt diese Aufgaben \u2014 vom Login \u00fcber Social-Logins bis hin zum feingranularen Rechte-Management. In diesem Artikel zeige ich, wie Keycloak nahtlos in eine Spring-Boot-Anwendung integriert wird.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Was Keycloak kann<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Keycloak ist ein IAM-System (Identity and Access Management) mit folgenden Kernfunktionen:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Single Sign-On (SSO)<\/strong>\u00a0\u2014 eine Anmeldung f\u00fcr mehrere Anwendungen<\/li>\n\n\n\n<li><strong>OAuth 2.0 und OpenID Connect (OIDC)<\/strong>\u00a0\u2014 standardisierte Protokolle<\/li>\n\n\n\n<li><strong>Social Login<\/strong>\u00a0\u2014 Anmeldung per Google, GitHub, Facebook etc.<\/li>\n\n\n\n<li><strong>Benutzerverwaltung<\/strong>\u00a0\u2014 inklusive Rollen, Gruppen und Berechtigungen<\/li>\n\n\n\n<li><strong>Identity Brokering<\/strong>\u00a0\u2014 Delegation an externe Identity Provider<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Keycloak mit Docker starten<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr die lokale Entwicklung starten wir Keycloak am einfachsten per Docker:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">docker run -d -p 127.0.0.1:8080:8080 \\\n  -e KC_BOOTSTRAP_ADMIN_USERNAME=admin \\\n  -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \\\n  quay.io\/keycloak\/keycloak:26.6.3 start-dev\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Danach ist die Admin-Konsole unter&nbsp;<code>http:\/\/localhost:8080\/admin<\/code>&nbsp;erreichbar. Dort legen wir einen Realm namens&nbsp;<code>meine-anwendung<\/code>&nbsp;an, einen Client&nbsp;<code>spring-boot-client<\/code>&nbsp;und einen Testbenutzer.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Hinweis zur Keycloak-Distribution:<\/strong>&nbsp;Seit Keycloak 17 basiert die Server-Distribution auf Quarkus, einem Kubernetes-nativen Java-Stack. Die WildFly-basierte Distribution wurde mit Version 20 endg\u00fcltig entfernt. Der Docker-Befehl oben verwendet die Quarkus-Konfiguration (<code>KC_BOOTSTRAP_ADMIN_*<\/code>).<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">Spring Boot konfigurieren<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Die Integration auf Spring-Seite erfolgt \u00fcber den standardisierten Spring Security OAuth2-Client. Der veraltete&nbsp;<code>keycloak-spring-boot-adapter<\/code>&nbsp;wurde mit Keycloak 19+ endg\u00fcltig durch OIDC\/OAuth2-basierte Adapter abgel\u00f6st und ist nicht mehr zu verwenden. Die moderne Konfiguration sieht so aus:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.springframework.boot<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>spring-boot-starter-oauth2-client<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.springframework.boot<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>spring-boot-starter-security<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">&lt;em&gt;<span class=\"hljs-comment\"># application.yml&lt;\/em&gt;<\/span>\nspring:\n  security:\n    oauth2:\n      client:\n        registration:\n          keycloak:\n            client-id: spring-boot-client\n            client-secret: abc123def456\n            scope: openid, profile, email\n            authorization-grant-type: authorization_code\n            redirect-uri: <span class=\"hljs-string\">\"{baseUrl}\/login\/oauth2\/code\/{registrationId}\"<\/span>\n        provider:\n          keycloak:\n            issuer-uri: http:<span class=\"hljs-comment\">\/\/localhost:8080\/realms\/meine-anwendung<\/span>\n            user-name-attribute: preferred_username\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Security-Konfiguration<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Die&nbsp;<code>SecurityFilterChain<\/code>-Bean definiert, welche Pfade gesch\u00fctzt sind und wie authentifiziert wird:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import<\/span> org.springframework.context.annotation.Bean;\n<span class=\"hljs-keyword\">import<\/span> org.springframework.context.annotation.Configuration;\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.config.annotation.web.builders.HttpSecurity;\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.web.SecurityFilterChain;\n\n@Configuration\npublic <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">SecurityConfig<\/span> <\/span>{\n\n    @Bean\n    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {\n        http\n            .authorizeHttpRequests(auth -&gt; auth\n                .requestMatchers(<span class=\"hljs-string\">\"\/public\/**\"<\/span>).permitAll()\n                .requestMatchers(<span class=\"hljs-string\">\"\/api\/admin\/**\"<\/span>).hasRole(<span class=\"hljs-string\">\"admin\"<\/span>)\n                .anyRequest().authenticated()\n            )\n            .oauth2Login(oauth2 -&gt; oauth2\n                .defaultSuccessUrl(<span class=\"hljs-string\">\"\/dashboard\"<\/span>, <span class=\"hljs-literal\">true<\/span>)\n            )\n            .logout(logout -&gt; logout\n                .logoutSuccessUrl(<span class=\"hljs-string\">\"\/\"<\/span>)\n            );\n        <span class=\"hljs-keyword\">return<\/span> http.build();\n    }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Rollenbasierte Zugriffskontrolle<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Keycloak-Rollen werden automatisch als Spring-Security-Authorities abgebildet. Mit&nbsp;<code>@PreAuthorize<\/code>&nbsp;lassen sich Methoden granular sch\u00fctzen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">import<\/span> <span class=\"hljs-selector-tag\">org<\/span><span class=\"hljs-selector-class\">.springframework<\/span><span class=\"hljs-selector-class\">.security<\/span><span class=\"hljs-selector-class\">.access<\/span><span class=\"hljs-selector-class\">.prepost<\/span><span class=\"hljs-selector-class\">.PreAuthorize<\/span>;\n<span class=\"hljs-selector-tag\">import<\/span> <span class=\"hljs-selector-tag\">org<\/span><span class=\"hljs-selector-class\">.springframework<\/span><span class=\"hljs-selector-class\">.web<\/span><span class=\"hljs-selector-class\">.bind<\/span><span class=\"hljs-selector-class\">.annotation<\/span><span class=\"hljs-selector-class\">.GetMapping<\/span>;\n<span class=\"hljs-selector-tag\">import<\/span> <span class=\"hljs-selector-tag\">org<\/span><span class=\"hljs-selector-class\">.springframework<\/span><span class=\"hljs-selector-class\">.web<\/span><span class=\"hljs-selector-class\">.bind<\/span><span class=\"hljs-selector-class\">.annotation<\/span><span class=\"hljs-selector-class\">.RestController<\/span>;\n\n<span class=\"hljs-keyword\">@RestController<\/span>\npublic class UserController {\n\n    <span class=\"hljs-keyword\">@GetMapping<\/span>(\"\/api\/admin\/dashboard\")\n    @PreAuthorize(<span class=\"hljs-string\">\"hasRole('admin')\"<\/span>)\n    public String adminDashboard() {\n        <span class=\"hljs-selector-tag\">return<\/span> \"<span class=\"hljs-selector-tag\">Willkommen<\/span> <span class=\"hljs-selector-tag\">im<\/span> <span class=\"hljs-selector-tag\">Admin-Bereich<\/span>!\";\n    }\n\n    <span class=\"hljs-keyword\">@GetMapping<\/span>(\"\/api\/user\/profile\")\n    @PreAuthorize(<span class=\"hljs-string\">\"hasAnyRole('user', 'admin')\"<\/span>)\n    public String userProfile() {\n        <span class=\"hljs-selector-tag\">return<\/span> \"<span class=\"hljs-selector-tag\">Ihr<\/span> <span class=\"hljs-selector-tag\">Benutzerprofil<\/span>\";\n    }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Benutzerinformationen auslesen<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u00dcber&nbsp;<code>@AuthenticationPrincipal<\/code>&nbsp;lassen sich die OIDC-Benutzerdaten direkt in Controller-Methoden injizieren:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">import<\/span> <span class=\"hljs-selector-tag\">org<\/span><span class=\"hljs-selector-class\">.springframework<\/span><span class=\"hljs-selector-class\">.security<\/span><span class=\"hljs-selector-class\">.core<\/span><span class=\"hljs-selector-class\">.annotation<\/span><span class=\"hljs-selector-class\">.AuthenticationPrincipal<\/span>;\n<span class=\"hljs-selector-tag\">import<\/span> <span class=\"hljs-selector-tag\">org<\/span><span class=\"hljs-selector-class\">.springframework<\/span><span class=\"hljs-selector-class\">.security<\/span><span class=\"hljs-selector-class\">.oauth2<\/span><span class=\"hljs-selector-class\">.core<\/span><span class=\"hljs-selector-class\">.oidc<\/span><span class=\"hljs-selector-class\">.user<\/span><span class=\"hljs-selector-class\">.OidcUser<\/span>;\n\n<span class=\"hljs-keyword\">@GetMapping<\/span>(\"\/whoami\")\npublic Map&lt;String, Object&gt; whoami(@AuthenticationPrincipal OidcUser user) {\n    <span class=\"hljs-selector-tag\">return<\/span> <span class=\"hljs-selector-tag\">Map<\/span><span class=\"hljs-selector-class\">.of<\/span>(\n        \"<span class=\"hljs-selector-tag\">name<\/span>\", <span class=\"hljs-selector-tag\">user<\/span><span class=\"hljs-selector-class\">.getFullName<\/span>(),\n        \"<span class=\"hljs-selector-tag\">email<\/span>\", <span class=\"hljs-selector-tag\">user<\/span><span class=\"hljs-selector-class\">.getEmail<\/span>(),\n        \"<span class=\"hljs-selector-tag\">roles<\/span>\", <span class=\"hljs-selector-tag\">user<\/span><span class=\"hljs-selector-class\">.getAuthorities<\/span>()\n    );\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Fazit<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Keycloak in Kombination mit Spring Boot und Spring Security 7 bietet eine produktiv getestete L\u00f6sung f\u00fcr Authentifizierung und Autorisierung. Statt Passwort-Hashing, Session-Management und Rollen-Logik selbst zu bauen, konzentriert man sich auf die Fachdom\u00e4ne \u2014 Keycloak erledigt den Rest. Die Konfiguration ist dank Spring-Security-Autokonfiguration und standardisiertem OIDC-Protokoll in wenigen Minuten erledigt.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Authentifizierung und Autorisierung selbst zu implementieren ist fehlertr\u00e4chtig und aufwendig. Keycloak, der Open-Source-Identity-Provider von Red Hat, \u00fcbernimmt diese Aufgaben \u2014 vom Login \u00fcber 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 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,5],"tags":[],"class_list":["post-673","post","type-post","status-publish","format-standard","hentry","category-plain_java","category-spring"],"_links":{"self":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/673","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=673"}],"version-history":[{"count":1,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/673\/revisions"}],"predecessor-version":[{"id":674,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/673\/revisions\/674"}],"wp:attachment":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=673"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=673"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=673"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}