From a47ee1e6f55c26a3ed0f6d1d592ecf48ebafaa2b Mon Sep 17 00:00:00 2001
From: OZGCloud <ozgcloud@mgm-tp.com>
Date: Tue, 3 Dec 2024 11:08:11 +0100
Subject: [PATCH] OZG-7092 add tests for configuration; remove outdated tests

---
 .../token/saml/SamlConfiguration.java         |  13 +-
 .../token/TokenCheckApplicationTest.java      |  37 --
 .../saml/Saml2DecryptionServiceTest.java      | 293 -------------
 .../token/saml/Saml2ParseServiceTest.java     | 246 -----------
 .../saml/Saml2VerificationServiceTest.java    | 384 ------------------
 .../token/saml/SamlConfigurationTest.java     | 182 +++++++++
 .../token/saml/SamlTokenUtilsTest.java        | 319 ---------------
 .../saml/SamlTokenValidationServiceTest.java  |   3 +-
 8 files changed, 190 insertions(+), 1287 deletions(-)
 delete mode 100644 token-checker-server/src/test/java/de/ozgcloud/token/TokenCheckApplicationTest.java
 delete mode 100644 token-checker-server/src/test/java/de/ozgcloud/token/saml/Saml2DecryptionServiceTest.java
 delete mode 100644 token-checker-server/src/test/java/de/ozgcloud/token/saml/Saml2ParseServiceTest.java
 delete mode 100644 token-checker-server/src/test/java/de/ozgcloud/token/saml/Saml2VerificationServiceTest.java
 create mode 100644 token-checker-server/src/test/java/de/ozgcloud/token/saml/SamlConfigurationTest.java
 delete mode 100644 token-checker-server/src/test/java/de/ozgcloud/token/saml/SamlTokenUtilsTest.java

