diff --git a/token-checker-server/src/main/java/de/ozgcloud/token/TokenCheckConfiguration.java b/token-checker-server/src/main/java/de/ozgcloud/token/TokenCheckConfiguration.java
deleted file mode 100644
index df1d3f971d9fe526538bce3bfb109ab449b79945..0000000000000000000000000000000000000000
--- a/token-checker-server/src/main/java/de/ozgcloud/token/TokenCheckConfiguration.java
+++ /dev/null
@@ -1,190 +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 static de.ozgcloud.token.saml.SamlTokenUtils.*;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import jakarta.annotation.PostConstruct;
-
-import org.opensaml.core.config.ConfigurationService;
-import org.opensaml.core.config.InitializationException;
-import org.opensaml.core.config.InitializationService;
-import org.opensaml.core.criterion.EntityIdCriterion;
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistry;
-import org.opensaml.saml.criterion.ProtocolCriterion;
-import org.opensaml.saml.metadata.criteria.role.impl.EvaluableProtocolRoleDescriptorCriterion;
-import org.opensaml.saml.saml2.encryption.Decrypter;
-import org.opensaml.saml.saml2.encryption.EncryptedElementTypeEncryptedKeyResolver;
-import org.opensaml.security.credential.Credential;
-import org.opensaml.security.credential.CredentialResolver;
-import org.opensaml.security.credential.CredentialSupport;
-import org.opensaml.security.credential.UsageType;
-import org.opensaml.security.credential.criteria.impl.EvaluableEntityIDCredentialCriterion;
-import org.opensaml.security.credential.criteria.impl.EvaluableUsageCredentialCriterion;
-import org.opensaml.security.credential.impl.CollectionCredentialResolver;
-import org.opensaml.security.criteria.UsageCriterion;
-import org.opensaml.security.x509.BasicX509Credential;
-import org.opensaml.xmlsec.config.impl.DefaultSecurityConfigurationBootstrap;
-import org.opensaml.xmlsec.encryption.support.ChainingEncryptedKeyResolver;
-import org.opensaml.xmlsec.encryption.support.EncryptedKeyResolver;
-import org.opensaml.xmlsec.encryption.support.InlineEncryptedKeyResolver;
-import org.opensaml.xmlsec.encryption.support.SimpleRetrievalMethodEncryptedKeyResolver;
-import org.opensaml.xmlsec.keyinfo.impl.CollectionKeyInfoCredentialResolver;
-import org.opensaml.xmlsec.signature.support.SignatureTrustEngine;
-import org.opensaml.xmlsec.signature.support.impl.ExplicitKeySignatureTrustEngine;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.core.io.Resource;
-import org.springframework.security.saml2.Saml2Exception;
-import org.springframework.security.saml2.core.Saml2X509Credential;
-import org.springframework.stereotype.Component;
-
-import de.ozgcloud.common.errorhandling.TechnicalException;
-import de.ozgcloud.token.saml.ConfigurationEntity;
-import de.ozgcloud.token.saml.SamlSetting;
-import de.ozgcloud.token.saml.SamlSettingsRegistry;
-import de.ozgcloud.token.saml.SamlTokenUtils;
-import lombok.RequiredArgsConstructor;
-import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
-import net.shibboleth.utilities.java.support.xml.ParserPool;
-import net.shibboleth.utilities.java.support.xml.XMLParserException;
-
-@Component
-@Configuration
-@RequiredArgsConstructor
-public class TokenCheckConfiguration {
-	private XMLObjectProviderRegistry registry;
-	private final TokenCheckProperties tokenCheckerProperties;
-	private final ParserPool parserPool;
-	private final SamlSettingsRegistry samlSettingsRegistry;
-
-	private static final EncryptedKeyResolver encryptedKeyResolver = new ChainingEncryptedKeyResolver(
-			Arrays.asList(new InlineEncryptedKeyResolver(), new EncryptedElementTypeEncryptedKeyResolver(),
-					new SimpleRetrievalMethodEncryptedKeyResolver()));
-
-	@PostConstruct
-	public void initOpenSAML() {
-		try {
-			registry = new XMLObjectProviderRegistry();
-			ConfigurationService.register(XMLObjectProviderRegistry.class, registry);
-
-			registry.setParserPool(parserPool);
-			InitializationService.initialize();
-
-			tokenCheckerProperties.getEntities().forEach(this::initSamlSetting);
-		} catch (InitializationException e) {
-			throw new TechnicalException("Initialization failed", e);
-		}
-	}
-
-	private void initSamlSetting(final ConfigurationEntity entity) {
-		var trustEngine = initTrustEngine(entity.getMetadata(), entity.getIdpEntityId());
-		var verificationCriteria = getVerificationCriteria(entity.getIdpEntityId());
-		var decrypter = initDecrypter(entity);
-
-		var samlSetting = SamlSetting.builder()
-				.trustEngine(trustEngine)
-				.criteriaSet(verificationCriteria)
-				.decrypter(decrypter)
-				.mappings(entity.getMappings())
-				.idIsPostfachId(entity.getUseIdAsPostfachId())
-				.build();
-
-		samlSettingsRegistry.addSetting(entity.getIdpEntityId(), samlSetting);
-	}
-
-	private SignatureTrustEngine initTrustEngine(Resource metadata, String idpEntityId) {
-		Set<Credential> credentials = new HashSet<>();
-		Collection<Saml2X509Credential> keys = getCertificatesFromMetadata(metadata);
-
-		for (Saml2X509Credential key : keys) {
-			var cred = new BasicX509Credential(key.getCertificate());
-			cred.setUsageType(UsageType.SIGNING);
-			cred.setEntityId(idpEntityId);
-			credentials.add(cred);
-		}
-
-		CredentialResolver credentialsResolver = new CollectionCredentialResolver(credentials);
-		return new ExplicitKeySignatureTrustEngine(credentialsResolver,
-				DefaultSecurityConfigurationBootstrap.buildBasicInlineKeyInfoCredentialResolver());
-	}
-
-	private CriteriaSet getVerificationCriteria(String idpEntityId) {
-		var criteria = new CriteriaSet();
-		criteria.add(new EvaluableEntityIDCredentialCriterion(new EntityIdCriterion(idpEntityId)));
-		criteria.add(new EvaluableProtocolRoleDescriptorCriterion(new ProtocolCriterion("urn:oasis:names:tc:SAML:2.0:protocol")));
-		criteria.add(new EvaluableUsageCredentialCriterion(new UsageCriterion(UsageType.SIGNING)));
-		return criteria;
-	}
-
-	private List<Saml2X509Credential> getCertificatesFromMetadata(Resource metadataResource) {
-		try (var metadata = metadataResource.getInputStream()) {
-			var xmlObject = xmlObject(metadata);
-			var descriptorOptional = findEntityDescriptor(xmlObject);
-			if (descriptorOptional.isPresent()) {
-				return SamlTokenUtils.getVerificationCertificates(descriptorOptional.get());
-			}
-		} catch (IOException e) {
-			throw new Saml2Exception("Error reading idp metadata.", e);
-		} catch (XMLParserException e) {
-			throw new Saml2Exception("Error initializing parser pool.", e);
-		}
-
-		throw new Saml2Exception("No IDPSSO Descriptors found");
-	}
-
-	private 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);
-		}
-	}
-
-	private Decrypter initDecrypter(ConfigurationEntity entity) {
-		var credentials = new ArrayList<Credential>();
-		var decryptionX509Credential = SamlTokenUtils.getDecryptionCredential(entity.getKey(), entity.getCertificate());
-
-		var cred = CredentialSupport.getSimpleCredential(decryptionX509Credential.getCertificate(), decryptionX509Credential.getPrivateKey());
-		credentials.add(cred);
-
-		var resolver = new CollectionKeyInfoCredentialResolver(credentials);
-		var setupDecrypter = new Decrypter(null, resolver, encryptedKeyResolver);
-		setupDecrypter.setRootInNewDocument(true);
-
-		return setupDecrypter;
-	}
-}
diff --git a/token-checker-server/src/main/java/de/ozgcloud/token/TokenCheckerConfiguration.java b/token-checker-server/src/main/java/de/ozgcloud/token/TokenCheckerConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..00bce6c3068da62d39b1fa3682d1ce00d3631cd6
--- /dev/null
+++ b/token-checker-server/src/main/java/de/ozgcloud/token/TokenCheckerConfiguration.java
@@ -0,0 +1,76 @@
+/*
+ * 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 java.util.Map;
+
+import org.opensaml.core.config.ConfigurationService;
+import org.opensaml.core.config.InitializationException;
+import org.opensaml.core.config.InitializationService;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistry;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.stereotype.Component;
+
+import lombok.RequiredArgsConstructor;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.xml.BasicParserPool;
+import net.shibboleth.utilities.java.support.xml.ParserPool;
+
+@Component
+@Configuration
+@RequiredArgsConstructor
+public class TokenCheckerConfiguration {
+
+	public static final String FEATURES_EXTERNAL_GENERAL_ENTITIES = "http://xml.org/sax/features/external-general-entities";
+	public static final String FEATURES_EXTERNAL_PARAMETER_ENTITIES = "http://xml.org/sax/features/external-parameter-entities";
+	public static final String FEATURES_DISALLOW_DOCTYPE_DECL = "http://apache.org/xml/features/disallow-doctype-decl";
+	public static final String VALIDATION_SCHEMA_NORMALIZED_VALUE = "http://apache.org/xml/features/validation/schema/normalized-value";
+	public static final String FEATURE_SECURE_PROCESSING = "http://javax.xml.XMLConstants/feature/secure-processing";
+
+	@Bean
+	ParserPool parserPool() throws ComponentInitializationException {
+		var localParserPool = new BasicParserPool();
+		localParserPool.setBuilderFeatures(createFeatureMap());
+		localParserPool.initialize();
+
+		return localParserPool;
+	}
+
+	Map<String, Boolean> createFeatureMap() {
+		return Map.of(
+				FEATURES_EXTERNAL_GENERAL_ENTITIES, Boolean.FALSE,
+				FEATURES_EXTERNAL_PARAMETER_ENTITIES, Boolean.FALSE,
+				FEATURES_DISALLOW_DOCTYPE_DECL, Boolean.TRUE,
+				VALIDATION_SCHEMA_NORMALIZED_VALUE, Boolean.FALSE,
+				FEATURE_SECURE_PROCESSING, Boolean.TRUE);
+	}
+
+	@Bean
+	XMLObjectProviderRegistry xmlObjectProviderRegistry(ParserPool parserPool) throws InitializationException {
+		var registry = new XMLObjectProviderRegistry();
+		registry.setParserPool(parserPool);
+		ConfigurationService.register(XMLObjectProviderRegistry.class, registry);
+		InitializationService.initialize();
+		return registry;
+	}
+
+}
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 ebbec99d8289c722135a1b46e788a414211c682b..765249041fe488427e299d744c89f1db216f5422 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
@@ -1,17 +1,35 @@
 package de.ozgcloud.token.saml;
 
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.opensaml.core.criterion.EntityIdCriterion;
 import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.saml.criterion.ProtocolCriterion;
+import org.opensaml.saml.metadata.criteria.role.impl.EvaluableProtocolRoleDescriptorCriterion;
 import org.opensaml.saml.saml2.core.Response;
 import org.opensaml.saml.saml2.core.impl.ResponseUnmarshaller;
 import org.opensaml.saml.security.impl.SAMLSignatureProfileValidator;
+import org.opensaml.security.credential.UsageType;
+import org.opensaml.security.credential.criteria.impl.EvaluableEntityIDCredentialCriterion;
+import org.opensaml.security.credential.criteria.impl.EvaluableUsageCredentialCriterion;
+import org.opensaml.security.criteria.UsageCriterion;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 
+import de.ozgcloud.token.TokenValidationProperties;
+import lombok.RequiredArgsConstructor;
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+
 @Configuration
+@RequiredArgsConstructor
 public class SamlConfiguration {
 
+	private final SamlTrustEngineFactory samlTrustEngineFactory;
+	private final SamlDecrypterFactory samlDecrypterFactory;
+
 	@Bean
-	SAMLSignatureProfileValidator sAMLSignatureProfileValidator() {
+	SAMLSignatureProfileValidator samlSignatureProfileValidator() {
 		return new SAMLSignatureProfileValidator();
 	}
 
@@ -19,4 +37,31 @@ public class SamlConfiguration {
 	ResponseUnmarshaller responseUnmarshaller() {
 		return (ResponseUnmarshaller) XMLObjectProviderRegistrySupport.getUnmarshallerFactory().getUnmarshaller(Response.DEFAULT_ELEMENT_NAME);
 	}
+
+	@Bean
+	SamlServiceRegistry samSettingsRegistry(TokenValidationProperties tokenValidationProperties) {
+		var registryBuilder = SamlServiceRegistry.builder();
+		for (var tokenEntity : tokenValidationProperties.getEntities()) {
+			registryBuilder.samlService(tokenEntity.getIdpEntityId(), samlTokenService(tokenEntity));
+		}
+		return registryBuilder.build();
+	}
+
+	SamlTokenService samlTokenService(TokenValidationProperties.TokenValidationProperty tokenValidationProperty) {
+		return SamlTokenService.builder()
+				.signatureTrustEngine(samlTrustEngineFactory.buildSamlTrustEngine(tokenValidationProperty))
+				.decrypter(samlDecrypterFactory.buildDecrypter(tokenValidationProperty))
+				.verificationCriteria(buildVerificationCriteria(tokenValidationProperty.getIdpEntityId()))
+				.userIdAsPostfachId(tokenValidationProperty.isUserIdAsPostfachId())
+				.build();
+	}
+
+	CriteriaSet buildVerificationCriteria(String idpEntityId) {
+		return Stream.of(
+				new EvaluableEntityIDCredentialCriterion(new EntityIdCriterion(idpEntityId)),
+				new EvaluableProtocolRoleDescriptorCriterion(new ProtocolCriterion("urn:oasis:names:tc:SAML:2.0:protocol")),
+				new EvaluableUsageCredentialCriterion(new UsageCriterion(UsageType.SIGNING))
+		).collect(Collectors.toCollection(CriteriaSet::new));
+	}
+
 }