<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Testing Archive | INOTEQ GmbH</title>
	<atom:link href="https://www.inoteq.com/tag/testing/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.inoteq.com/tag/testing/</link>
	<description>IT Unternehmensberatung, Software Entwicklung, IT Infrastruktur aus Karlsruhe</description>
	<lastBuildDate>Mon, 12 Feb 2024 16:21:21 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.4.5</generator>

<image>
	<url>https://www.inoteq.com/wp-content/uploads/2019/12/cropped-Inoteq_Logo_trans_icon-1-32x32.png</url>
	<title>Testing Archive | INOTEQ GmbH</title>
	<link>https://www.inoteq.com/tag/testing/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Automatisches Front-End-Testing einer OAuth 2.0 Spring-Boot Anwendungen</title>
		<link>https://www.inoteq.com/2024/02/08/automatisches-front-end-testing-einer-oauth-2-0-spring-boot-anwendungen/</link>
					<comments>https://www.inoteq.com/2024/02/08/automatisches-front-end-testing-einer-oauth-2-0-spring-boot-anwendungen/#respond</comments>
		
		<dc:creator><![CDATA[Alexander Kusmin]]></dc:creator>
		<pubDate>Thu, 08 Feb 2024 15:09:39 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Keycloak]]></category>
		<category><![CDATA[OAuth2]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Testing]]></category>
		<guid isPermaLink="false">https://www.inoteq.com/?p=2754</guid>

					<description><![CDATA[<p>Dieser Beitrag vertieft die Thematik des automatischen Front-End-Testings einer OAuth 2.0 Spring Boot-Anwendung. Er fungiert als komplementäre Erweiterung zu unserem vorangegangenen Beitrag über Spring Boot mit OAuth 2.0 und Keycloak. Im Fokus stehen die Integration von Keycloak als zentraler OAuth 2.0 Dienst und die Rolle von Spring Boot als fundamentale Anwendungsplattform. Ein kurzer Rückblick auf [&#8230;]</p>
<p>Der Beitrag <a href="https://www.inoteq.com/2024/02/08/automatisches-front-end-testing-einer-oauth-2-0-spring-boot-anwendungen/">Automatisches Front-End-Testing einer OAuth 2.0 Spring-Boot Anwendungen</a> erschien zuerst auf <a href="https://www.inoteq.com">INOTEQ GmbH</a>.</p>
]]></description>
										<content:encoded><![CDATA[		<div data-elementor-type="wp-post" data-elementor-id="2754" class="elementor elementor-2754" data-elementor-post-type="post">
						<section class="elementor-section elementor-top-section elementor-element elementor-element-e45a7f1 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="e45a7f1" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-b443f44" data-id="b443f44" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
						<div class="elementor-element elementor-element-5ac51a7 elementor-widget elementor-widget-spacer" data-id="5ac51a7" data-element_type="widget" data-widget_type="spacer.default">
				<div class="elementor-widget-container">
					<div class="elementor-spacer">
			<div class="elementor-spacer-inner"></div>
		</div>
				</div>
				</div>
				<div class="elementor-element elementor-element-d21d227 elementor-widget elementor-widget-html" data-id="d21d227" data-element_type="widget" data-widget_type="html.default">
				<div class="elementor-widget-container">
			<!-- Only for Code Snippet Styles -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/themes/prism-coy.min.css" integrity="sha256-VcuSs+n31yebPlEcehu6PvnidJ808ScFBsK8+tJKX+Q=" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/components/prism-core.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/plugins/autoloader/prism-autoloader.min.js"></script>
<style>
    :not(pre) > code[class*=language-].inline {
        padding: 0 0.2rem;
        color: #000;
    }
</style>		</div>
				</div>
				<div class="elementor-element elementor-element-d6809f5 elementor-widget elementor-widget-theme-post-title elementor-page-title elementor-widget-heading" data-id="d6809f5" data-element_type="widget" data-widget_type="theme-post-title.default">
				<div class="elementor-widget-container">
			<h1 class="elementor-heading-title elementor-size-default">Automatisches Front-End-Testing einer OAuth 2.0 Spring-Boot Anwendungen</h1>		</div>
				</div>
				<div class="elementor-element elementor-element-f62244b elementor-widget elementor-widget-post-info" data-id="f62244b" data-element_type="widget" data-widget_type="post-info.default">
				<div class="elementor-widget-container">
					<ul class="elementor-inline-items elementor-icon-list-items elementor-post-info">
								<li class="elementor-icon-list-item elementor-repeater-item-170d69d elementor-inline-item" itemprop="datePublished">
						<a href="https://www.inoteq.com/2024/02/08/">
											<span class="elementor-icon-list-icon">
								<i aria-hidden="true" class="fas fa-calendar"></i>							</span>
									<span class="elementor-icon-list-text elementor-post-info__item elementor-post-info__item--type-date">
										Februar 8, 2024					</span>
									</a>
				</li>
				<li class="elementor-icon-list-item elementor-repeater-item-680cb58 elementor-inline-item" itemprop="author">
						<a href="https://www.inoteq.com/author/akusmin/">
											<span class="elementor-icon-list-icon">
								<i aria-hidden="true" class="far fa-user-circle"></i>							</span>
									<span class="elementor-icon-list-text elementor-post-info__item elementor-post-info__item--type-author">
										Alexander Kusmin					</span>
									</a>
				</li>
				<li class="elementor-icon-list-item elementor-repeater-item-0db5256 elementor-inline-item" itemprop="about">
										<span class="elementor-icon-list-icon">
								<i aria-hidden="true" class="fas fa-tags"></i>							</span>
									<span class="elementor-icon-list-text elementor-post-info__item elementor-post-info__item--type-terms">
										<span class="elementor-post-info__terms-list">
				<a href="https://www.inoteq.com/tag/keycloak/" class="elementor-post-info__terms-list-item">Keycloak</a>, <a href="https://www.inoteq.com/tag/oauth2/" class="elementor-post-info__terms-list-item">OAuth2</a>, <a href="https://www.inoteq.com/tag/spring/" class="elementor-post-info__terms-list-item">Spring</a>, <a href="https://www.inoteq.com/tag/testing/" class="elementor-post-info__terms-list-item">Testing</a>				</span>
					</span>
								</li>
				</ul>
				</div>
				</div>
				<div class="elementor-element elementor-element-a90db89 elementor-widget elementor-widget-text-editor" data-id="a90db89" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p>Dieser Beitrag vertieft die Thematik des automatischen Front-End-Testings einer OAuth 2.0 Spring Boot-Anwendung. Er fungiert als komplementäre Erweiterung zu unserem vorangegangenen Beitrag über <a href="https://www.inoteq.com/2023/11/30/oauth2-keycloak-locally/" target="_blank" rel="noopener">Spring Boot mit OAuth 2.0 und Keycloak</a>. Im Fokus stehen die Integration von Keycloak als zentraler OAuth 2.0 Dienst und die Rolle von Spring Boot als fundamentale Anwendungsplattform.</p><p>Ein kurzer Rückblick auf die wesentlichen Konzepte von OAuth 2.0 sowie die spezifische Bedeutung von Keycloak bietet einen soliden Ausgangspunkt. In unserem vorherigen Beitrag haben wir bereits die Integration von Spring Boot und Keycloak beleuchtet, um eine sichere OAuth 2.0-Authentifizierung zu gewährleisten. Falls Sie diesen Beitrag bisher nicht verfolgt haben, empfiehlt es sich, einen Blick darauf zu werfen, da der vorliegende Beitrag nahtlos auf den dort behandelten Grundlagen aufbaut.</p><p>Die Analyse konzentriert sich auf fortgeschrittene Aspekte des automatischen Front-End-Testings. Insbesondere wird die Erstellung einer GitLab Pipeline für automatische Tests auf bewährten Prinzipien von Keycloak und Spring Boot basierend erkundet. Das Ziel ist es, Ihnen Einblicke in die strategischen Schritte zu geben, um eine effiziente und zuverlässige Testumgebung zu schaffen, die sich nahtlos in Ihre Entwicklungsprozesse integrieren lässt.</p>						</div>
				</div>
				<div class="elementor-element elementor-element-8d73400 elementor-widget elementor-widget-theme-post-featured-image elementor-widget-image" data-id="8d73400" data-element_type="widget" data-widget_type="theme-post-featured-image.default">
				<div class="elementor-widget-container">
										<figure class="wp-caption">
										<img fetchpriority="high" decoding="async" width="2000" height="1200" src="https://www.inoteq.com/wp-content/uploads/2023/11/wp4.png" class="attachment-full size-full wp-image-2920" alt="" srcset="https://www.inoteq.com/wp-content/uploads/2023/11/wp4.png 2000w, https://www.inoteq.com/wp-content/uploads/2023/11/wp4-300x180.png 300w, https://www.inoteq.com/wp-content/uploads/2023/11/wp4-1024x614.png 1024w, https://www.inoteq.com/wp-content/uploads/2023/11/wp4-768x461.png 768w, https://www.inoteq.com/wp-content/uploads/2023/11/wp4-1536x922.png 1536w" sizes="(max-width: 2000px) 100vw, 2000px" />											<figcaption class="widget-image-caption wp-caption-text">KI generiertes Symbolbild: compelling, illustration, symbolizing automated pipeline testing, logo-style, clipboard with test results, pipeline</figcaption>
										</figure>
							</div>
				</div>
				<div class="elementor-element elementor-element-0abacf3 elementor-toc--minimized-on-tablet elementor-widget elementor-widget-table-of-contents" data-id="0abacf3" data-element_type="widget" data-settings="{&quot;exclude_headings_by_selector&quot;:&quot;.exclude-from-toc&quot;,&quot;headings_by_tags&quot;:[&quot;h2&quot;,&quot;h3&quot;,&quot;h4&quot;,&quot;h5&quot;,&quot;h6&quot;],&quot;marker_view&quot;:&quot;numbers&quot;,&quot;minimize_box&quot;:&quot;yes&quot;,&quot;minimized_on&quot;:&quot;tablet&quot;,&quot;hierarchical_view&quot;:&quot;yes&quot;,&quot;min_height&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]},&quot;min_height_tablet&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]},&quot;min_height_mobile&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]}}" data-widget_type="table-of-contents.default">
				<div class="elementor-widget-container">
					<div class="elementor-toc__header">
			<h4 class="elementor-toc__header-title">
				Table of Contents			</h4>
							<div class="elementor-toc__toggle-button elementor-toc__toggle-button--expand" role="button" tabindex="0" aria-controls="elementor-toc__0abacf3" aria-expanded="true" aria-label="Open table of contents"><i aria-hidden="true" class="fas fa-chevron-down"></i></div>
				<div class="elementor-toc__toggle-button elementor-toc__toggle-button--collapse" role="button" tabindex="0" aria-controls="elementor-toc__0abacf3" aria-expanded="true" aria-label="Close table of contents"><i aria-hidden="true" class="fas fa-chevron-up"></i></div>
					</div>
		<div id="elementor-toc__0abacf3" class="elementor-toc__body">
			<div class="elementor-toc__spinner-container">
				<i class="elementor-toc__spinner eicon-animation-spin eicon-loading" aria-hidden="true"></i>			</div>
		</div>
				</div>
				</div>
					</div>
		</div>
					</div>
		</section>
				<section class="elementor-section elementor-top-section elementor-element elementor-element-247900a elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="247900a" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-daa0597" data-id="daa0597" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
						<div class="elementor-element elementor-element-0d03c77 elementor-widget elementor-widget-spacer" data-id="0d03c77" data-element_type="widget" data-widget_type="spacer.default">
				<div class="elementor-widget-container">
					<div class="elementor-spacer">
			<div class="elementor-spacer-inner"></div>
		</div>
				</div>
				</div>
				<div class="elementor-element elementor-element-a3ebc38 elementor-widget elementor-widget-heading" data-id="a3ebc38" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h2 class="elementor-heading-title elementor-size-default">Keycloak für die Testumgebung</h2>		</div>
				</div>
				<div class="elementor-element elementor-element-0268f17 elementor-widget elementor-widget-text-editor" data-id="0268f17" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p>Zum Testen der Spring Boot Anwendung ist eine Keycloak Konfiguration für die Testumgebung erforderlich. Später wird mithilfe von Testcontainers eine Keycloak-Instanz mit der gegebenen Konfiguration geladen, um die Authentifizierung in den Tests zu übernehmen. Zu diesem Zweck wird eine Import-Datei im JSON-Format benötigt. Ein einfacher Export der Konfiguration ist über die Keycloak-Benutzeroberfläche zwar möglich, allerdings werden aus Sicherheitsgründen die angelegten Benutzer nicht mit exportiert. Die Testumgebung wäre dann zwar in der Lage, sich mit dem OAuth 2.0 Server zu verbinden und normal zu starten, es stehen anschließend jedoch keine Benutzer für die Authentifizierung zur Verfügung.</p>						</div>
				</div>
				<div class="elementor-element elementor-element-3dd3b3e elementor-widget elementor-widget-heading" data-id="3dd3b3e" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Realm-Export mit Benutzern</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-fc7fb45 elementor-widget elementor-widget-text-editor" data-id="fc7fb45" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p>Im Folgenden wird erklärt, wie man einen bereits vollständig konfigurierten Realm mit allen Benutzern exportiert, während der Keycloak-Server in einer Docker-Umgebung läuft. Im <a href="https://github.com/inoteq/spring-boot-keycloak-oauth2" target="_blank" rel="noopener">Repository</a> zum letzten Beitrag findet sich bereits eine aus dem vorkonfigurierten Demo-Realm exportierte <strong><i>realm.json</i></strong> Datei, die hier wieder verwendet wird.</p><p>Folgender Befehl wird im Terminal des Systems ausgeführt:</p><p><code class="language-bash inline">docker exec -it keycloak-demo bash</code></p><p>Darüber gelangen wir in das Terminal innerhalb des Containers, auf dem der Keycloak-Server läuft. Dabei wird hier der Container <em><strong>keycloak-demo</strong></em> gewählt. Innerhalb des Containers wird dann folgender Befehl ausgeführt:</p><p><code class="language-bash inline">./opt/keycloak/bin/kc.sh export --dir /tmp/export --realm demo-realm --users realm_file</code></p><p>Damit exportieren wir die Realm-Konfiguration mit allen Benutzerdaten als <strong><i>demo-realm-realm.json</i></strong> in das Verzeichnis <em><strong>/tmp/export</strong></em> innerhalb des Containers. Mit dem Befehl <code class="language-bash inline">exit</code> gelangt man wieder in das Terminal des eigenen Systems zurück. Zuletzt wird die exportierte Datei mit dem folgendem Befehl aus dem Container herauskopiert.</p><p><code class="language-bash inline">docker cp keycloak-demo:/tmp/export/demo-realm-realm.json ~/Desktop/realm.json</code></p><p>In diesem Beispiel wird es einfach auf den Desktop kopiert und gleichzeitig in <strong><i>realm.json</i></strong> umbenannt, später wird diese aber im Spring Boot-Projekt gebraucht.</p>						</div>
				</div>
				<div class="elementor-element elementor-element-b50f9a4 elementor-widget elementor-widget-alert" data-id="b50f9a4" data-element_type="widget" data-widget_type="alert.default">
				<div class="elementor-widget-container">
					<div class="elementor-alert elementor-alert-warning" role="alert">
			<span class="elementor-alert-title">Sensible Daten</span>
							<span class="elementor-alert-description">Die exportierte Realm-Konfiguration kann sensible Daten wie Passwort-Hashes oder E-Mails enthalten. Aus diesem Grund sollte diese Variante ausschließlich für Entwicklungszwecke oder mit Testsysteme mit Testdaten verwendet werden.</span>
								</div>
				</div>
				</div>
					</div>
		</div>
					</div>
		</section>
				<section class="elementor-section elementor-top-section elementor-element elementor-element-1ac0dc1 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="1ac0dc1" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-67a783c" data-id="67a783c" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
						<div class="elementor-element elementor-element-8dc0c6a elementor-widget elementor-widget-spacer" data-id="8dc0c6a" data-element_type="widget" data-widget_type="spacer.default">
				<div class="elementor-widget-container">
					<div class="elementor-spacer">
			<div class="elementor-spacer-inner"></div>
		</div>
				</div>
				</div>
				<div class="elementor-element elementor-element-8c0be78 elementor-widget elementor-widget-heading" data-id="8c0be78" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h2 class="elementor-heading-title elementor-size-default">Playwright Frontend Tests</h2>		</div>
				</div>
				<div class="elementor-element elementor-element-d36b81d elementor-widget elementor-widget-text-editor" data-id="d36b81d" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p>Um die Benutzeroberfläche der Anwendung zu testen, wird das Testframework <a href="https://playwright.dev/java/" target="_blank" rel="noopener">Playwright</a> verwendet.</p><p>Im Vergleich zu dem bekannteren Selenium bietet Playwright einige Vorteile, wie zum Beispiel eine bessere Performance und weniger erforderlichen Boilerplate-Code beim Schreiben der Tests. Playwright bietet eine verbesserte Browser-Automation und unterstützt mehrere Browser. Außerdem gibt es eine native Unterstützung für den Headless-Modus, bessere Möglichkeiten zur Manipulation von Webseiten und eine einfache Verwendung mit Pipelines für automatische Tests.</p>						</div>
				</div>
				<div class="elementor-element elementor-element-60e90f4 elementor-widget elementor-widget-heading" data-id="60e90f4" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Konfiguration</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-999edee elementor-widget elementor-widget-text-editor" data-id="999edee" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p>Für die Verwendung von Playwright für Tests muss die <b><i>build.gradle</i></b> angepasst werden. Zunächst sollte sichergestellt werden, dass es eine Test-Task für Gradle existiert und die benötigten Abhängigkeiten für <a href="https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test" target="_blank" rel="noopener">Spring Boot Starter Tests</a> als auch <a href="https://mvnrepository.com/artifact/com.microsoft.playwright/playwright" target="_blank" rel="noopener">Playwright</a> für die Testimplementierung angegeben sind, als auch die Abhängigkeiten für die Verwendung von OAuth 2.0 selbst.</p>						</div>
				</div>
				<div class="elementor-element elementor-element-ae00014 elementor-tabs-view-horizontal elementor-widget elementor-widget-tabs" data-id="ae00014" data-element_type="widget" data-widget_type="tabs.default">
				<div class="elementor-widget-container">
					<div class="elementor-tabs">
			<div class="elementor-tabs-wrapper" role="tablist" >
									<div id="elementor-tab-title-1821" class="elementor-tab-title elementor-tab-desktop-title" aria-selected="true" data-tab="1" role="tab" tabindex="0" aria-controls="elementor-tab-content-1821" aria-expanded="false">build.gradle</div>
							</div>
			<div class="elementor-tabs-content-wrapper" role="tablist" aria-orientation="vertical">
									<div class="elementor-tab-title elementor-tab-mobile-title" aria-selected="true" data-tab="1" role="tab" tabindex="0" aria-controls="elementor-tab-content-1821" aria-expanded="false">build.gradle</div>
					<div id="elementor-tab-content-1821" class="elementor-tab-content elementor-clearfix" data-tab="1" role="tabpanel" aria-labelledby="elementor-tab-title-1821" tabindex="0" hidden="false"><pre><code class="language-groovy">dependencies {
    ...
    testImplementation 'org.springframework.boot:spring-boot-starter-test:3.2.2'
    testImplementation 'com.microsoft.playwright:playwright:1.41.1'
}

...

tasks.named('test') {
    useJUnitPlatform()
}
</code></pre></div>
							</div>
		</div>
				</div>
				</div>
				<div class="elementor-element elementor-element-971daba elementor-widget elementor-widget-text-editor" data-id="971daba" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p>Eine Testklasse wird erstellt und für die Spring Boot Anwendung sowie für Playwright konfiguriert. Zunächst wird Playwright so konfiguriert, dass der automatische Testprozess beobachtet werden kann, um mögliche Fehler zu sichten. Später sollte diese Option wieder ausgestellt werden, da die Tests so wesentlich schneller laufen.</p>						</div>
				</div>
				<div class="elementor-element elementor-element-948a594 elementor-tabs-view-horizontal elementor-widget elementor-widget-tabs" data-id="948a594" data-element_type="widget" data-widget_type="tabs.default">
				<div class="elementor-widget-container">
					<div class="elementor-tabs">
			<div class="elementor-tabs-wrapper" role="tablist" >
									<div id="elementor-tab-title-1551" class="elementor-tab-title elementor-tab-desktop-title" aria-selected="true" data-tab="1" role="tab" tabindex="0" aria-controls="elementor-tab-content-1551" aria-expanded="false">src/test/kotlin/DemoTest.kt</div>
							</div>
			<div class="elementor-tabs-content-wrapper" role="tablist" aria-orientation="vertical">
									<div class="elementor-tab-title elementor-tab-mobile-title" aria-selected="true" data-tab="1" role="tab" tabindex="0" aria-controls="elementor-tab-content-1551" aria-expanded="false">src/test/kotlin/DemoTest.kt</div>
					<div id="elementor-tab-content-1551" class="elementor-tab-content elementor-clearfix" data-tab="1" role="tabpanel" aria-labelledby="elementor-tab-title-1551" tabindex="0" hidden="false"><pre><code class="language-kotlin">import ...

@SpringBootTest(
    classes = [DemoApplication::class],
    webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT
)
class DemoTest {
    companion object {
        // Playwright setup
        private var playwright: Playwright? = null
        private var browser: Browser? = null
        private var context: BrowserContext? = null
        private var page: Page? = null

        @JvmStatic
        @BeforeAll
        fun launchBrowser() {
            playwright = Playwright.create()
            
            browser = playwright?.chromium()?.launch(
                // Run playwright in headed mode with slow motion to see what's happening
                BrowserType.LaunchOptions().setHeadless(false).setSlowMo(100.0)
            )
        }

        @JvmStatic
        @AfterAll
        fun closeBrowser() {
            playwright?.close()
        }
    }

    @BeforeEach
    fun createContextAndPage() {
        context = browser?.newContext()
        page = context?.newPage()
    }

    @AfterEach
    fun closeContext() {
        context?.close()
    }
}
</code></pre></div>
							</div>
		</div>
				</div>
				</div>
				<div class="elementor-element elementor-element-acca8d1 elementor-widget elementor-widget-text-editor" data-id="acca8d1" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p>Damit kann Playwright nun für Tests verwendet werden.</p>						</div>
				</div>
				<div class="elementor-element elementor-element-fe028e7 elementor-widget elementor-widget-heading" data-id="fe028e7" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Beispieltests</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-c839f98 elementor-widget elementor-widget-text-editor" data-id="c839f98" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							Wir halten uns bei diesem Beispiel an das Demo-Projekt aus dem letzten Beitrag und wollen die beiden Endpunkte <code class="language-plain inline">/public</code> und <code class="language-plain inline">/private</code> testen. Der <code class="language-plain inline">/public</code> Endpunkt ist immer aufrufbar, aber der <code class="language-plain inline">/private</code> Endpunkt ist erst aufrufbar, nachdem sich der Benutzer erfolgreich authentifiziert hat. Dafür müssen wir Playwright mitteilen, dass er nach dem Aufruf von <code class="language-plain inline">/private</code> auf eine Weiterleitung zum OAuth 2.0 Server warten soll, dort dann Benutzername und Passwort eingibt, bestätigt und zu guter Letzt wieder auf dem erwarteten Endpunkt <code class="language-plain inline">/private</code> landet.						</div>
				</div>
				<div class="elementor-element elementor-element-7391122 elementor-tabs-view-horizontal elementor-widget elementor-widget-tabs" data-id="7391122" data-element_type="widget" data-widget_type="tabs.default">
				<div class="elementor-widget-container">
					<div class="elementor-tabs">
			<div class="elementor-tabs-wrapper" role="tablist" >
									<div id="elementor-tab-title-1211" class="elementor-tab-title elementor-tab-desktop-title" aria-selected="true" data-tab="1" role="tab" tabindex="0" aria-controls="elementor-tab-content-1211" aria-expanded="false">src/test/kotlin/DemoTest.kt</div>
							</div>
			<div class="elementor-tabs-content-wrapper" role="tablist" aria-orientation="vertical">
									<div class="elementor-tab-title elementor-tab-mobile-title" aria-selected="true" data-tab="1" role="tab" tabindex="0" aria-controls="elementor-tab-content-1211" aria-expanded="false">src/test/kotlin/DemoTest.kt</div>
					<div id="elementor-tab-content-1211" class="elementor-tab-content elementor-clearfix" data-tab="1" role="tabpanel" aria-labelledby="elementor-tab-title-1211" tabindex="0" hidden="false"><pre><code class="language-kotlin">@Test
fun publicEndpointTest() {
    page?.navigate("http://localhost:8080/public")
    assertThat(page?.locator("body")).hasText("Hello from a public endpoint!")
}

@Test
fun privateEndpointTest() {
    // Unable to access private endpoint without logging in and redirects to login page
    page?.navigate("http://localhost:8080/private")

    // Login with example user 'John Doe' by filling the login form and submitting it
    page?.fill("#username", "john.doe")
    page?.fill("#password", "password")
    page?.locator("input[type=submit]")?.click()
    // Wait for redirect to previously requested private endpoint
    page?.waitForURL("http://localhost:8080/private?continue")

    // Check for expected content on private endpoint
    assertThat(page?.locator("body")).hasText("Hello from a private endpoint!")
}</code></pre></div>
							</div>
		</div>
				</div>
				</div>
				<div class="elementor-element elementor-element-945f459 elementor-widget elementor-widget-text-editor" data-id="945f459" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p>Um sicherzustellen, dass unsere Tests korrekt funktionieren, lassen wir den OAuth 2.0 Keycloak-Container im Hintergrund laufen und führen die Tests aus. Dabei wird ein neuer Chromium-Browser geöffnet, den Playwright manipuliert. Für einen kurzen Moment ist auch zu sehen, wie Playwright sich am OAuth 2.0 Server anmeldet.</p><p>Um die Auswirkungen von fehlendem OAuth 2.0 Zugriff zu zeigen, wird der Keycloak-Container gestoppt und die Tests erneut ausgeführt. Dadurch sollten die Tests fehlschlagen. Im nächsten Schritt wird der Zugriff wieder ermöglicht, indem bei den Tests ein Keycloak-Container erstellt und gestartet wird.</p>						</div>
				</div>
					</div>
		</div>
					</div>
		</section>
				<section class="elementor-section elementor-top-section elementor-element elementor-element-1014992 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="1014992" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-7af1228" data-id="7af1228" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
						<div class="elementor-element elementor-element-c29614c elementor-widget elementor-widget-spacer" data-id="c29614c" data-element_type="widget" data-widget_type="spacer.default">
				<div class="elementor-widget-container">
					<div class="elementor-spacer">
			<div class="elementor-spacer-inner"></div>
		</div>
				</div>
				</div>
				<div class="elementor-element elementor-element-8ab9cf3 elementor-widget elementor-widget-heading" data-id="8ab9cf3" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h2 class="elementor-heading-title elementor-size-default">Keycloak Testcontainer</h2>		</div>
				</div>
				<div class="elementor-element elementor-element-31071f5 elementor-widget elementor-widget-text-editor" data-id="31071f5" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p>Zunächst benötigen wir die richtige Abhängigkeit, um einen Keycloak-Container für Tests zu starten. Dafür gibt es den <a href="https://github.com/dasniko/testcontainers-keycloak" target="_blank" rel="noopener">Keycloak Testcontainer</a>, eine spezielle Variante des Testcontainers, der für Keycloak angepasst wurde. Dazu wird die folgende Zeile in <b><i>build.gradle</i></b> eingefügt:</p><p><code class="language-gradle inline">testImplementation 'com.github.dasniko:testcontainers-keycloak:3.2.0'</code></p><p>Wichtig ist, dass Docker auf Ihrem System läuft.</p><p>Die Testklasse wird so angepasst, dass unser gewünschter OAuth 2.0 Service wieder erreichbar ist, ohne dass wir den Container dafür erstellen und starten müssen. Dazu wird der Code wie folgt ergänzt:</p>						</div>
				</div>
				<div class="elementor-element elementor-element-99a6d9a elementor-tabs-view-horizontal elementor-widget elementor-widget-tabs" data-id="99a6d9a" data-element_type="widget" data-widget_type="tabs.default">
				<div class="elementor-widget-container">
					<div class="elementor-tabs">
			<div class="elementor-tabs-wrapper" role="tablist" >
									<div id="elementor-tab-title-1611" class="elementor-tab-title elementor-tab-desktop-title" aria-selected="true" data-tab="1" role="tab" tabindex="0" aria-controls="elementor-tab-content-1611" aria-expanded="false">src/test/kotlin/DemoTest.kt</div>
							</div>
			<div class="elementor-tabs-content-wrapper" role="tablist" aria-orientation="vertical">
									<div class="elementor-tab-title elementor-tab-mobile-title" aria-selected="true" data-tab="1" role="tab" tabindex="0" aria-controls="elementor-tab-content-1611" aria-expanded="false">src/test/kotlin/DemoTest.kt</div>
					<div id="elementor-tab-content-1611" class="elementor-tab-content elementor-clearfix" data-tab="1" role="tabpanel" aria-labelledby="elementor-tab-title-1611" tabindex="0" hidden="false"><pre><code class="language-kotlin">companion object {
    // Start a Keycloak instance with an import file for the demo realm
    @JvmStatic
    private val keycloakContainer = KeycloakContainer().apply {
        withRealmImportFile("realm.json")
        portBindings = listOf("8081:8080")
        start()
    }

    // Register the Keycloak issuer URL as a dynamic property for the Spring Boot application
    @JvmStatic
    @DynamicPropertySource
    private fun registerResourceServerIssuerProperty(registry: DynamicPropertyRegistry) {
        registry.add("spring.security.oauth2.client.provider.demo-provider.issuer-uri") {
            "${keycloakContainer.authServerUrl}/realms/demo-realm"
        }
    }

    ...

    @JvmStatic
    @BeforeAll
    fun launchBrowser() {
        playwright = Playwright.create()
        browser = playwright?.chromium()?.launch() // Use headless mode
    }

   ...
}</code></pre></div>
							</div>
		</div>
				</div>
				</div>
				<div class="elementor-element elementor-element-b266315 elementor-widget elementor-widget-text-editor" data-id="b266315" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p>Es wird ein Keycloak-Container definiert, der die zuvor exportierte <b><i>realm.json</i></b> importiert. Diese Datei muss sich dazu im Verzeichnis <b><i>src/test/resources </i></b>befinden. Zudem wird vor dem Start die Portbindung definiert.</p><p>Testcontainer werden immer mit einem zufälligen Port gestartet. Die Anwendung benötigt jedoch diesen Port, um den OAuth 2.0 Dienst richtig zu konfigurieren. Für diesen Zweck wird im Code die dynamische Eigenschaft für den OAuth 2.0-Dienst angepasst, indem wir die URL des Testcontainers einschließlich des Ports vor dem verwendeten Realm angeben.</p><p>Die Tests sind jetzt unabhängig von der lokalen Umgebung ausführbar. Während des Testprozesses wird ein neuer Container in Docker erstellt und nach Abschluss der Tests wieder gelöscht.</p><p>Es empfiehlt sich, Playwright wieder headless zu benutzen, da dadurch eine wesentlich bessere Performance erreicht wird. Das ist vor allem im nächsten Schritt wichtig.</p>						</div>
				</div>
					</div>
		</div>
					</div>
		</section>
				<section class="elementor-section elementor-top-section elementor-element elementor-element-2802df5 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="2802df5" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-8cf8bd3" data-id="8cf8bd3" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
						<div class="elementor-element elementor-element-9f0c98e elementor-widget elementor-widget-spacer" data-id="9f0c98e" data-element_type="widget" data-widget_type="spacer.default">
				<div class="elementor-widget-container">
					<div class="elementor-spacer">
			<div class="elementor-spacer-inner"></div>
		</div>
				</div>
				</div>
				<div class="elementor-element elementor-element-b9d6ec9 elementor-widget elementor-widget-heading" data-id="b9d6ec9" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h2 class="elementor-heading-title elementor-size-default">GitLab Pipeline</h2>		</div>
				</div>
				<div class="elementor-element elementor-element-49b2e44 elementor-widget elementor-widget-text-editor" data-id="49b2e44" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p>Das Ziel war bisher, die Tests zu automatisieren und für eine GitLab-Pipeline ausführbar zu machen. Dafür ist es wichtig, dass der GitLab-Runner Docker-Container ausführen kann.</p><p>Playwright bietet ein Image an, das für die Zwecke dieses Projekts geeignet ist. Auf der <a href="https://playwright.dev/java/docs/ci#gitlab-ci" target="_blank" rel="noopener">Playwright-Website</a> gibt es genauere Details zur kontinuierlichen Integration, einschließlich GitHub und anderen Plattformen. Auch für Testcontainers werden <a href="https://java.testcontainers.org/supported_docker_environment/continuous_integration/gitlab_ci/" target="_blank" rel="noopener">ausführliche Beispiele</a> gezeict, wie man z.B. eine GitLab Pipeline mit Testcontainers konfiguriert. In unserem Fall orientieren wir uns an der Variante, die Docker-in-Docker verwendet.</p><p>Sobald die benötigten Anpassungen vorgenommen wurden, lassen sich mittels <code class="language-bash inline">./gradlew test</code> die Tests ausführen.</p>						</div>
				</div>
				<div class="elementor-element elementor-element-9069fba elementor-tabs-view-horizontal elementor-widget elementor-widget-tabs" data-id="9069fba" data-element_type="widget" data-widget_type="tabs.default">
				<div class="elementor-widget-container">
					<div class="elementor-tabs">
			<div class="elementor-tabs-wrapper" role="tablist" >
									<div id="elementor-tab-title-1511" class="elementor-tab-title elementor-tab-desktop-title" aria-selected="true" data-tab="1" role="tab" tabindex="0" aria-controls="elementor-tab-content-1511" aria-expanded="false">gitlab-ci.yml</div>
							</div>
			<div class="elementor-tabs-content-wrapper" role="tablist" aria-orientation="vertical">
									<div class="elementor-tab-title elementor-tab-mobile-title" aria-selected="true" data-tab="1" role="tab" tabindex="0" aria-controls="elementor-tab-content-1511" aria-expanded="false">gitlab-ci.yml</div>
					<div id="elementor-tab-content-1511" class="elementor-tab-content elementor-clearfix" data-tab="1" role="tabpanel" aria-labelledby="elementor-tab-title-1511" tabindex="0" hidden="false"><pre><code class="language-yml">image: mcr.microsoft.com/playwright/java:v1.41.0-jammy

services:
  - name: docker:dind
    command: [ "--tls=false" ]

variables:
  DOCKER_HOST: "tcp://docker:2375"
  DOCKER_TLS_CERTDIR: ""
  DOCKER_DRIVER: overlay2

before_script:
  - GRADLE_USER_HOME="$(pwd)/.gradle"
  - export GRADLE_USER_HOME

stages:
  - test

tests:
  stage: test
  script:
    - ./gradlew test
</code></pre></div>
							</div>
		</div>
				</div>
				</div>
				<div class="elementor-element elementor-element-b9bf388 elementor-widget elementor-widget-text-editor" data-id="b9bf388" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p>Wie man nun sehen kann, läuft die Pipeline erfolgreich durch. Allerdings ist es erwähnenswert, dass sie einige Zeit dafür benötigt. Mit einer größeren Anzahl an Tests steigt auch die Zeit, die die Pipeline benötigt, um diese auszuführen. Dabei sei gesagt, dass die meiste Zeit für die Vorbereitung der Pipeline benötigt wird, einschließlich der größeren Abhängigkeiten wie dem Playwright Browser.</p>						</div>
				</div>
				<div class="elementor-element elementor-element-8b042b4 elementor-tabs-view-horizontal elementor-widget elementor-widget-tabs" data-id="8b042b4" data-element_type="widget" data-widget_type="tabs.default">
				<div class="elementor-widget-container">
					<div class="elementor-tabs">
			<div class="elementor-tabs-wrapper" role="tablist" >
									<div id="elementor-tab-title-1451" class="elementor-tab-title elementor-tab-desktop-title" aria-selected="true" data-tab="1" role="tab" tabindex="0" aria-controls="elementor-tab-content-1451" aria-expanded="false">GitLab Runner</div>
							</div>
			<div class="elementor-tabs-content-wrapper" role="tablist" aria-orientation="vertical">
									<div class="elementor-tab-title elementor-tab-mobile-title" aria-selected="true" data-tab="1" role="tab" tabindex="0" aria-controls="elementor-tab-content-1451" aria-expanded="false">GitLab Runner</div>
					<div id="elementor-tab-content-1451" class="elementor-tab-content elementor-clearfix" data-tab="1" role="tabpanel" aria-labelledby="elementor-tab-title-1451" tabindex="0" hidden="false"><pre><code class="language-log">Running with gitlab-runner 14.7.0 (98daeee0)
  on gitlab-runner-01 y7AkGoZD
Preparing the "docker" executor 00:34
...
Preparing environment 00:00
...
Getting source from Git repository 00:02
...
Executing "step_script" stage of the job script 03:52
Using docker image sha256:df9599e540016f99fbcd1d862224ae9d1cf30df17fa5d367c969ee37cc060afb for mcr.microsoft.com/playwright/java:v1.41.0-jammy with digest mcr.microsoft.com/playwright/java@sha256:390fdf6801be59dd7bc6a3fad6344ae9d795b6585d102af293b57d61076d0824 ...
$ GRADLE_USER_HOME="$(pwd)/.gradle"
$ export GRADLE_USER_HOME
$ ./gradlew test
Downloading https://services.gradle.org/distributions/gradle-8.5-bin.zip
............10%.............20%............30%.............40%.............50%............60%.............70%.............80%............90%.............100%
Welcome to Gradle 8.5!
Here are the highlights of this release:
 - Support for running on Java 21
 - Faster first use with Kotlin DSL
 - Improved error and warning messages
For more details see https://docs.gradle.org/8.5/release-notes.html
Starting a Gradle Daemon (subsequent builds will be faster)
&gt; Task :checkKotlinGradlePluginConfigurationErrors
&gt; Task :processResources
&gt; Task :processTestResources
&gt; Task :compileKotlin
&gt; Task :compileJava NO-SOURCE
&gt; Task :classes
&gt; Task :compileTestKotlin
&gt; Task :compileTestJava NO-SOURCE
&gt; Task :testClasses
&gt; Task :test
OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
For more on this, please refer to https://docs.gradle.org/8.5/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.
BUILD SUCCESSFUL in 3m 50s
6 actionable tasks: 6 executed
Cleaning up project directory and file based variables 00:01
Job succeeded</code></pre></div>
							</div>
		</div>
				</div>
				</div>
					</div>
		</div>
					</div>
		</section>
				<section class="elementor-section elementor-top-section elementor-element elementor-element-01f7774 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="01f7774" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-c412524" data-id="c412524" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
						<div class="elementor-element elementor-element-9689723 elementor-widget elementor-widget-spacer" data-id="9689723" data-element_type="widget" data-widget_type="spacer.default">
				<div class="elementor-widget-container">
					<div class="elementor-spacer">
			<div class="elementor-spacer-inner"></div>
		</div>
				</div>
				</div>
				<div class="elementor-element elementor-element-7fdc40d elementor-widget elementor-widget-heading" data-id="7fdc40d" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h2 class="elementor-heading-title elementor-size-default">Fazit</h2>		</div>
				</div>
				<div class="elementor-element elementor-element-d14bd30 elementor-widget elementor-widget-text-editor" data-id="d14bd30" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p>Die vorgestellten Tests zeichnen sich durch ihre hohe Realitätsnähe aus, da sie auf einer dynamischen Keycloak-Testumgebung basieren. Dies vereinfacht die Entwicklung und trägt zur Sicherstellung einer zuverlässigen Authentifizierung bei. Jedoch ist es wichtig zu beachten, dass die GitLab Pipeline, aufgrund ihrer umfassenden Abhängigkeiten wie dem Playwright Browser, eine längere Ausführungszeit aufweisen kann. Trotz dieser potenziellen Einschränkung bieten die realitätsnahen Tests einen unschätzbaren Wert für die Entwicklung von sicheren und zuverlässigen OAuth 2.0 Spring Boot-Anwendungen.</p>
<p>Für weitere Details steht das <a href="https://github.com/inoteq/spring-boot-keycloak-oauth2-testing">GitHub Repository</a> zur Verfügung, das alle im Artikel beschriebenen Schritte und Konfigurationen enthält.</p>						</div>
				</div>
					</div>
		</div>
					</div>
		</section>
				<section class="elementor-section elementor-top-section elementor-element elementor-element-44c973b elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="44c973b" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-5b14c43" data-id="5b14c43" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
						<div class="elementor-element elementor-element-9d09d69 elementor-widget elementor-widget-spacer" data-id="9d09d69" data-element_type="widget" data-widget_type="spacer.default">
				<div class="elementor-widget-container">
					<div class="elementor-spacer">
			<div class="elementor-spacer-inner"></div>
		</div>
				</div>
				</div>
				<div class="elementor-element elementor-element-354e095 elementor-widget elementor-widget-heading" data-id="354e095" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h2 class="elementor-heading-title elementor-size-default">Referenzierte Artikel</h2>		</div>
				</div>
				<div class="elementor-element elementor-element-98051f8 elementor-grid-1 elementor-grid-tablet-1 elementor-posts--thumbnail-left elementor-hidden-tablet elementor-hidden-mobile elementor-grid-mobile-1 elementor-widget elementor-widget-posts" data-id="98051f8" data-element_type="widget" data-settings="{&quot;classic_columns&quot;:&quot;1&quot;,&quot;classic_columns_tablet&quot;:&quot;1&quot;,&quot;classic_columns_mobile&quot;:&quot;1&quot;,&quot;classic_row_gap&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:35,&quot;sizes&quot;:[]},&quot;classic_row_gap_tablet&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]},&quot;classic_row_gap_mobile&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]}}" data-widget_type="posts.classic">
				<div class="elementor-widget-container">
					<div class="elementor-posts-container elementor-posts elementor-posts--skin-classic elementor-grid">
				<article class="elementor-post elementor-grid-item post-1744 post type-post status-publish format-standard has-post-thumbnail hentry category-blog tag-keycloak tag-oauth-2-0 tag-spring">
				<a class="elementor-post__thumbnail__link" href="https://www.inoteq.com/2023/11/30/oauth2-keycloak-locally/" tabindex="-1" >
			<div class="elementor-post__thumbnail"><img decoding="async" width="2000" height="1200" src="https://www.inoteq.com/wp-content/uploads/2023/11/wp1.png" class="attachment-full size-full wp-image-2922" alt="" srcset="https://www.inoteq.com/wp-content/uploads/2023/11/wp1.png 2000w, https://www.inoteq.com/wp-content/uploads/2023/11/wp1-300x180.png 300w, https://www.inoteq.com/wp-content/uploads/2023/11/wp1-1024x614.png 1024w, https://www.inoteq.com/wp-content/uploads/2023/11/wp1-768x461.png 768w, https://www.inoteq.com/wp-content/uploads/2023/11/wp1-1536x922.png 1536w" sizes="(max-width: 2000px) 100vw, 2000px" /></div>
		</a>
				<div class="elementor-post__text">
				<p class="elementor-post__title">
			<a href="https://www.inoteq.com/2023/11/30/oauth2-keycloak-locally/" >
				Integration von OAuth 2.0 in Spring Boot mit Keycloak			</a>
		</p>
				<div class="elementor-post__meta-data">
					<span class="elementor-post-author">
			Alexander Kusmin		</span>
				<span class="elementor-post-date">
			30. November 2023		</span>
				</div>
				<div class="elementor-post__excerpt">
			<p>Dieser Leitfaden beschreibt die Integration von OAuth 2.0 in eine Spring Boot Anwendung mit Keycloak. Nach einer kurzen Einführung in die Spring Boot Plattform liegt der Schwerpunkt auf der genauen Konfiguration von Keycloak als vertrauenswürdigen OAuth 2.0 Server und der Absicherung bestimmter Endpunkte in der Anwendung mit Anmeldedaten. Der Beitrag ist dabei so strukturiert, dass Entwickler Schritt für Schritt eine sichere Authentifizierung in einer Spring Boot-Anwendung implementieren können. Inhaltsverzeichnis Spring</p>
		</div>
		
		<a class="elementor-post__read-more" href="https://www.inoteq.com/2023/11/30/oauth2-keycloak-locally/" aria-label="Read more about Integration von OAuth 2.0 in Spring Boot mit Keycloak" tabindex="-1" >
			Weiterlesen »		</a>

				</div>
				</article>
				</div>
		
				</div>
				</div>
				<div class="elementor-element elementor-element-1b24a2c elementor-grid-1 elementor-grid-tablet-1 elementor-posts--thumbnail-left elementor-hidden-desktop elementor-hidden-mobile elementor-grid-mobile-1 elementor-widget elementor-widget-posts" data-id="1b24a2c" data-element_type="widget" data-settings="{&quot;classic_columns&quot;:&quot;1&quot;,&quot;classic_columns_tablet&quot;:&quot;1&quot;,&quot;classic_columns_mobile&quot;:&quot;1&quot;,&quot;classic_row_gap&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:35,&quot;sizes&quot;:[]},&quot;classic_row_gap_tablet&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]},&quot;classic_row_gap_mobile&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]}}" data-widget_type="posts.classic">
				<div class="elementor-widget-container">
					<div class="elementor-posts-container elementor-posts elementor-posts--skin-classic elementor-grid">
				<article class="elementor-post elementor-grid-item post-1744 post type-post status-publish format-standard has-post-thumbnail hentry category-blog tag-keycloak tag-oauth-2-0 tag-spring">
				<a class="elementor-post__thumbnail__link" href="https://www.inoteq.com/2023/11/30/oauth2-keycloak-locally/" tabindex="-1" >
			<div class="elementor-post__thumbnail"><img decoding="async" width="2000" height="1200" src="https://www.inoteq.com/wp-content/uploads/2023/11/wp1.png" class="attachment-full size-full wp-image-2922" alt="" srcset="https://www.inoteq.com/wp-content/uploads/2023/11/wp1.png 2000w, https://www.inoteq.com/wp-content/uploads/2023/11/wp1-300x180.png 300w, https://www.inoteq.com/wp-content/uploads/2023/11/wp1-1024x614.png 1024w, https://www.inoteq.com/wp-content/uploads/2023/11/wp1-768x461.png 768w, https://www.inoteq.com/wp-content/uploads/2023/11/wp1-1536x922.png 1536w" sizes="(max-width: 2000px) 100vw, 2000px" /></div>
		</a>
				<div class="elementor-post__text">
				<p class="elementor-post__title">
			<a href="https://www.inoteq.com/2023/11/30/oauth2-keycloak-locally/" >
				Integration von OAuth 2.0 in Spring Boot mit Keycloak			</a>
		</p>
				<div class="elementor-post__meta-data">
					<span class="elementor-post-author">
			Alexander Kusmin		</span>
				<span class="elementor-post-date">
			30. November 2023		</span>
				</div>
				<div class="elementor-post__excerpt">
			<p>Dieser Leitfaden beschreibt die Integration von OAuth 2.0 in eine Spring Boot Anwendung mit Keycloak. Nach einer kurzen Einführung in die Spring Boot Plattform liegt der Schwerpunkt auf der genauen Konfiguration von Keycloak als vertrauenswürdigen</p>
		</div>
		
		<a class="elementor-post__read-more" href="https://www.inoteq.com/2023/11/30/oauth2-keycloak-locally/" aria-label="Read more about Integration von OAuth 2.0 in Spring Boot mit Keycloak" tabindex="-1" >
			Weiterlesen »		</a>

				</div>
				</article>
				</div>
		
				</div>
				</div>
				<div class="elementor-element elementor-element-decdf13 elementor-grid-1 elementor-grid-tablet-1 elementor-hidden-desktop elementor-hidden-tablet elementor-grid-mobile-1 elementor-posts--thumbnail-top elementor-widget elementor-widget-posts" data-id="decdf13" data-element_type="widget" data-settings="{&quot;classic_columns&quot;:&quot;1&quot;,&quot;classic_columns_tablet&quot;:&quot;1&quot;,&quot;classic_columns_mobile&quot;:&quot;1&quot;,&quot;classic_row_gap&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:35,&quot;sizes&quot;:[]},&quot;classic_row_gap_tablet&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]},&quot;classic_row_gap_mobile&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]}}" data-widget_type="posts.classic">
				<div class="elementor-widget-container">
					<div class="elementor-posts-container elementor-posts elementor-posts--skin-classic elementor-grid">
				<article class="elementor-post elementor-grid-item post-1744 post type-post status-publish format-standard has-post-thumbnail hentry category-blog tag-keycloak tag-oauth-2-0 tag-spring">
				<a class="elementor-post__thumbnail__link" href="https://www.inoteq.com/2023/11/30/oauth2-keycloak-locally/" tabindex="-1" >
			<div class="elementor-post__thumbnail"><img decoding="async" width="2000" height="1200" src="https://www.inoteq.com/wp-content/uploads/2023/11/wp1.png" class="attachment-full size-full wp-image-2922" alt="" srcset="https://www.inoteq.com/wp-content/uploads/2023/11/wp1.png 2000w, https://www.inoteq.com/wp-content/uploads/2023/11/wp1-300x180.png 300w, https://www.inoteq.com/wp-content/uploads/2023/11/wp1-1024x614.png 1024w, https://www.inoteq.com/wp-content/uploads/2023/11/wp1-768x461.png 768w, https://www.inoteq.com/wp-content/uploads/2023/11/wp1-1536x922.png 1536w" sizes="(max-width: 2000px) 100vw, 2000px" /></div>
		</a>
				<div class="elementor-post__text">
				<p class="elementor-post__title">
			<a href="https://www.inoteq.com/2023/11/30/oauth2-keycloak-locally/" >
				Integration von OAuth 2.0 in Spring Boot mit Keycloak			</a>
		</p>
				<div class="elementor-post__meta-data">
					<span class="elementor-post-author">
			Alexander Kusmin		</span>
				<span class="elementor-post-date">
			30. November 2023		</span>
				</div>
				<div class="elementor-post__excerpt">
			<p>Dieser Leitfaden beschreibt die Integration von OAuth 2.0 in eine Spring Boot Anwendung mit Keycloak. Nach einer kurzen Einführung in die Spring Boot Plattform liegt der Schwerpunkt auf der genauen Konfiguration von Keycloak als vertrauenswürdigen OAuth 2.0 Server und der Absicherung bestimmter Endpunkte in der Anwendung mit Anmeldedaten. Der Beitrag ist dabei so strukturiert, dass Entwickler Schritt für Schritt eine sichere Authentifizierung in einer Spring Boot-Anwendung implementieren können. Inhaltsverzeichnis Spring Boot: Setup und Grundkonfiguration Konfiguration Die Vorbereitung der Spring Boot</p>
		</div>
		
		<a class="elementor-post__read-more" href="https://www.inoteq.com/2023/11/30/oauth2-keycloak-locally/" aria-label="Read more about Integration von OAuth 2.0 in Spring Boot mit Keycloak" tabindex="-1" >
			Weiterlesen »		</a>

				</div>
				</article>
				</div>
		
				</div>
				</div>
					</div>
		</div>
					</div>
		</section>
				<section class="elementor-section elementor-top-section elementor-element elementor-element-7c4cd4d elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="7c4cd4d" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-f80ad6a" data-id="f80ad6a" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
						<div class="elementor-element elementor-element-e5f9e74 elementor-widget elementor-widget-spacer" data-id="e5f9e74" data-element_type="widget" data-widget_type="spacer.default">
				<div class="elementor-widget-container">
					<div class="elementor-spacer">
			<div class="elementor-spacer-inner"></div>
		</div>
				</div>
				</div>
					</div>
		</div>
					</div>
		</section>
				</div>
		<p>Der Beitrag <a href="https://www.inoteq.com/2024/02/08/automatisches-front-end-testing-einer-oauth-2-0-spring-boot-anwendungen/">Automatisches Front-End-Testing einer OAuth 2.0 Spring-Boot Anwendungen</a> erschien zuerst auf <a href="https://www.inoteq.com">INOTEQ GmbH</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.inoteq.com/2024/02/08/automatisches-front-end-testing-einer-oauth-2-0-spring-boot-anwendungen/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