diff --git a/token-checker-server/src/main/java/de/ozgcloud/token/saml/SamlConfiguration.java b/token-checker-server/src/main/java/de/ozgcloud/token/saml/SamlConfiguration.java
index b0148c8..a60ef4a 100644
--- a/token-checker-server/src/main/java/de/ozgcloud/token/saml/SamlConfiguration.java
+++ b/token-checker-server/src/main/java/de/ozgcloud/token/saml/SamlConfiguration.java
@@ -28,18 +28,13 @@ public class SamlConfiguration {
 	private final SamlTrustEngineFactory samlTrustEngineFactory;
 	private final SamlDecrypterFactory samlDecrypterFactory;
 
-	@Bean
-	SAMLSignatureProfileValidator samlSignatureProfileValidator() {
-		return new SAMLSignatureProfileValidator();
-	}
-
 	@Bean
 	ResponseUnmarshaller responseUnmarshaller() {
 		return (ResponseUnmarshaller) XMLObjectProviderRegistrySupport.getUnmarshallerFactory().getUnmarshaller(Response.DEFAULT_ELEMENT_NAME);
 	}
 
 	@Bean
-	SamlServiceRegistry samSettingsRegistry(TokenValidationProperties tokenValidationProperties) {
+	SamlServiceRegistry samServiceRegistry(TokenValidationProperties tokenValidationProperties) {
 		var registryBuilder = SamlServiceRegistry.builder();
 		for (var tokenEntity : tokenValidationProperties.getEntities()) {
 			registryBuilder.samlService(tokenEntity.getIdpEntityId(), samlTokenService(tokenEntity));
@@ -51,10 +46,16 @@ public class SamlConfiguration {
 		return SamlTokenValidationService.builder()
 				.signatureTrustEngine(samlTrustEngineFactory.buildSamlTrustEngine(tokenValidationProperty))
 				.decrypter(samlDecrypterFactory.buildDecrypter(tokenValidationProperty))
+				.profileValidator(samlSignatureProfileValidator())
+				.tokenValidationProperty(tokenValidationProperty)
 				.verificationCriteria(buildVerificationCriteria(tokenValidationProperty.getIdpEntityId()))
 				.build();
 	}
 
+	SAMLSignatureProfileValidator samlSignatureProfileValidator() {
+		return new SAMLSignatureProfileValidator();
+	}
+
 	CriteriaSet buildVerificationCriteria(String idpEntityId) {
 		return Stream.of(
 				new EvaluableEntityIDCredentialCriterion(new EntityIdCriterion(idpEntityId)),
diff --git a/token-checker-server/src/test/java/de/ozgcloud/token/TokenCheckApplicationTest.java b/token-checker-server/src/test/java/de/ozgcloud/token/TokenCheckApplicationTest.java
deleted file mode 100644
index e664f6c..0000000
--- a/token-checker-server/src/test/java/de/ozgcloud/token/TokenCheckApplicationTest.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2024.
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-
-package de.ozgcloud.token;
-
-import org.junit.jupiter.api.Test;
-
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-
-class TokenCheckApplicationTest {
-
-	@Test
-	void shouldCreateParserPool() throws ComponentInitializationException {
-		TokenCheckApplication application = new TokenCheckApplication();
-
-//		var parserPool = application.parserPool();
-
-//		assertThat(parserPool).isNotNull();
-	}
-}
\ No newline at end of file
diff --git a/token-checker-server/src/test/java/de/ozgcloud/token/saml/Saml2DecryptionServiceTest.java b/token-checker-server/src/test/java/de/ozgcloud/token/saml/Saml2DecryptionServiceTest.java
deleted file mode 100644
index 06d6514..0000000
--- a/token-checker-server/src/test/java/de/ozgcloud/token/saml/Saml2DecryptionServiceTest.java
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Copyright (c) 2024.
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-
-package de.ozgcloud.token.saml;
-
-import static de.ozgcloud.token.saml.SamlTokenTestUtils.*;
-import static org.assertj.core.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.*;
-import static org.mockito.Mockito.*;
-
-import java.util.List;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.mockito.Spy;
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
-import org.opensaml.core.xml.schema.XSAny;
-import org.opensaml.core.xml.schema.XSBoolean;
-import org.opensaml.core.xml.schema.XSBooleanValue;
-import org.opensaml.core.xml.schema.XSInteger;
-import org.opensaml.core.xml.schema.XSString;
-import org.opensaml.saml.saml2.core.Assertion;
-import org.opensaml.saml.saml2.core.Attribute;
-import org.opensaml.saml.saml2.core.AttributeStatement;
-import org.opensaml.saml.saml2.core.AuthnStatement;
-import org.opensaml.saml.saml2.core.Response;
-import org.opensaml.saml.saml2.core.impl.AssertionBuilder;
-import org.opensaml.saml.saml2.core.impl.AttributeBuilder;
-import org.opensaml.saml.saml2.core.impl.AttributeStatementBuilder;
-import org.opensaml.saml.saml2.core.impl.AuthnStatementBuilder;
-import org.opensaml.saml.saml2.core.impl.ResponseUnmarshaller;
-import org.opensaml.saml.saml2.encryption.Decrypter;
-import org.springframework.security.saml2.Saml2Exception;
-
-import de.ozgcloud.common.test.TestUtils;
-import de.ozgcloud.token.TokenAttributeTestFactory;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-
-class Saml2DecryptionServiceTest {
-	private Response samlResponse;
-
-	@Spy
-	private Saml2DecryptionService service;
-
-	private SamlSetting samlSetting;
-	private Saml2ParseService parseService;
-
-	@BeforeEach
-	void setup() throws ComponentInitializationException {
-		var parserPool = SamlTokenTestUtils.initParserPool();
-
-		var samlSettingsRegistry = SamlTokenTestUtils.initConfig(BAYERN_ID);
-		samlSetting = samlSettingsRegistry.getService(IDP_ENTITY_ID_BAYERN_ID);
-		var responseUnmarshaller = (ResponseUnmarshaller) XMLObjectProviderRegistrySupport.getUnmarshallerFactory()
-				.getUnmarshaller(Response.DEFAULT_ELEMENT_NAME);
-		parseService = new Saml2ParseService(parserPool, responseUnmarshaller);
-		var token = TestUtils.loadTextFile("SamlResponseBayernId.xml");
-		samlResponse = parseService.parse(token);
-	}
-
-	@Nested
-	class TestDecryptAttributes {
-
-		@Test
-		void shouldCallDecryptResponseElements() {
-			service.decryptAttributes(samlResponse, samlSetting);
-
-			verify(service).decryptResponseElements(samlResponse, samlSetting.getDecrypter());
-		}
-
-		@Test
-		void shouldCallGetAttributes() {
-			service.decryptAttributes(samlResponse, samlSetting);
-
-			verify(service).getAttributes(samlResponse);
-		}
-
-		@Test
-		void shouldReturnTokenAttributes() {
-			var tokenAttribute = TokenAttributeTestFactory.create();
-			doReturn(List.of(tokenAttribute)).when(service).getAttributes(samlResponse);
-
-			var res = service.decryptAttributes(samlResponse, samlSetting);
-
-			assertThat(res).containsExactly(tokenAttribute);
-		}
-	}
-
-	@Nested
-	class TestDecryptResponseElements {
-
-		private Assertion assertion = new AssertionBuilder().buildObject();
-
-		@Test
-		void shouldCallDecryptAssertions() {
-			service.decryptResponseElements(samlResponse, samlSetting.getDecrypter());
-
-			samlResponse.getEncryptedAssertions()
-					.forEach(encryptedAssertion -> verify(service).decryptAssertion(encryptedAssertion, samlSetting.getDecrypter()));
-		}
-
-		@Test
-		void shouldAddDecryptedAssertions() {
-			doReturn(assertion).when(service).decryptAssertion(any(), any());
-
-			service.decryptResponseElements(samlResponse, samlSetting.getDecrypter());
-
-			assertThat(samlResponse.getAssertions()).containsExactly(assertion);
-		}
-
-	}
-
-	@Nested
-	class TestDecryptAssertion {
-
-		private Decrypter decrypter;
-
-		@BeforeEach
-		void setUp() {
-			decrypter = samlSetting.getDecrypter();
-		}
-
-		@Nested
-		class OnDecryptionException {
-			@Test
-			void shouldThrowExceptionWhenDecryptionFails() {
-				var token = TestUtils.loadTextFile("BrokenSamlResponse.xml");
-				var encryptedAssertion = parseService.parse(token).getEncryptedAssertions().getFirst();
-
-				assertThatExceptionOfType(Saml2Exception.class).isThrownBy(
-						() -> service.decryptAssertion(encryptedAssertion, decrypter));
-			}
-		}
-
-		@Nested
-		class OnNoException {
-
-			@Test
-			void shouldHaveSubject() {
-				var samlAssertion = decryptAssertion();
-
-				assertThat(samlAssertion.getSubject()).isNotNull();
-			}
-
-			@Test
-			void shouldHaveAuthnStatements() {
-				var samlAssertion = decryptAssertion();
-
-				assertThat(samlAssertion.getAuthnStatements()).isNotNull();
-			}
-
-			@Test
-			void shouldHaveStatements() {
-				var samlAssertion = decryptAssertion();
-
-				assertThat(samlAssertion.getStatements()).isNotNull();
-			}
-
-			@Test
-			void shouldHaveAttributes() {
-				var samlAssertion = decryptAssertion();
-
-				var statements = (AttributeStatement) samlAssertion.getStatements().get(1);
-				var attributes = statements.getAttributes();
-				assertThat(attributes).hasSize(7);
-			}
-
-			private Assertion decryptAssertion() {
-				return service.decryptAssertion(samlResponse.getEncryptedAssertions().getFirst(), decrypter);
-			}
-		}
-	}
-
-	@Nested
-	class TestGetAttributes {
-		private Attribute attribute = new AttributeBuilder().buildObject();
-		private AuthnStatement authnStatement = new AuthnStatementBuilder().buildObject();
-		private AttributeStatement attributeStatement = new AttributeStatementBuilder().buildObject();
-		private Assertion assertion = new AssertionBuilder().buildObject();
-
-		@BeforeEach
-		void setUpData() {
-			attribute.setName(TokenAttributeTestFactory.NAME);
-			attributeStatement.getAttributes().add(attribute);
-			assertion.getStatements().addAll(List.of(authnStatement, attributeStatement));
-			samlResponse.getAssertions().add(assertion);
-		}
-
-		@Test
-		void shouldCallGetAttributeValues() {
-			service.getAttributes(samlResponse);
-
-			verify(service).getAttributeValues(attribute);
-		}
-
-		@Test
-		void shouldReturnAttributes() {
-			doReturn(TokenAttributeTestFactory.VALUE).when(service).getAttributeValues(attribute);
-
-			var attributes = service.getAttributes(samlResponse);
-
-			assertThat(attributes).containsExactly(TokenAttributeTestFactory.create());
-		}
-	}
-
-	@Nested
-	class TestGetAttributeValue {
-
-		@Test
-		void shouldGetXSStringAttribute() {
-			var attributeValue = mock(XSString.class);
-			when(attributeValue.getValue()).thenReturn("test");
-
-			var value = service.getAttributeValue(attributeValue);
-
-			assertThat(value).isEqualTo("test");
-		}
-
-		@Test
-		void shouldGetXSAnyAttribute() {
-			var attributeValue = mock(XSAny.class);
-			when(attributeValue.getTextContent()).thenReturn("test");
-
-			var value = service.getAttributeValue(attributeValue);
-
-			assertThat(value).isEqualTo("test");
-		}
-
-		@Test
-		void shouldGetXSIntegerAttribute() {
-			var attributeValue = mock(XSInteger.class);
-			when(attributeValue.getValue()).thenReturn(1);
-
-			var value = service.getAttributeValue(attributeValue);
-
-			assertThat(value).isEqualTo("1");
-		}
-
-		@Test
-		void shouldGetXSBooleanAttribute() {
-			var attributeValue = mock(XSBoolean.class);
-			when(attributeValue.getValue()).thenReturn(XSBooleanValue.valueOf("true"));
-
-			var value = service.getAttributeValue(attributeValue);
-
-			assertThat(value).isEqualTo("true");
-		}
-
-		@Test
-		void shouldGetUnknownAttribute() {
-			var value = service.getAttributeValue(mock(XMLObject.class));
-
-			assertThat(value).startsWith("Mock for XMLObject");
-		}
-	}
-
-	@Nested
-	class TestGetAttributeValues {
-		@Test
-		void shouldGetAttributes() {
-			var attribute = mock(Attribute.class);
-
-			var attributeValue1 = mock(XSInteger.class);
-			when(attributeValue1.getValue()).thenReturn(1);
-			var attributeValue2 = mock(XSString.class);
-			when(attributeValue2.getValue()).thenReturn("test");
-			when(attribute.getAttributeValues()).thenReturn(List.of(attributeValue1, attributeValue2));
-
-			var value = service.getAttributeValues(attribute);
-
-			assertThat(value).isEqualTo("1;test");
-		}
-	}
-}
\ No newline at end of file
diff --git a/token-checker-server/src/test/java/de/ozgcloud/token/saml/Saml2ParseServiceTest.java b/token-checker-server/src/test/java/de/ozgcloud/token/saml/Saml2ParseServiceTest.java
deleted file mode 100644
index 590504e..0000000
--- a/token-checker-server/src/test/java/de/ozgcloud/token/saml/Saml2ParseServiceTest.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright (c) 2024.
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-
-package de.ozgcloud.token.saml;
-
-import static org.assertj.core.api.Assertions.*;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.*;
-import static org.mockito.Mockito.*;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.MockedConstruction;
-import org.mockito.Spy;
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.io.UnmarshallingException;
-import org.opensaml.saml.saml2.core.Response;
-import org.opensaml.saml.saml2.core.impl.ResponseUnmarshaller;
-import org.springframework.security.saml2.Saml2Exception;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import com.thedeanda.lorem.LoremIpsum;
-
-import de.ozgcloud.common.errorhandling.TechnicalException;
-import lombok.SneakyThrows;
-import net.shibboleth.utilities.java.support.xml.ParserPool;
-import net.shibboleth.utilities.java.support.xml.XMLParserException;
-
-class Saml2ParseServiceTest {
-
-	@InjectMocks
-	@Spy
-	private Saml2ParseService parser;
-
-	@Mock
-	private ParserPool parserPool;
-	@Mock
-	private ResponseUnmarshaller unmarshaller;
-
-	@Nested
-	class TestParse {
-
-		private final String request = LoremIpsum.getInstance().getParagraphs(1, 1);
-		private final byte[] requestBytes = request.getBytes(StandardCharsets.UTF_8);
-
-		@Mock
-		private Response response;
-
-		@Nested
-		class OnNoException {
-			@BeforeEach
-			@SneakyThrows
-			void mock() {
-				doReturn(response).when(parser).createXmlObject(requestBytes);
-			}
-
-			@Test
-			@SneakyThrows
-			void shouldCallCreateXmlObject() {
-				parse();
-
-				verify(parser).createXmlObject(requestBytes);
-			}
-
-			@Test
-			void shouldReturnResponse() {
-				var returnedResponse = parse();
-
-				assertThat(returnedResponse).isEqualTo(response);
-			}
-		}
-
-		@Nested
-		class OnIOException {
-
-			@Test
-			@SneakyThrows
-			void shouldThrowTechnicalException() {
-				doThrow(IOException.class).when(parser).createXmlObject(requestBytes);
-
-				assertThrows(TechnicalException.class, () -> parse());
-			}
-		}
-
-		Response parse() {
-			return parser.parse(request);
-		}
-	}
-
-	@Nested
-	class TestCreateXmlObject {
-
-		private final byte[] requestBytes = LoremIpsum.getInstance().getParagraphs(1, 1).getBytes(StandardCharsets.UTF_8);
-
-		@Nested
-		class OnNoExceptions {
-			private MockedConstruction<ByteArrayInputStream> inputStreamConstruction;
-			private byte[] passedBytes;
-			private ByteArrayInputStream inputStream;
-
-			@Mock
-			private Document document;
-			@Mock
-			private Element element;
-			@Mock
-			private XMLObject unmarshalledObject;
-
-			@BeforeEach
-			@SneakyThrows
-			void setUp() {
-				inputStreamConstruction = mockConstruction(ByteArrayInputStream.class,
-						(inputStream, context) -> {
-							passedBytes = (byte[]) context.arguments().getFirst();
-							this.inputStream = inputStream;
-						});
-				when(parserPool.parse(any(InputStream.class))).thenReturn(document);
-				when(document.getDocumentElement()).thenReturn(element);
-			}
-
-			@AfterEach
-			void cleanUp() {
-				inputStreamConstruction.close();
-			}
-
-			@Test
-			void shouldConstructByteArrayInputStream() {
-				createXmlObject();
-
-				assertThat(inputStreamConstruction.constructed()).hasSize(1);
-			}
-
-			@Test
-			void shouldPassRequestToByteArrayInputStream() {
-				createXmlObject();
-
-				assertThat(passedBytes).isEqualTo(requestBytes);
-			}
-
-			@Test
-			@SneakyThrows
-			void shouldCallParserPool() {
-				createXmlObject();
-
-				verify(parserPool).parse(inputStream);
-			}
-
-			@Test
-			void shouldGetDocumentElement() {
-				createXmlObject();
-
-				verify(document).getDocumentElement();
-			}
-
-			@Test
-			@SneakyThrows
-			void shouldCallUnmarshaller() {
-				createXmlObject();
-
-				verify(unmarshaller).unmarshall(element);
-			}
-
-			@Test
-			@SneakyThrows
-			void shouldReturnUnmarshalledObject() {
-				when(unmarshaller.unmarshall(element)).thenReturn(unmarshalledObject);
-
-				var result = createXmlObject();
-
-				assertThat(result).isEqualTo(unmarshalledObject);
-			}
-
-			@Test
-			@SneakyThrows
-			void shouldCloseInputStream() {
-				createXmlObject();
-
-				verify(inputStream).close();
-			}
-		}
-
-		@Nested
-		class OnXMLParserException {
-
-			@Test
-			@SneakyThrows
-			void shouldThrowSaml2Exception() {
-				when(parserPool.parse(any(InputStream.class))).thenThrow(XMLParserException.class);
-
-				assertThrows(Saml2Exception.class, () -> createXmlObject());
-			}
-		}
-
-		@Nested
-		class OnUnmarshallingException {
-
-			@Mock
-			private Document document;
-
-			@BeforeEach
-			@SneakyThrows
-			void setUp() {
-				when(parserPool.parse(any(InputStream.class))).thenReturn(document);
-			}
-
-			@Test
-			@SneakyThrows
-			void shouldThrowSaml2Exception() {
-				when(unmarshaller.unmarshall(any())).thenThrow(UnmarshallingException.class);
-
-				assertThrows(Saml2Exception.class, () -> createXmlObject());
-			}
-		}
-
-		@SneakyThrows
-		private XMLObject createXmlObject() {
-			return parser.createXmlObject(requestBytes);
-		}
-	}
-}
\ No newline at end of file
diff --git a/token-checker-server/src/test/java/de/ozgcloud/token/saml/Saml2VerificationServiceTest.java b/token-checker-server/src/test/java/de/ozgcloud/token/saml/Saml2VerificationServiceTest.java
deleted file mode 100644
index f9d3a4e..0000000
--- a/token-checker-server/src/test/java/de/ozgcloud/token/saml/Saml2VerificationServiceTest.java
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * Copyright (c) 2024.
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-
-package de.ozgcloud.token.saml;
-
-import static org.assertj.core.api.Assertions.*;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.*;
-import static org.mockito.Mockito.*;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.UUID;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.Spy;
-import org.opensaml.saml.saml2.core.Issuer;
-import org.opensaml.saml.saml2.core.Response;
-import org.opensaml.saml.security.impl.SAMLSignatureProfileValidator;
-import org.opensaml.security.SecurityException;
-import org.opensaml.xmlsec.signature.Signature;
-import org.opensaml.xmlsec.signature.support.SignatureException;
-import org.opensaml.xmlsec.signature.support.SignatureTrustEngine;
-import org.springframework.security.saml2.core.Saml2Error;
-import org.springframework.security.saml2.core.Saml2ErrorCodes;
-
-import com.thedeanda.lorem.LoremIpsum;
-
-import de.ozgcloud.token.common.errorhandling.TokenVerificationExceptionTestFactory;
-import lombok.SneakyThrows;
-import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
-
-class Saml2VerificationServiceTest {
-	@InjectMocks
-	@Spy
-	private Saml2VerificationService verifier;
-
-	@Mock
-	private Saml2ParseService parser;
-	@Mock
-	private SamlServiceRegistry samlServiceRegistry;
-	@Mock
-	private SAMLSignatureProfileValidator profileValidator;
-
-	@Nested
-	class TestVerify {
-		private final String token = LoremIpsum.getInstance().getParagraphs(1, 1);
-		@Mock
-		private Response response;
-
-		@Test
-		void shouldParseToken() {
-			doReturn(Collections.emptyList()).when(verifier).getSaml2Errors(any());
-
-			callVerify();
-
-			verify(parser).parse(token);
-		}
-
-		@Test
-		void shouldCallGetSaml2Errors() {
-			when(parser.parse(token)).thenReturn(response);
-
-			callVerify();
-
-			verify(verifier).getSaml2Errors(response);
-		}
-
-		@Test
-		void shouldReturnSaml2Errors() {
-			var saml2Error = TokenVerificationExceptionTestFactory.createSaml2Error();
-			doReturn(List.of(saml2Error)).when(verifier).getSaml2Errors(any());
-
-			var errors = callVerify();
-
-			assertThat(errors).containsExactly(saml2Error);
-		}
-
-		private List<Saml2Error> callVerify() {
-			return verifier.verify(token);
-		}
-	}
-
-	@Nested
-	class TestGetSaml2Errors {
-
-		@Mock
-		private Response response;
-
-		@Test
-		void shouldCheckIsSigned() {
-			getSaml2Errors();
-
-			verify(response).isSigned();
-		}
-
-		@Nested
-		class OnIsSigned {
-
-			private final Saml2Error profileError = new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE, "Profile Error");
-			private final Saml2Error signatureError = new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE, "Signature Error");
-
-			@SuppressWarnings("unchecked")
-			@BeforeEach
-			void givenIsSigned() {
-				when(response.isSigned()).thenReturn(true);
-				doAnswer(invocation -> ((List<Saml2Error>) invocation.getArgument(1)).add(profileError))
-						.when(verifier).validateProfile(any(), any());
-				doAnswer(invocation -> ((List<Saml2Error>) invocation.getArgument(1)).add(signatureError))
-						.when(verifier).validateSignature(any(), any());
-			}
-
-			@Test
-			void shouldCallValidateProfile() {
-				getSaml2Errors();
-
-				verify(verifier).validateProfile(eq(response), anyList());
-			}
-
-			@Test
-			void shouldCallValidateSignature() {
-				getSaml2Errors();
-
-				verify(verifier).validateSignature(eq(response), anyList());
-			}
-
-			@Test
-			void shouldReturnSaml2Errors() {
-				var errors = getSaml2Errors();
-
-				assertThat(errors).containsExactlyInAnyOrder(profileError, signatureError);
-			}
-		}
-
-		@Nested
-		class OnIsNotSigned {
-
-			@BeforeEach
-			void givenIsNotSigned() {
-				when(response.isSigned()).thenReturn(false);
-			}
-
-			@Test
-			void shouldNotCallValidateProfile() {
-				getSaml2Errors();
-
-				verify(verifier, never()).validateProfile(any(), any());
-			}
-
-			@Test
-			void shouldNotCallValidateSignature() {
-				getSaml2Errors();
-
-				verify(verifier, never()).validateSignature(any(), any());
-			}
-
-			@Test
-			void shouldReturnSaml2Error() {
-				var expectedSaml2Error = new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE, Saml2VerificationService.SIGNATURE_MISSING);
-
-				var errors = getSaml2Errors();
-
-				assertThat(errors).usingRecursiveFieldByFieldElementComparator().containsExactly(expectedSaml2Error);
-			}
-
-			@Test
-			void shouldReturnUnmodifiableList() {
-				var saml2Error = TokenVerificationExceptionTestFactory.createSaml2Error();
-
-				var list = getSaml2Errors();
-
-				assertThrows(UnsupportedOperationException.class, () -> list.add(saml2Error));
-			}
-		}
-
-		private List<Saml2Error> getSaml2Errors() {
-			return verifier.getSaml2Errors(response);
-		}
-	}
-
-	@Nested
-	class TestValidateProfile {
-
-		@Mock
-		private Response response;
-		@Mock
-		private Signature signature;
-
-		private List<Saml2Error> errors;
-
-		@BeforeEach
-		void setUp() {
-			when(response.getSignature()).thenReturn(signature);
-			errors = new ArrayList<>();
-		}
-
-		@Test
-		@SneakyThrows
-		void shouldCallProfileValidator() {
-			validateProfile();
-
-			verify(profileValidator).validate(signature);
-		}
-
-		@Nested
-		class OnSignatureException {
-
-			@Test
-			@SneakyThrows
-			void shouldAddSaml2Error() {
-				var expectedSaml2Error = new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
-						Saml2VerificationService.INVALID_SIGNATURE_PROFILE + Saml2VerificationService.FORMAT.formatted(response.getID()));
-				doThrow(SignatureException.class).when(profileValidator).validate(signature);
-
-				validateProfile();
-
-				assertThat(errors).usingRecursiveFieldByFieldElementComparator().containsExactly(expectedSaml2Error);
-			}
-		}
-
-		@Nested
-		class OnNoSignatureException {
-
-			@Test
-			@SneakyThrows
-			void shouldNotAddSaml2Error() {
-				validateProfile();
-
-				assertThat(errors).isEmpty();
-			}
-		}
-
-		private void validateProfile() {
-			verifier.validateProfile(response, errors);
-		}
-	}
-
-	@Nested
-	class TestValidateSignature {
-
-		@Mock
-		private Response response;
-		@Mock
-		private Signature signature;
-		@Mock
-		private Issuer issuer;
-		private final String issuerValue = LoremIpsum.getInstance().getWords(1);
-
-		@Mock
-		private SamlSetting samlSetting;
-		@Mock
-		private SignatureTrustEngine trustEngine;
-		@Mock
-		private CriteriaSet criteriaSet;
-
-		private List<Saml2Error> errors;
-		private final String id = UUID.randomUUID().toString();
-
-		@BeforeEach
-		void setUp() {
-			when(response.getSignature()).thenReturn(signature);
-			when(response.getIssuer()).thenReturn(issuer);
-			when(issuer.getValue()).thenReturn(issuerValue);
-			errors = new ArrayList<>();
-			when(samlServiceRegistry.getService(any())).thenReturn(samlSetting);
-			when(samlSetting.getTrustEngine()).thenReturn(trustEngine);
-			when(samlSetting.getCriteriaSet()).thenReturn(criteriaSet);
-		}
-
-		@Test
-		void shouldGetSamlSetting() {
-			validateSignature();
-
-			verify(samlServiceRegistry).getService(issuerValue);
-		}
-
-		@Test
-		void shouldGetTrustEngine() {
-			validateSignature();
-
-			verify(samlSetting).getTrustEngine();
-		}
-
-		@Test
-		void shouldGetCriteriaSet() {
-			validateSignature();
-
-			verify(samlSetting).getCriteriaSet();
-		}
-
-		@Test
-		@SneakyThrows
-		void shouldCallTrustEngine() {
-			validateSignature();
-
-			verify(trustEngine).validate(signature, criteriaSet);
-		}
-
-		@Nested
-		class OnInvalidSignature {
-
-			private final Saml2Error invalidSignatureError = new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
-					Saml2VerificationService.INVALID_SIGNATURE + Saml2VerificationService.FORMAT.formatted(id));
-
-			@BeforeEach
-			@SneakyThrows
-			void givenSignatureIsInvalid() {
-				when(trustEngine.validate(any(), any())).thenReturn(false);
-				when(response.getID()).thenReturn(id);
-			}
-
-			@Test
-			void shouldAddSaml2Error() {
-				validateSignature();
-
-				assertThat(errors).usingRecursiveFieldByFieldElementComparator().containsExactly(invalidSignatureError);
-			}
-		}
-
-		@Nested
-		class OnValidSignature {
-
-			@BeforeEach
-			@SneakyThrows
-			void givenSignatureIsValid() {
-				when(trustEngine.validate(any(), any())).thenReturn(true);
-			}
-
-			@Test
-			void shouldNotAddSaml2Error() {
-				validateSignature();
-
-				assertThat(errors).isEmpty();
-			}
-		}
-
-		@Nested
-		class OnSecurityException {
-
-			private final Saml2Error errorOnValidatingSignatureError = new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
-					Saml2VerificationService.ERROR_VALIDATING_SIGNATURE + Saml2VerificationService.FORMAT.formatted(id));
-
-			@BeforeEach
-			@SneakyThrows
-			void givenSecurityExceptionThrown() {
-				when(trustEngine.validate(any(), any())).thenThrow(SecurityException.class);
-				when(response.getID()).thenReturn(id);
-			}
-
-			@Test
-			void shouldAddSaml2Error() {
-				validateSignature();
-
-				assertThat(errors).usingRecursiveFieldByFieldElementComparator().containsExactly(errorOnValidatingSignatureError);
-			}
-		}
-
-		private void validateSignature() {
-			verifier.validateSignature(response, errors);
-		}
-	}
-}
\ No newline at end of file
diff --git a/token-checker-server/src/test/java/de/ozgcloud/token/saml/SamlConfigurationTest.java b/token-checker-server/src/test/java/de/ozgcloud/token/saml/SamlConfigurationTest.java
new file mode 100644
index 0000000..82f6021
--- /dev/null
+++ b/token-checker-server/src/test/java/de/ozgcloud/token/saml/SamlConfigurationTest.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.token.saml;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.util.List;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.opensaml.saml.saml2.encryption.Decrypter;
+import org.opensaml.saml.security.impl.SAMLSignatureProfileValidator;
+import org.opensaml.xmlsec.signature.support.SignatureTrustEngine;
+
+import com.thedeanda.lorem.LoremIpsum;
+
+import de.ozgcloud.token.TokenValidationProperties;
+import de.ozgcloud.token.TokenValidationProperties.TokenValidationProperty;
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+
+class SamlConfigurationTest {
+
+	private static final String IDP_ENTITY_ID = LoremIpsum.getInstance().getWords(1);
+
+	@Spy
+	@InjectMocks
+	private SamlConfiguration configuration;
+
+	@Mock
+	private SamlTrustEngineFactory samlTrustEngineFactory;
+	@Mock
+	private SamlDecrypterFactory samlDecrypterFactory;
+
+	@Nested
+	class TestSamlServiceRegistry {
+
+		@Mock
+		private TokenValidationProperties tokenValidationProperties;
+		@Mock
+		private TokenValidationProperty tokenValidationProperty;
+		@Mock
+		private SamlTokenValidationService tokenValidationService;
+
+		@BeforeEach
+		void init() {
+			when(tokenValidationProperty.getIdpEntityId()).thenReturn(IDP_ENTITY_ID);
+			when(tokenValidationProperties.getEntities()).thenReturn(List.of(tokenValidationProperty));
+			doReturn(tokenValidationService).when(configuration).samlTokenService(any());
+		}
+
+		@Test
+		void shouldCallSamlTokenService() {
+			configuration.samServiceRegistry(tokenValidationProperties);
+
+			verify(configuration).samlTokenService(tokenValidationProperty);
+		}
+
+		@Test
+		void shouldAddService() {
+			var result = configuration.samServiceRegistry(tokenValidationProperties);
+
+			assertThat(result.getService(IDP_ENTITY_ID)).contains(tokenValidationService);
+		}
+	}
+
+	@Nested
+	class TestSamlTokenService {
+
+		@Mock
+		private TokenValidationProperty tokenValidationProperty;
+		@Mock
+		private SignatureTrustEngine signatureTrustEngine;
+		@Mock
+		private Decrypter decrypter;
+		@Mock
+		private SAMLSignatureProfileValidator profileValidator;
+		@Mock
+		private CriteriaSet verificationCriteria;
+
+		@BeforeEach
+		void init() {
+			when(tokenValidationProperty.getIdpEntityId()).thenReturn(IDP_ENTITY_ID);
+			doReturn(signatureTrustEngine).when(samlTrustEngineFactory).buildSamlTrustEngine(any());
+			doReturn(decrypter).when(samlDecrypterFactory).buildDecrypter(any());
+			doReturn(profileValidator).when(configuration).samlSignatureProfileValidator();
+			doReturn(verificationCriteria).when(configuration).buildVerificationCriteria(any());
+		}
+
+		@Test
+		void shouldCallBuildSamlTrustEngine() {
+			samlTokenService();
+
+			verify(samlTrustEngineFactory).buildSamlTrustEngine(tokenValidationProperty);
+		}
+
+		@Test
+		void shouldSetSignatureTrustEngine() {
+			var result = samlTokenService();
+
+			assertThat(result).extracting("signatureTrustEngine").isEqualTo(signatureTrustEngine);
+		}
+
+		@Test
+		void shouldCallBuildDecrypter() {
+			samlTokenService();
+
+			verify(samlDecrypterFactory).buildDecrypter(tokenValidationProperty);
+		}
+
+		@Test
+		void shouldSetDecrypter() {
+			var result = samlTokenService();
+
+			assertThat(result).extracting("decrypter").isEqualTo(decrypter);
+		}
+
+		@Test
+		void shouldCallSamlSignatureProfileValidator() {
+			samlTokenService();
+
+			verify(configuration).samlSignatureProfileValidator();
+		}
+
+		@Test
+		void shouldSetProfileValidator() {
+			var result = samlTokenService();
+
+			assertThat(result).extracting("profileValidator").isEqualTo(profileValidator);
+		}
+
+		@Test
+		void shouldSetTokenValidationProperty() {
+			var result = samlTokenService();
+
+			assertThat(result).extracting("tokenValidationProperty").isEqualTo(tokenValidationProperty);
+		}
+
+		@Test
+		void shouldCallBuildVerificationCriteria() {
+			samlTokenService();
+
+			verify(configuration).buildVerificationCriteria(IDP_ENTITY_ID);
+		}
+
+		@Test
+		void shouldSetVerificationCriteria() {
+			var result = samlTokenService();
+
+			assertThat(result).extracting("verificationCriteria").isEqualTo(verificationCriteria);
+		}
+
+		private SamlTokenValidationService samlTokenService() {
+			return configuration.samlTokenService(tokenValidationProperty);
+		}
+	}
+}
\ No newline at end of file
diff --git a/token-checker-server/src/test/java/de/ozgcloud/token/saml/SamlTokenUtilsTest.java b/token-checker-server/src/test/java/de/ozgcloud/token/saml/SamlTokenUtilsTest.java
deleted file mode 100644
index 87e7b67..0000000
--- a/token-checker-server/src/test/java/de/ozgcloud/token/saml/SamlTokenUtilsTest.java
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Copyright (c) 2024.
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-
-package de.ozgcloud.token.saml;
-
-import static de.ozgcloud.token.saml.SamlTokenUtils.*;
-import static org.assertj.core.api.Assertions.*;
-import static org.mockito.Mockito.*;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.List;
-
-import org.jetbrains.annotations.NotNull;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.mockito.Mock;
-import org.opensaml.core.config.ConfigurationService;
-import org.opensaml.core.config.InitializationService;
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistry;
-import org.opensaml.saml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml.saml2.metadata.IDPSSODescriptor;
-import org.opensaml.saml.saml2.metadata.KeyDescriptor;
-import org.opensaml.security.credential.UsageType;
-import org.opensaml.xmlsec.signature.KeyInfo;
-import org.opensaml.xmlsec.signature.X509Data;
-import org.springframework.core.io.InputStreamResource;
-import org.springframework.core.io.Resource;
-import org.springframework.security.saml2.Saml2Exception;
-
-import de.ozgcloud.common.test.TestUtils;
-import de.ozgcloud.token.TokenValidationProperties;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.xml.BasicParserPool;
-import net.shibboleth.utilities.java.support.xml.ParserPool;
-import net.shibboleth.utilities.java.support.xml.XMLParserException;
-
-class SamlTokenUtilsTest {
-	private XMLObjectProviderRegistry registry;
-	private ParserPool parserPool;
-
-	@BeforeEach
-	void setup() throws ComponentInitializationException {
-		parserPool = parserPool();
-		initOpenSAML();
-	}
-
-	private ParserPool parserPool() throws ComponentInitializationException {
-		var localParserPool = new BasicParserPool();
-
-		final var features = SamlTokenUtils.createFeatureMap();
-		localParserPool.setBuilderFeatures(features);
-		localParserPool.setBuilderAttributes(new HashMap<>());
-		localParserPool.initialize();
-
-		return localParserPool;
-	}
-
-	public void initOpenSAML() {
-		try {
-			registry = new XMLObjectProviderRegistry();
-			ConfigurationService.register(XMLObjectProviderRegistry.class, registry);
-
-			registry.setParserPool(parserPool);
-			InitializationService.initialize();
-		} catch (Exception e) {
-			throw new RuntimeException("Initialization failed");
-		}
-	}
-
-	XMLObject xmlObject(InputStream inputStream) throws XMLParserException {
-		var document = parserPool.parse(inputStream);
-		var element = document.getDocumentElement();
-		var unmarshaller = registry.getUnmarshallerFactory().getUnmarshaller(element);
-		if (unmarshaller == null) {
-			throw new Saml2Exception("Unsupported element of type " + element.getTagName());
-		}
-		try {
-			return unmarshaller.unmarshall(element);
-		} catch (Exception ex) {
-			throw new Saml2Exception(ex);
-		}
-	}
-
-	@Nested
-	class TestXmlFeatureMapCreation {
-		@Test
-		void shouldCreateFeatureMap() {
-			var map = SamlTokenUtils.createFeatureMap();
-
-			assertThat(map).isNotNull();
-		}
-
-		@Test
-		void shouldHaveExternalGeneralEntitiesFalse() {
-			var map = SamlTokenUtils.createFeatureMap();
-
-			assertThat(map).containsEntry(FEATURES_EXTERNAL_GENERAL_ENTITIES, Boolean.FALSE);
-		}
-
-		@Test
-		void shouldHaveExternalParameterEntitiesFalse() {
-			var map = SamlTokenUtils.createFeatureMap();
-
-			assertThat(map).containsEntry(FEATURES_EXTERNAL_PARAMETER_ENTITIES, Boolean.FALSE);
-		}
-
-		@Test
-		void shouldHaveDisallowDocTypeDeclTrue() {
-			var map = SamlTokenUtils.createFeatureMap();
-
-			assertThat(map).containsEntry(FEATURES_DISALLOW_DOCTYPE_DECL, Boolean.TRUE);
-		}
-
-		@Test
-		void shouldHaveValidationSchemaNormalizedFalse() {
-			var map = SamlTokenUtils.createFeatureMap();
-
-			assertThat(map).containsEntry(VALIDATION_SCHEMA_NORMALIZED_VALUE, Boolean.FALSE);
-		}
-
-		@Test
-		void shouldHaveSecureProcessingTrue() {
-			var map = SamlTokenUtils.createFeatureMap();
-
-			assertThat(map).containsEntry(FEATURE_SECURE_PROCESSING, Boolean.TRUE);
-		}
-	}
-
-	@Nested
-	class TestLoadingDecryptionCredentials {
-		private Resource key;
-		private Resource certificate;
-
-		@BeforeEach
-		void setUp() {
-			TokenValidationProperties tokenCheckerProperties = SamlTokenTestUtils.initProperties();
-			key = tokenCheckerProperties.getEntities().getFirst().getKey();
-			certificate = tokenCheckerProperties.getEntities().getFirst().getCertificate();
-		}
-
-		@Test
-		void shouldLoadDecryptionCredentials() {
-			var credentials = SamlTokenUtils.getDecryptionCredential(key, certificate);
-
-			assertThat(credentials).isNotNull();
-		}
-
-		@Test
-		void shouldNotLoadDecryptionCredentialsBecauseOfMissingCertificate() {
-			assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> SamlTokenUtils.getDecryptionCredential(key, null))
-			  .withMessageStartingWith(NO_CERTIFICATE_LOCATION_SPECIFIED);
-		}
-
-		@Test
-		void shouldNotLoadDecryptionCredentialsBecauseOfMissingKey() {
-			assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> SamlTokenUtils.getDecryptionCredential(null, certificate))
-			  .withMessageStartingWith(NO_PRIVATE_KEY_LOCATION_SPECIFIED);
-		}
-
-		@Nested
-		class TestMissingLocations {
-			@Mock
-			private Resource keyMock;
-			@Mock
-			private Resource certificateMock;
-
-			@Test
-			void shouldNotLoadDecryptionCredentialsBecauseOfMissingCertificateLocation() {
-				when(certificateMock.exists()).thenReturn(Boolean.FALSE);
-
-				assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> SamlTokenUtils.getDecryptionCredential(key, certificateMock))
-				  .withMessageStartingWith(CERTIFICATE_LOCATION);
-			}
-
-			@Test
-			void shouldNotLoadDecryptionCredentialsBecauseOfCertificateIOException() throws IOException {
-				when(certificateMock.exists()).thenReturn(Boolean.TRUE);
-				when(certificateMock.getInputStream()).thenThrow(new IOException("test"));
-
-				assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(
-				  () -> SamlTokenUtils.getDecryptionCredential(key, certificateMock));
-			}
-
-			@Test
-			void shouldNotLoadDecryptionCredentialsBecauseOfMissingKeyLocation() {
-				when(keyMock.exists()).thenReturn(Boolean.FALSE);
-
-				assertThatExceptionOfType(IllegalStateException.class).isThrownBy(
-				  () -> SamlTokenUtils.getDecryptionCredential(keyMock, certificate)).withMessageStartingWith(PRIVATE_KEY_LOCATION);
-			}
-
-			@Test
-			void shouldNotLoadDecryptionCredentialsBecauseOfKeyIOException() throws IOException {
-				when(keyMock.exists()).thenReturn(Boolean.TRUE);
-				when(keyMock.getInputStream()).thenThrow(new IOException("test"));
-
-				assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(
-				  () -> SamlTokenUtils.getDecryptionCredential(keyMock, certificate));
-			}
-		}
-	}
-
-	@Nested
-	class TestLoadingEntityDescriptor {
-		@Test
-		void shouldLoadEntityDescriptor() throws IOException, XMLParserException {
-			var metadata = xmlObject(new InputStreamResource(TestUtils.loadFile("metadata/bayernid-idp-infra.xml")).getInputStream());
-
-			var entityDescriptor = SamlTokenUtils.findEntityDescriptor(metadata);
-
-			assertThat(entityDescriptor).isNotEmpty();
-		}
-
-		@Test
-		void shouldLoadEntitiesDescriptor() throws IOException, XMLParserException {
-			var metadata = xmlObject(new InputStreamResource(TestUtils.loadFile("metadata/mujina_metadata.xml")).getInputStream());
-
-			var entityDescriptor = SamlTokenUtils.findEntityDescriptor(metadata);
-
-			assertThat(entityDescriptor).isNotEmpty();
-		}
-
-		@Test
-		void shouldNotLoadEntityDescriptor() {
-			var entityDescriptor = SamlTokenUtils.findEntityDescriptor(null);
-
-			assertThat(entityDescriptor).isEmpty();
-		}
-
-		@Test
-		void shouldNotLoadEntityDescriptorMissing() throws IOException, XMLParserException {
-			var metadata = xmlObject(new InputStreamResource(TestUtils.loadFile("metadata/missing_IDPSSODescriptor.xml")).getInputStream());
-
-			var entityDescriptor = SamlTokenUtils.findEntityDescriptor(metadata);
-
-			assertThat(entityDescriptor).isEmpty();
-		}
-	}
-
-	@Nested
-	class TestLoadingVerificationCertificatesFromIDPMetadata {
-
-		@Test
-		void shouldLoadVerificationCertificates() throws IOException, XMLParserException {
-			var metadata = xmlObject(new InputStreamResource(TestUtils.loadFile("metadata/bayernid-idp-infra.xml")).getInputStream());
-
-			var credentials = SamlTokenUtils.getVerificationCertificates(SamlTokenUtils.findEntityDescriptor(metadata).get());
-
-			assertThat(credentials).isNotEmpty();
-		}
-
-		@Test
-		void shouldNotLoadVerificationCertificatesBecauseOfException() throws IOException, XMLParserException {
-			var metadata = xmlObject(new InputStreamResource(TestUtils.loadFile("metadata/invalid_IDPSSODescriptor.xml")).getInputStream());
-			var cert = SamlTokenUtils.findEntityDescriptor(metadata).get();
-
-			assertThatExceptionOfType(Saml2Exception.class).isThrownBy(
-				() -> SamlTokenUtils.getVerificationCertificates(cert))
-			  .withMessageStartingWith(SAML_ASSERTIONS_VERIFICATION_EMPTY);
-		}
-
-		@Test
-		void shouldNotLoadVerificationCertificatesBecauseMissing() {
-			var entityDescriptor = mock(EntityDescriptor.class);
-			when(entityDescriptor.getIDPSSODescriptor(anyString())).thenReturn(null);
-
-			assertThatExceptionOfType(Saml2Exception.class).isThrownBy(
-				() -> SamlTokenUtils.getVerificationCertificates(entityDescriptor))
-			  .withMessageStartingWith(MISSING_THE_NECESSARY_IDPSSODESCRIPTOR_ELEMENT);
-		}
-
-		@Test
-		void shouldNotLoadCertificates() {
-			var entityDescriptor = initTestData();
-
-			assertThatExceptionOfType(Saml2Exception.class).isThrownBy(
-			  () -> SamlTokenUtils.getVerificationCertificates(entityDescriptor));
-		}
-
-		private static @NotNull EntityDescriptor initTestData() {
-			var entityDescriptor = mock(EntityDescriptor.class);
-			var iDPSSODescriptor = mock(IDPSSODescriptor.class);
-			var keyDescriptor = mock(KeyDescriptor.class);
-			var keyInfo = mock(KeyInfo.class);
-			var x509Data = mock(X509Data.class);
-			var x509Certificate = mock(org.opensaml.xmlsec.signature.X509Certificate.class);
-			when(x509Certificate.getValue()).thenReturn(
-			  "-----BEGIN CERTIFICATE-----\nMIIEGzCCAwOgAwIBAgIUWPZFfhB4+iI3XdjUTMqhhDkljGgwDQYJKoZIhvcNAQEL\n-----END CERTIFICATE-----");
-			when(x509Data.getX509Certificates()).thenReturn(List.of(x509Certificate));
-			when(keyInfo.getX509Datas()).thenReturn(List.of(x509Data));
-			when(keyDescriptor.getKeyInfo()).thenReturn(keyInfo);
-			when(keyDescriptor.getUse()).thenReturn(UsageType.SIGNING);
-			when(iDPSSODescriptor.getKeyDescriptors()).thenReturn(List.of(keyDescriptor));
-			when(entityDescriptor.getIDPSSODescriptor(anyString())).thenReturn(iDPSSODescriptor);
-			return entityDescriptor;
-		}
-	}
-}
\ No newline at end of file
diff --git a/token-checker-server/src/test/java/de/ozgcloud/token/saml/SamlTokenValidationServiceTest.java b/token-checker-server/src/test/java/de/ozgcloud/token/saml/SamlTokenValidationServiceTest.java
index 7f0fd52..7998a53 100644
--- a/token-checker-server/src/test/java/de/ozgcloud/token/saml/SamlTokenValidationServiceTest.java
+++ b/token-checker-server/src/test/java/de/ozgcloud/token/saml/SamlTokenValidationServiceTest.java
@@ -415,8 +415,7 @@ class SamlTokenValidationServiceTest {
 		@Test
 		void shouldReturnWhenXSBoolean() {
 			var value = String.valueOf(new Random().nextBoolean());
-			XSBooleanValue booleanValue = when(mock(XSBooleanValue.class).toString()).thenReturn(value).getMock();
-			XMLObject attrValue = when(mock(XSBoolean.class).getValue()).thenReturn(booleanValue).getMock();
+			XMLObject attrValue = when(mock(XSBoolean.class).getValue()).thenReturn(XSBooleanValue.valueOf(value)).getMock();
 
 			var result = service.getAttributeValue(attrValue);
 
-- 
GitLab