summaryrefslogtreecommitdiff
path: root/eaaf_modules/eaaf_module_pvp2_core
diff options
context:
space:
mode:
authorThomas Lenz <thomas.lenz@egiz.gv.at>2020-01-31 20:41:54 +0100
committerThomas Lenz <thomas.lenz@egiz.gv.at>2020-01-31 20:41:54 +0100
commitd41afe91ee59daf6b5f5037cecac52900fe2ccb2 (patch)
tree3a19e1818d276d701574758ce6166b2f3a7e2030 /eaaf_modules/eaaf_module_pvp2_core
parent0cf9926282ba4aa46bad3f4e8020cec72683492f (diff)
downloadEAAF-Components-d41afe91ee59daf6b5f5037cecac52900fe2ccb2.tar.gz
EAAF-Components-d41afe91ee59daf6b5f5037cecac52900fe2ccb2.tar.bz2
EAAF-Components-d41afe91ee59daf6b5f5037cecac52900fe2ccb2.zip
a lot of more OpenSAML3 refactoring staff
This version is also NOT stable!
Diffstat (limited to 'eaaf_modules/eaaf_module_pvp2_core')
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/pom.xml16
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PvpConstants.java33
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IDecoder.java9
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IEncoder.java18
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/credential/EaafX509Credential.java25
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvp2MetadataProvider.java (renamed from eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataProvider.java)39
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlBindingException.java12
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlSigningException.java17
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/AbstractBinding.java108
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/PostBinding.java220
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/RedirectBinding.java376
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/SoapBinding.java203
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/CitizenTokenBuilder.java6
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PvpMetadataBuilder.java10
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/SamlAttributeGenerator.java6
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafExtensionImplementation.java2
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestExtensionBuilder.java8
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeBuilder.java4
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeMarshaller.java17
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeUnmarshaller.java15
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesBuilder.java4
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesMarshaller.java2
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesUnmarshaller.java8
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/logging/PvpModuleMessageSource.java17
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/InboundMessage.java18
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PvpSProfileRequest.java11
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PvpSProfileResponse.java11
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/AbstractChainingMetadataProvider.java253
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/MetadataFilterChain.java76
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/SimpleMetadataResolver.java (renamed from eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/SimpleMetadataProvider.java)104
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpPostDecoder.java77
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpRedirectDeflateDecoder.java71
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafKeyStoreX509CredentialAdapter.java58
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/HttpPostEncoderWithOwnTemplate.java56
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/StringRedirectDeflateEncoder.java33
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafDefaultSaml2Bootstrap.java88
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafDefaultSecurityConfigurationBootstrap.java218
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafOpenSaml3xInitializer.java156
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EaafRequestedAttributeImpl.java12
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EaafRequestedAttributesImpl.java8
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/AbstractCredentialProvider.java109
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/Saml2Utils.java235
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/EaafUriCompare.java3
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/TrustEngineFactory.java36
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/AbstractMetadataSignatureFilter.java19
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/PvpEntityCategoryFilter.java41
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SchemaValidationFilter.java22
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/AbstractRequestSignedSecurityPolicyRule.java33
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafMessageContextInitializationHandler.java23
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpAuthRequestSignedRole.java57
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSamlMessageHandlerChain.java71
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSignedRequestPolicyRule.java9
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SamlVerificationEngine.java80
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/resources/eaaf_pvp.beans.xml21
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/resources/messages/pvp_messages.properties12
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/PostBindingTest.java448
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/RedirectBindingTest.java490
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/dummy/DummyCredentialProvider.java70
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_1.props8
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_with_sig_1.xml38
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_without_sig_1.xml11
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_with_sig_1.xml81
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_without_sig_1.xml52
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit.jksbin0 -> 2733 bytes
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_postbinding_template.html3
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core.beans.xml22
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_pvp.beans.xml29
67 files changed, 3228 insertions, 1220 deletions
diff --git a/eaaf_modules/eaaf_module_pvp2_core/pom.xml b/eaaf_modules/eaaf_module_pvp2_core/pom.xml
index abf2ebe5..62973ac5 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/pom.xml
+++ b/eaaf_modules/eaaf_module_pvp2_core/pom.xml
@@ -49,10 +49,6 @@
</dependency>
<dependency>
- <groupId>org.owasp.esapi</groupId>
- <artifactId>esapi</artifactId>
- </dependency>
- <dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
@@ -64,6 +60,18 @@
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>at.gv.egiz.eaaf</groupId>
+ <artifactId>eaaf-core</artifactId>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
+
</dependencies>
<build>
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PvpConstants.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PvpConstants.java
index 979a61d5..b1ac8e75 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PvpConstants.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PvpConstants.java
@@ -28,19 +28,33 @@ import javax.xml.namespace.QName;
import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions;
import at.gv.egiz.eaaf.core.impl.data.Triple;
+import org.apache.xml.security.algorithms.MessageDigestAlgorithm;
+import org.apache.xml.security.signature.XMLSignature;
import org.opensaml.xmlsec.encryption.support.EncryptionConstants;
import org.opensaml.xmlsec.signature.support.SignatureConstants;
+import com.google.common.collect.ImmutableMap;
+
public interface PvpConstants extends PvpAttributeDefinitions {
+ //module configuration parameters
+ String CONFIG_PROP_SEC_SIGNING_RSA_ALG = "pvp2.security.alg.signing.rsa";
+ String CONFIG_PROP_SEC_SIGNING_EC_ALG = "pvp2.security.alg.signing.ec";
- String DEFAULT_SIGNING_METHODE =
+ //Default values
+ String DEFAULT_SIGNING_METHODE_RSA =
SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256;
+ String DEFAULT_SIGNING_METHODE_EC =
+ SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA256;
+
String DEFAULT_DIGESTMETHODE = SignatureConstants.ALGO_ID_DIGEST_SHA256;
+
String DEFAULT_SYM_ENCRYPTION_METHODE =
EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256;
String DEFAULT_ASYM_ENCRYPTION_METHODE =
EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP;
+
+ //PVP entity categories
String ENTITY_CATEGORY_ATTRIBITE = "http://macedir.org/entity-category";
String EGOVTOKEN = "http://www.ref.gv.at/ns/names/agiz/pvp/egovtoken";
String CITIZENTOKEN = "http://www.ref.gv.at/ns/names/agiz/pvp/citizentoken";
@@ -136,4 +150,21 @@ public interface PvpConstants extends PvpAttributeDefinitions {
QName EIDAS_REQUESTED_ATTRIBUTE_VALUE_TYPE =
new QName(EIDAT10_SAML_NS, "AttributeValue", EIDAT10_PREFIX);
+ ImmutableMap<String, String> SIGNATURE_TO_DIGEST_ALGORITHM_MAP =
+ ImmutableMap.<String, String>builder()
+ .put(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256, SignatureConstants.ALGO_ID_DIGEST_SHA256)
+ .put(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA384, SignatureConstants.ALGO_ID_DIGEST_SHA384)
+ .put(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA512, SignatureConstants.ALGO_ID_DIGEST_SHA512)
+ .put(SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA256, SignatureConstants.ALGO_ID_DIGEST_SHA256)
+ .put(SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA384, SignatureConstants.ALGO_ID_DIGEST_SHA384)
+ .put(SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA512, SignatureConstants.ALGO_ID_DIGEST_SHA512)
+ .put(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256_MGF1, SignatureConstants.ALGO_ID_DIGEST_SHA256)
+ .put(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA384_MGF1, SignatureConstants.ALGO_ID_DIGEST_SHA384)
+ .put(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512_MGF1, SignatureConstants.ALGO_ID_DIGEST_SHA512)
+ .put(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA3_256_MGF1, MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA3_256)
+ .put(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA3_384_MGF1, MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA3_384)
+ .put(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA3_512_MGF1, MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA3_512)
+
+ .build();
+
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IDecoder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IDecoder.java
index 57dd63bf..e8da499c 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IDecoder.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IDecoder.java
@@ -23,18 +23,15 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
-import org.opensaml.messaging.decoder.MessageDecodingException;
-import org.opensaml.saml2.metadata.provider.MetadataProvider;
-import org.opensaml.security.SecurityException;
-
import net.shibboleth.utilities.java.support.net.URIComparator;
public interface IDecoder {
InboundMessageInterface decode(HttpServletRequest req, HttpServletResponse resp,
- MetadataProvider metadataProvider, boolean isSpEndPoint, URIComparator comparator)
- throws MessageDecodingException, SecurityException, Pvp2Exception;
+ IPvp2MetadataProvider metadataProvider, boolean isSpEndPoint, URIComparator comparator)
+ throws Pvp2Exception;
boolean handleDecode(String action, HttpServletRequest req);
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IEncoder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IEncoder.java
index 01f541a9..691d6574 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IEncoder.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IEncoder.java
@@ -23,13 +23,12 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
-import org.opensaml.messaging.encoder.MessageEncodingException;
import org.opensaml.saml.saml2.core.RequestAbstractType;
import org.opensaml.saml.saml2.core.StatusResponseType;
import org.opensaml.security.SecurityException;
-import org.opensaml.security.credential.Credential;
public interface IEncoder {
@@ -44,13 +43,11 @@ public interface IEncoder {
* @param credentials Credential to sign the request object
* @param pendingReq Internal MOA-ID request object that contains
* session-state informations but never null
- * @throws MessageEncodingException In case of an error
- * @throws SecurityException In case of an error
- * @throws Pvp2Exception In case of an error
+ * @throws Pvp2Exception In case of an error
*/
void encodeRequest(HttpServletRequest req, HttpServletResponse resp,
- RequestAbstractType request, String targetLocation, String relayState, Credential credentials,
- IRequest pendingReq) throws MessageEncodingException, SecurityException, Pvp2Exception;
+ RequestAbstractType request, String targetLocation, String relayState, EaafX509Credential credentials,
+ IRequest pendingReq) throws Pvp2Exception;
/**
* Encoder SAML Response.
@@ -63,10 +60,9 @@ public interface IEncoder {
* @param credentials Credential to sign the response object
* @param pendingReq Internal MOA-ID request object that contains
* session-state informations but never null
- * @throws MessageEncodingException In case of an error
* @throws SecurityException In case of an error
*/
- void encodeRespone(HttpServletRequest req, HttpServletResponse resp,
- StatusResponseType response, String targetLocation, String relayState, Credential credentials,
- IRequest pendingReq) throws MessageEncodingException, SecurityException, Pvp2Exception;
+ void encodeResponse(HttpServletRequest req, HttpServletResponse resp,
+ StatusResponseType response, String targetLocation, String relayState, EaafX509Credential credentials,
+ IRequest pendingReq) throws Pvp2Exception;
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/credential/EaafX509Credential.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/credential/EaafX509Credential.java
new file mode 100644
index 00000000..568b617d
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/credential/EaafX509Credential.java
@@ -0,0 +1,25 @@
+package at.gv.egiz.eaaf.modules.pvp2.api.credential;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.security.x509.X509Credential;
+
+
+public interface EaafX509Credential extends X509Credential {
+
+ /**
+ * Get the signature algorithm that has to be used with this credential.
+ *
+ * @return Signature-algorithm identifier
+ */
+ @Nonnull
+ String getSignatureAlgorithmForSigning();
+
+ /**
+ * Set the signature algorithm that has to be used with this credential.
+ *
+ * @param sigAlg Signature-algorithm identifier
+ */
+ void setSignatureAlgorithmForSigning(@Nonnull String sigAlg);
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvp2MetadataProvider.java
index 25b2d250..e2ee0c9d 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataProvider.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvp2MetadataProvider.java
@@ -23,42 +23,29 @@ import java.util.List;
import javax.xml.namespace.QName;
-import org.opensaml.saml2.metadata.EntitiesDescriptor;
-import org.opensaml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml2.metadata.RoleDescriptor;
-import org.opensaml.saml2.metadata.provider.MetadataFilter;
-import org.opensaml.saml2.metadata.provider.MetadataProvider;
-import org.opensaml.saml2.metadata.provider.MetadataProviderException;
-import org.opensaml.xml.XMLObject;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException;
-public interface IPvpMetadataProvider extends MetadataProvider {
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.saml.metadata.resolver.MetadataResolver;
+import org.opensaml.saml.saml2.metadata.EntitiesDescriptor;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml.saml2.metadata.RoleDescriptor;
- @Override
- boolean requireValidMetadata();
+public interface IPvp2MetadataProvider extends MetadataResolver {
- @Override
- void setRequireValidMetadata(boolean requireValidMetadata);
+ XMLObject getMetadata() throws Pvp2MetadataException;
- @Override
- MetadataFilter getMetadataFilter();
- @Override
- void setMetadataFilter(MetadataFilter newFilter) throws MetadataProviderException;
+ EntitiesDescriptor getEntitiesDescriptor(String entitiesID) throws Pvp2MetadataException;
- @Override
- XMLObject getMetadata() throws MetadataProviderException;
- @Override
- EntitiesDescriptor getEntitiesDescriptor(String entitiesID) throws MetadataProviderException;
+ EntityDescriptor getEntityDescriptor(String entityID) throws Pvp2MetadataException;
- @Override
- EntityDescriptor getEntityDescriptor(String entityID) throws MetadataProviderException;
- @Override
- List<RoleDescriptor> getRole(String entityID, QName roleName) throws MetadataProviderException;
+ List<RoleDescriptor> getRole(String entityID, QName roleName) throws Pvp2MetadataException;
+
- @Override
RoleDescriptor getRole(String entityID, QName roleName, String supportedProtocol)
- throws MetadataProviderException;
+ throws Pvp2MetadataException;
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlBindingException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlBindingException.java
new file mode 100644
index 00000000..9f079584
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlBindingException.java
@@ -0,0 +1,12 @@
+package at.gv.egiz.eaaf.modules.pvp2.exception;
+
+public class SamlBindingException extends Pvp2Exception {
+
+ private static final long serialVersionUID = 7122051055002687486L;
+
+ public SamlBindingException(String messageId, Object[] parameters, Throwable wrapped) {
+ super(messageId, parameters, wrapped);
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlSigningException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlSigningException.java
new file mode 100644
index 00000000..e1a5a9d9
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlSigningException.java
@@ -0,0 +1,17 @@
+package at.gv.egiz.eaaf.modules.pvp2.exception;
+
+public class SamlSigningException extends Pvp2Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ public SamlSigningException(String messageId, Object[] parameters, Throwable wrapped) {
+ super(messageId, parameters, wrapped);
+
+ }
+
+ public SamlSigningException(String messageId, Object[] parameters) {
+ super(messageId, parameters);
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/AbstractBinding.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/AbstractBinding.java
new file mode 100644
index 00000000..ae108c35
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/AbstractBinding.java
@@ -0,0 +1,108 @@
+package at.gv.egiz.eaaf.modules.pvp2.impl.binding;
+
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
+import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory;
+
+import org.opensaml.core.config.ConfigurationService;
+import org.opensaml.messaging.context.BaseContext;
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.saml.common.SAMLObject;
+import org.opensaml.saml.common.SignableSAMLObject;
+import org.opensaml.saml.common.binding.SAMLBindingSupport;
+import org.opensaml.saml.common.binding.encoding.SAMLMessageEncoder;
+import org.opensaml.saml.common.messaging.context.SAMLEndpointContext;
+import org.opensaml.saml.common.messaging.context.SAMLMessageInfoContext;
+import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext;
+import org.opensaml.saml.common.messaging.context.SAMLProtocolContext;
+import org.opensaml.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.saml2.metadata.SingleSignOnService;
+import org.opensaml.saml.saml2.metadata.impl.SingleSignOnServiceBuilder;
+import org.opensaml.xmlsec.SignatureSigningParameters;
+import org.opensaml.xmlsec.SignatureValidationConfiguration;
+import org.opensaml.xmlsec.SignatureValidationParameters;
+import org.opensaml.xmlsec.context.SecurityParametersContext;
+import org.opensaml.xmlsec.signature.support.SignatureConstants;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * Abstract Binding implements common code for SAML2 binding implementations.
+ *
+ * @author tlenz
+ *
+ */
+public abstract class AbstractBinding {
+
+ @Autowired protected IConfiguration basicConfig;
+
+ public abstract String getSaml2BindingName();
+
+ protected MessageContext<SAMLObject> buildBasicMessageContext(
+ SAMLMessageEncoder encoder, SignableSAMLObject response) {
+ final MessageContext<SAMLObject> messageContext = new MessageContext<SAMLObject>();
+ messageContext.setMessage(response);
+ encoder.setMessageContext(messageContext);
+ return messageContext;
+
+ }
+
+ protected BaseContext injectSigningInfos(EaafX509Credential credentials) throws SamlSigningException {
+ final SecurityParametersContext securityParamContext = new SecurityParametersContext();
+ final SignatureSigningParameters signingParams = new SignatureSigningParameters();
+ securityParamContext.setSignatureSigningParameters(signingParams);
+
+ signingParams.setSigningCredential(credentials);
+ signingParams.setSignatureCanonicalizationAlgorithm(
+ SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
+ signingParams.setSignatureReferenceCanonicalizationAlgorithm(
+ SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
+ signingParams.setSignatureAlgorithm(credentials.getSignatureAlgorithmForSigning());
+ signingParams.setSignatureReferenceDigestMethod(
+ Saml2Utils.getDigestAlgorithm(signingParams.getSignatureAlgorithm()));
+
+ signingParams.setKeyInfoGenerator(Saml2Utils.getKeyInfoGenerator(credentials, false));
+
+ return securityParamContext;
+
+ }
+
+ protected BaseContext injectEndpointInfos(final SignableSAMLObject response, String targetLocation) {
+ SAMLBindingSupport.setSAML2Destination(response, targetLocation);
+ final SingleSignOnService service = new SingleSignOnServiceBuilder().buildObject();
+ service.setBinding(getSaml2BindingName());
+ service.setLocation(targetLocation);
+ final SAMLPeerEntityContext peerEntityContext = new SAMLPeerEntityContext();
+ final SAMLEndpointContext endpointContext = new SAMLEndpointContext();
+ endpointContext.setEndpoint(service);
+ peerEntityContext.addSubcontext(endpointContext);
+ return peerEntityContext;
+
+ }
+
+ protected void injectInboundMessageContexts(MessageContext<SAMLObject> messageContext,
+ IPvp2MetadataProvider metadataProvider) {
+ messageContext.addSubcontext(new SAMLPeerEntityContext());
+ messageContext.addSubcontext(new SAMLMessageInfoContext());
+
+
+ final SAMLProtocolContext protocolContext = new SAMLProtocolContext();
+ protocolContext.setProtocol(SAMLConstants.SAML20P_NS);
+ messageContext.addSubcontext(protocolContext);
+
+
+ final SecurityParametersContext securityParameterContext = new SecurityParametersContext();
+ final SignatureValidationParameters sigValParameters = new SignatureValidationParameters();
+ securityParameterContext.setSignatureValidationParameters(sigValParameters);
+ messageContext.addSubcontext(securityParameterContext);
+
+ sigValParameters.setBlacklistedAlgorithms(
+ ConfigurationService.get(SignatureValidationConfiguration.class)
+ .getBlacklistedAlgorithms());
+ sigValParameters.setSignatureTrustEngine(
+ TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider));
+
+ }
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/PostBinding.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/PostBinding.java
index 251f6081..6f39392d 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/PostBinding.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/PostBinding.java
@@ -27,48 +27,37 @@ import at.gv.egiz.eaaf.core.api.gui.IGuiBuilderConfigurationFactory;
import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiBuilderConfiguration;
import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiFormBuilder;
import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
-import at.gv.egiz.eaaf.core.impl.gui.velocity.VelocityProvider;
import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
import at.gv.egiz.eaaf.modules.pvp2.api.binding.IDecoder;
import at.gv.egiz.eaaf.modules.pvp2.api.binding.IEncoder;
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.exception.InvalidPvpRequestException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SamlBindingException;
import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage;
import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileRequest;
import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileResponse;
+import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.EaafHttpPostDecoder;
import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.HttpPostEncoderWithOwnTemplate;
-import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafDefaultSaml2Bootstrap;
-import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory;
-import at.gv.egiz.eaaf.modules.pvp2.impl.verification.PvpSignedRequestPolicyRule;
-import org.apache.commons.lang3.StringUtils;
-import org.opensaml.common.binding.BasicSAMLMessageContext;
+import org.opensaml.messaging.context.MessageContext;
import org.opensaml.messaging.decoder.MessageDecodingException;
-import org.opensaml.messaging.encoder.MessageEncodingException;
import org.opensaml.saml.common.SAMLObject;
+import org.opensaml.saml.common.binding.SAMLBindingSupport;
+import org.opensaml.saml.common.messaging.SAMLMessageSecuritySupport;
import org.opensaml.saml.common.xml.SAMLConstants;
-import org.opensaml.saml.saml2.binding.decoding.impl.HTTPPostDecoder;
+import org.opensaml.saml.saml2.core.RequestAbstractType;
import org.opensaml.saml.saml2.core.StatusResponseType;
-import org.opensaml.saml.saml2.metadata.IDPSSODescriptor;
-import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
-import org.opensaml.saml.saml2.metadata.SingleSignOnService;
-import org.opensaml.saml.saml2.metadata.impl.SingleSignOnServiceBuilder;
-import org.opensaml.saml2.metadata.provider.MetadataProvider;
-import org.opensaml.security.credential.Credential;
-import org.opensaml.ws.security.SecurityPolicyResolver;
-import org.opensaml.ws.security.provider.BasicSecurityPolicy;
-import org.opensaml.ws.security.provider.StaticSecurityPolicyResolver;
-import org.opensaml.ws.transport.http.HttpServletRequestAdapter;
-import org.opensaml.ws.transport.http.HttpServletResponseAdapter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
+import lombok.extern.slf4j.Slf4j;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
import net.shibboleth.utilities.java.support.net.URIComparator;
-@Service("PVPPOSTBinding")
-public class PostBinding implements IDecoder, IEncoder {
- private static final Logger log = LoggerFactory.getLogger(PostBinding.class);
+@Slf4j
+public class PostBinding extends AbstractBinding implements IDecoder, IEncoder {
@Autowired(required = true)
IConfiguration authConfig;
@@ -78,152 +67,160 @@ public class PostBinding implements IDecoder, IEncoder {
IGuiBuilderConfigurationFactory guiConfigFactory;
@Override
- public void encodeRequest(final HttpServletRequest req, final HttpServletResponse resp,
+ public void encodeRequest(final HttpServletRequest httpReq, final HttpServletResponse httpResp,
final RequestAbstractType request, final String targetLocation, final String relayState,
- final Credential credentials, final IRequest pendingReq)
- throws MessageEncodingException, SecurityException {
+ final EaafX509Credential credentials, final IRequest pendingReq)
+ throws Pvp2Exception {
try {
- // load default PVP security configurations
- EaafDefaultSaml2Bootstrap.initializeDefaultPvpConfiguration();
-
// initialize POST binding encoder with template decoration
final IVelocityGuiBuilderConfiguration guiConfig =
guiConfigFactory.getSpSpecificSaml2PostConfiguration(pendingReq,
"pvp_postbinding_template.html", authConfig.getConfigurationRootDirectory());
- final HttpPostEncoderWithOwnTemplate encoder = new HttpPostEncoderWithOwnTemplate(guiConfig,
- guiBuilder, VelocityProvider.getClassPathVelocityEngine());
+ final HttpPostEncoderWithOwnTemplate encoder
+ = new HttpPostEncoderWithOwnTemplate(guiConfig, guiBuilder);
+
+ encoder.setHttpServletResponse(httpResp);
+
+ //inject message context
+ final MessageContext<SAMLObject> messageContext = buildBasicMessageContext(encoder, request);
+
+ //inject signing context
+ messageContext.addSubcontext(injectSigningInfos(credentials));
- // set OpenSAML2 process parameter into binding context dao
- final HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter(resp, true);
- final BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context =
- new BasicSAMLMessageContext<>();
- final SingleSignOnService service = new SingleSignOnServiceBuilder().buildObject();
- service.setBinding("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST");
- service.setLocation(targetLocation);
+ //set endpoint url
+ messageContext.addSubcontext(injectEndpointInfos(request, targetLocation));
- context.setOutboundSAMLMessageSigningCredential(credentials);
- context.setPeerEntityEndpoint(service);
- context.setOutboundSAMLMessage(request);
- context.setOutboundMessageTransport(responseAdapter);
- context.setRelayState(relayState);
- encoder.encode(context);
+ //set relayState of exists
+ SAMLBindingSupport.setRelayState(messageContext, relayState);
+
+ //sign SAML2 message
+ SAMLMessageSecuritySupport.signMessage(messageContext);
+
+ //encode message
+ encoder.initialize();
+ encoder.encode();
} catch (final Exception e) {
- log.warn("Can not encode SAML2 request", e);
- throw new SecurityException(e);
+ log.warn("Can not encode SAML2 Post-Binding request", e);
+ throw new SamlBindingException("internal.pvp.95",
+ new Object[] {PvpConstants.POST, "encoding", e.getMessage()},
+ e);
}
}
@Override
- public void encodeRespone(final HttpServletRequest req, final HttpServletResponse resp,
+ public void encodeResponse(final HttpServletRequest httpReq, final HttpServletResponse httpResp,
final StatusResponseType response, final String targetLocation, final String relayState,
- final Credential credentials, final IRequest pendingReq)
- throws MessageEncodingException, SecurityException {
+ final EaafX509Credential credentials, final IRequest pendingReq)
+ throws Pvp2Exception {
try {
- // load default PVP security configurations
- EaafDefaultSaml2Bootstrap.initializeDefaultPvpConfiguration();
-
log.debug("create SAML POSTBinding response");
// initialize POST binding encoder with template decoration
final IVelocityGuiBuilderConfiguration guiConfig =
guiConfigFactory.getSpSpecificSaml2PostConfiguration(pendingReq,
"pvp_postbinding_template.html", authConfig.getConfigurationRootDirectory());
- final HttpPostEncoderWithOwnTemplate encoder = new HttpPostEncoderWithOwnTemplate(guiConfig,
- guiBuilder, VelocityProvider.getClassPathVelocityEngine());
-
- // set OpenSAML2 process parameter into binding context dao
- final HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter(resp, true);
- final BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context =
- new BasicSAMLMessageContext<>();
- final SingleSignOnService service = new SingleSignOnServiceBuilder().buildObject();
- service.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);
- service.setLocation(targetLocation);
- context.setOutboundSAMLMessageSigningCredential(credentials);
- context.setPeerEntityEndpoint(service);
- // context.setOutboundMessage(authReq);
- context.setOutboundSAMLMessage(response);
- context.setOutboundMessageTransport(responseAdapter);
- context.setRelayState(relayState);
-
- encoder.encode(context);
+ final HttpPostEncoderWithOwnTemplate encoder =
+ new HttpPostEncoderWithOwnTemplate(guiConfig, guiBuilder);
+
+ encoder.setHttpServletResponse(httpResp);
+
+ //inject message context
+ final MessageContext<SAMLObject> messageContext = buildBasicMessageContext(encoder, response);
+
+ //inject signing context
+ messageContext.addSubcontext(injectSigningInfos(credentials));
+
+ //set endpoint url
+ messageContext.addSubcontext(injectEndpointInfos(response, targetLocation));
+
+ //set relayState of exists
+ SAMLBindingSupport.setRelayState(messageContext, relayState);
+
+ //sign SAML2 message
+ SAMLMessageSecuritySupport.signMessage(messageContext);
+
+ //encode message
+ encoder.initialize();
+ encoder.encode();
} catch (final Exception e) {
- log.warn("Can not encode SAML2 response", e);
- throw new SecurityException(e);
+ log.warn("Can not encode SAML2 Post-Binding response", e);
+ throw new SamlBindingException("internal.pvp.95",
+ new Object[] {PvpConstants.POST, "encoding", e.getMessage()},
+ e);
}
}
+
+
+
+
@Override
public InboundMessageInterface decode(final HttpServletRequest req,
- final HttpServletResponse resp, final MetadataProvider metadataProvider,
+ final HttpServletResponse resp, final IPvp2MetadataProvider metadataProvider,
final boolean isSpEndPoint, final URIComparator comparator)
- throws MessageDecodingException, SecurityException {
+ throws Pvp2Exception {
- final HTTPPostDecoder decode = new HTTPPostDecoder();
+ //TODO: check, if we should re-implement HTTPPostDecoder to collect the last http parameter!!!
+ final EaafHttpPostDecoder decode = new EaafHttpPostDecoder();
decode.setHttpServletRequest(req);
- final BasicSAMLMessageContext<SAMLObject, ?, ?> messageContext =
- new BasicSAMLMessageContext<>();
- messageContext.setInboundMessageTransport(new HttpServletRequestAdapter(req));
- // set metadata descriptor type
- if (isSpEndPoint) {
- messageContext.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME);
- decode.setURIComparator(comparator);
+ //decode request
+ try {
+ decode.initialize();
+ decode.decode();
- } else {
- messageContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
- decode.setURIComparator(comparator);
+ } catch (MessageDecodingException | ComponentInitializationException e) {
+ throw new SamlBindingException("internal.pvp.95",
+ new Object[] {PvpConstants.POST, "decoding", e.getMessage()},
+ e);
}
- messageContext.setMetadataProvider(metadataProvider);
+ final MessageContext<SAMLObject> messageContext = decode.getMessageContext();
+
+ if (SAMLBindingSupport.isSigningCapableBinding(messageContext)) {
+ log.info("SAML Post-Binding message contains no signature. Message will be rejected");
+ throw new InvalidPvpRequestException("internal.pvp.02", null);
+
+ }
+
+ //inject informations into message context that are required for further processing
+ injectInboundMessageContexts(messageContext, metadataProvider);
+
+
+ //TODO: add sig validation!!!
- // set security policy context
- final BasicSecurityPolicy policy = new BasicSecurityPolicy();
- policy.getPolicyRules()
- .add(new PvpSignedRequestPolicyRule(metadataProvider,
- TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider),
- messageContext.getPeerEntityRole()));
- final SecurityPolicyResolver secResolver = new StaticSecurityPolicyResolver(policy);
- messageContext.setSecurityPolicyResolver(secResolver);
- decode.decode(messageContext);
InboundMessage msg = null;
- if (messageContext.getInboundMessage() instanceof RequestAbstractType) {
+
+ if (messageContext.getMessage() instanceof RequestAbstractType) {
final RequestAbstractType inboundMessage =
- (RequestAbstractType) messageContext.getInboundMessage();
+ (RequestAbstractType) messageContext.getMessage();
msg = new PvpSProfileRequest(inboundMessage, getSaml2BindingName());
msg.setEntityID(inboundMessage.getIssuer().getValue());
- } else if (messageContext.getInboundMessage() instanceof StatusResponseType) {
+ } else if (messageContext.getMessage() instanceof StatusResponseType) {
final StatusResponseType inboundMessage =
- (StatusResponseType) messageContext.getInboundMessage();
+ (StatusResponseType) messageContext.getMessage();
msg = new PvpSProfileResponse(inboundMessage);
msg.setEntityID(inboundMessage.getIssuer().getValue());
} else {
// create empty container if request type is unknown
msg = new InboundMessage();
- }
- if (messageContext.getPeerEntityMetadata() != null) {
- msg.setEntityID(messageContext.getPeerEntityMetadata().getEntityID());
- } else {
- if (StringUtils.isEmpty(msg.getEntityID())) {
- log.info(
- "No Metadata found for OA with EntityID " + messageContext.getInboundMessageIssuer());
- }
}
- msg.setVerified(true);
- msg.setRelayState(messageContext.getRelayState());
+ msg.setVerified(false);
+ msg.setRelayState(SAMLBindingSupport.getRelayState(messageContext));
return msg;
}
@@ -231,6 +228,7 @@ public class PostBinding implements IDecoder, IEncoder {
@Override
public boolean handleDecode(final String action, final HttpServletRequest req) {
return req.getMethod().equals("POST") && action.equals(PvpConstants.POST);
+
}
@Override
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/RedirectBinding.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/RedirectBinding.java
index 559ee3b8..5f74053d 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/RedirectBinding.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/RedirectBinding.java
@@ -26,211 +26,315 @@ import at.gv.egiz.eaaf.core.api.IRequest;
import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
import at.gv.egiz.eaaf.modules.pvp2.api.binding.IDecoder;
import at.gv.egiz.eaaf.modules.pvp2.api.binding.IEncoder;
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface;
-import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.exception.InvalidPvpRequestException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SamlBindingException;
import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage;
import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileRequest;
import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileResponse;
-import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafDefaultSaml2Bootstrap;
-import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory;
-import at.gv.egiz.eaaf.modules.pvp2.impl.verification.PvpAuthRequestSignedRole;
+import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.EaafHttpRedirectDeflateDecoder;
+import at.gv.egiz.eaaf.modules.pvp2.impl.verification.PvpSamlMessageHandlerChain;
-import org.apache.commons.lang3.StringUtils;
-import org.opensaml.common.binding.BasicSAMLMessageContext;
+import org.opensaml.messaging.context.MessageContext;
import org.opensaml.messaging.decoder.MessageDecodingException;
-import org.opensaml.messaging.encoder.MessageEncodingException;
+import org.opensaml.messaging.handler.MessageHandlerException;
import org.opensaml.saml.common.SAMLObject;
+import org.opensaml.saml.common.binding.SAMLBindingSupport;
+import org.opensaml.saml.common.binding.impl.CheckMessageVersionHandler;
+import org.opensaml.saml.common.binding.security.impl.MessageLifetimeSecurityHandler;
+import org.opensaml.saml.common.messaging.context.SAMLBindingContext;
import org.opensaml.saml.common.xml.SAMLConstants;
-import org.opensaml.saml.saml2.binding.decoding.impl.HTTPRedirectDeflateDecoder;
import org.opensaml.saml.saml2.binding.encoding.impl.HTTPRedirectDeflateEncoder;
+import org.opensaml.saml.saml2.binding.security.impl.SAML2HTTPRedirectDeflateSignatureSecurityHandler;
import org.opensaml.saml.saml2.core.RequestAbstractType;
import org.opensaml.saml.saml2.core.StatusResponseType;
-import org.opensaml.saml.saml2.metadata.IDPSSODescriptor;
-import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
-import org.opensaml.saml.saml2.metadata.SingleSignOnService;
-import org.opensaml.saml.saml2.metadata.impl.SingleSignOnServiceBuilder;
-import org.opensaml.saml2.binding.security.SAML2HTTPRedirectDeflateSignatureRule;
-import org.opensaml.saml2.metadata.provider.MetadataProvider;
-import org.opensaml.security.credential.Credential;
-import org.opensaml.ws.security.SecurityPolicyResolver;
-import org.opensaml.ws.security.provider.BasicSecurityPolicy;
-import org.opensaml.ws.security.provider.StaticSecurityPolicyResolver;
-import org.opensaml.ws.transport.http.HttpServletRequestAdapter;
-import org.opensaml.ws.transport.http.HttpServletResponseAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Service;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
import net.shibboleth.utilities.java.support.net.URIComparator;
-import net.shibboleth.utilities.java.support.xml.BasicParserPool;
-@Service("PVPRedirectBinding")
-public class RedirectBinding implements IDecoder, IEncoder {
+public class RedirectBinding extends AbstractBinding implements IDecoder, IEncoder {
private static final Logger log = LoggerFactory.getLogger(RedirectBinding.class);
@Override
public void encodeRequest(final HttpServletRequest req, final HttpServletResponse resp,
final RequestAbstractType request, final String targetLocation, final String relayState,
- final Credential credentials, final IRequest pendingReq)
- throws MessageEncodingException, SecurityException {
-
- // load default PVP security configurations
- EaafDefaultSaml2Bootstrap.initializeDefaultPvpConfiguration();
-
- log.debug("create SAML RedirectBinding response");
-
- final HTTPRedirectDeflateEncoder encoder = new HTTPRedirectDeflateEncoder();
- final HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter(resp, true);
- final BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context =
- new BasicSAMLMessageContext<>();
- final SingleSignOnService service = new SingleSignOnServiceBuilder().buildObject();
- service.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
- service.setLocation(targetLocation);
- context.setOutboundSAMLMessageSigningCredential(credentials);
- context.setPeerEntityEndpoint(service);
- context.setOutboundSAMLMessage(request);
- context.setOutboundMessageTransport(responseAdapter);
- context.setRelayState(relayState);
-
- encoder.encode(context);
+ final EaafX509Credential credentials, final IRequest pendingReq)
+ throws Pvp2Exception {
+
+ try {
+ log.debug("create SAML RedirectBinding response");
+ final HTTPRedirectDeflateEncoder encoder = new HTTPRedirectDeflateEncoder();
+ encoder.setHttpServletResponse(resp);
+
+ final MessageContext<SAMLObject> messageContext = buildBasicMessageContext(encoder, request);
+
+ // set endpoint url
+ messageContext.addSubcontext(injectEndpointInfos(request, targetLocation));
+
+ // inject signing context
+ messageContext.addSubcontext(injectSigningInfos(credentials));
+
+ // set relayState of exists
+ SAMLBindingSupport.setRelayState(messageContext, relayState);
+
+ // encode message
+ encoder.initialize();
+ encoder.encode();
+
+ } catch (final Exception e) {
+ log.warn("Can not encode SAML2 Redirect-Binding request", e);
+ throw new SamlBindingException("internal.pvp.95",
+ new Object[] { PvpConstants.REDIRECT, "encoding", e.getMessage() },
+ e);
+
+ }
+
}
@Override
- public void encodeRespone(final HttpServletRequest req, final HttpServletResponse resp,
+ public void encodeResponse(final HttpServletRequest req, final HttpServletResponse resp,
final StatusResponseType response, final String targetLocation, final String relayState,
- final Credential credentials, final IRequest pendingReq)
- throws MessageEncodingException, SecurityException {
+ final EaafX509Credential credentials, final IRequest pendingReq)
+ throws Pvp2Exception {
+
+ try {
+ log.debug("create SAML RedirectBinding response");
+
+ final HTTPRedirectDeflateEncoder encoder = new HTTPRedirectDeflateEncoder();
+ encoder.setHttpServletResponse(resp);
+
+ final MessageContext<SAMLObject> messageContext = buildBasicMessageContext(encoder, response);
+
+ // set endpoint url
+ messageContext.addSubcontext(injectEndpointInfos(response, targetLocation));
- // load default PVP security configurations
- EaafDefaultSaml2Bootstrap.initializeDefaultPvpConfiguration();
+ // inject signing context
+ messageContext.addSubcontext(injectSigningInfos(credentials));
- log.debug("create SAML RedirectBinding response");
+ // set relayState of exists
+ SAMLBindingSupport.setRelayState(messageContext, relayState);
- final HTTPRedirectDeflateEncoder encoder = new HTTPRedirectDeflateEncoder();
- final HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter(resp, true);
- final BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context =
- new BasicSAMLMessageContext<>();
- final SingleSignOnService service = new SingleSignOnServiceBuilder().buildObject();
- service.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
- service.setLocation(targetLocation);
- context.setOutboundSAMLMessageSigningCredential(credentials);
- context.setPeerEntityEndpoint(service);
- context.setOutboundSAMLMessage(response);
- context.setOutboundMessageTransport(responseAdapter);
- context.setRelayState(relayState);
+ // encode message
+ encoder.initialize();
+ encoder.encode();
- encoder.encode(context);
+ } catch (final Exception e) {
+ log.warn("Can not encode SAML2 Redirect-Binding request", e);
+ throw new SamlBindingException("internal.pvp.95",
+ new Object[] { PvpConstants.REDIRECT, "encoding", e.getMessage() },
+ e);
+
+ }
}
@Override
public InboundMessageInterface decode(final HttpServletRequest req,
- final HttpServletResponse resp, final MetadataProvider metadataProvider,
+ final HttpServletResponse resp, final IPvp2MetadataProvider metadataProvider,
final boolean isSpEndPoint, final URIComparator comparator)
- throws MessageDecodingException, SecurityException {
-
- final HTTPRedirectDeflateDecoder decode = new HTTPRedirectDeflateDecoder(new BasicParserPool());
-
- final BasicSAMLMessageContext<SAMLObject, ?, ?> messageContext =
- new BasicSAMLMessageContext<>();
- messageContext.setInboundMessageTransport(new HttpServletRequestAdapter(req));
+ throws Pvp2Exception {
- // set metadata descriptor type
- if (isSpEndPoint) {
- messageContext.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME);
- decode.setURIComparator(comparator);
+ // TODO: implement one flat decoder to get SAML2 request/response parametes as
+ // same as in SAML2HTTPRedirectDeflateSignatureSecurityHandler
+ final EaafHttpRedirectDeflateDecoder decode = new EaafHttpRedirectDeflateDecoder();
+ decode.setHttpServletRequest(req);
- } else {
- messageContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
- decode.setURIComparator(comparator);
- }
+ // decode request
+ try {
+ decode.initialize();
+ decode.decode();
- messageContext.setMetadataProvider(metadataProvider);
-
- final SAML2HTTPRedirectDeflateSignatureRule signatureRule =
- new SAML2HTTPRedirectDeflateSignatureRule(
- TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider));
- final PvpAuthRequestSignedRole signedRole = new PvpAuthRequestSignedRole();
- final BasicSecurityPolicy policy = new BasicSecurityPolicy();
- policy.getPolicyRules().add(signedRole);
- policy.getPolicyRules().add(signatureRule);
- final SecurityPolicyResolver resolver = new StaticSecurityPolicyResolver(policy);
- messageContext.setSecurityPolicyResolver(resolver);
-
- // set metadata descriptor type
- if (isSpEndPoint) {
- messageContext.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME);
- } else {
- messageContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
+ } catch (MessageDecodingException | ComponentInitializationException e) {
+ throw new SamlBindingException("internal.pvp.95",
+ new Object[] { PvpConstants.REDIRECT, "decoding", e.getMessage() },
+ e);
}
- try {
- decode.decode(messageContext);
-
- // check signature
- signatureRule.evaluate(messageContext);
+ final MessageContext<SAMLObject> messageContext = decode.getMessageContext();
- } catch (final SecurityException e) {
- if (StringUtils.isEmpty(messageContext.getInboundMessageIssuer())) {
- throw e;
+ final SAMLBindingContext bindingContext = messageContext.getSubcontext(SAMLBindingContext.class, true);
+ if (!bindingContext.hasBindingSignature()) {
+ log.info("SAML Redirect-Binding message contains no signature. Message will be rejected");
+ throw new InvalidPvpRequestException("internal.pvp.02", null);
- }
+ }
- if (metadataProvider instanceof IRefreshableMetadataProvider) {
- log.debug("PVP2X message validation FAILED. Reload metadata for entityID: "
- + messageContext.getInboundMessageIssuer());
- if (!((IRefreshableMetadataProvider) metadataProvider)
- .refreshMetadataProvider(messageContext.getInboundMessageIssuer())) {
- throw e;
- } else {
- log.trace("PVP2X metadata reload finished. Check validate message again.");
- decode.decode(messageContext);
+ //inject informations into message context that are required for further processing
+ injectInboundMessageContexts(messageContext, metadataProvider);
+
+ log.trace("Signature validation on binding-level starts ... ");
+ final PvpSamlMessageHandlerChain messageValidatorChain = new PvpSamlMessageHandlerChain();
+ final SAML2HTTPRedirectDeflateSignatureSecurityHandler redirectBindingSignaturHandler =
+ new SAML2HTTPRedirectDeflateSignatureSecurityHandler();
+ redirectBindingSignaturHandler.setHttpServletRequest(req);
+
+ messageValidatorChain.addHandler(new CheckMessageVersionHandler());
+ messageValidatorChain.addHandler(redirectBindingSignaturHandler);
+ messageValidatorChain.addHandler(new MessageLifetimeSecurityHandler());
+
+
+ /*TODO: maybe we add it in a later version
+ * Because:
+ * - AuthnRequest replay should not be a problem on IDP side
+ * - Response replay will be not possible, because EAAF PVP implements
+ * countermeasure based on one-time tokens for each request
+ *
+ */
+ //final MessageReplaySecurityHandler replaySecurityHandler = new MessageReplaySecurityHandler();
+ //final StorageService replayCacheStorage = null;
+ //final ReplayCache replayCache = new ReplayCache();
+ //replayCache.setId("Message replay cache");
+ //replayCache.setStrict(true);
+ //replayCache.setStorage(replayCacheStorage);
+ //replaySecurityHandler.setReplayCache(replayCache );
+ //messageValidatorChain.addHandler(replaySecurityHandler);
- // check signature
- signatureRule.evaluate(messageContext);
- }
- log.trace("Second PVP2X message validation finished");
+ try {
+ messageValidatorChain.initialize();
+ messageValidatorChain.invoke(messageContext);
- } else {
- throw e;
+ } catch (final ComponentInitializationException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
- }
+ } catch (final MessageHandlerException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
}
InboundMessage msg = null;
- if (messageContext.getInboundMessage() instanceof RequestAbstractType) {
+
+ if (messageContext.getMessage() instanceof RequestAbstractType) {
final RequestAbstractType inboundMessage =
- (RequestAbstractType) messageContext.getInboundMessage();
+ (RequestAbstractType) messageContext.getMessage();
msg = new PvpSProfileRequest(inboundMessage, getSaml2BindingName());
+ msg.setEntityID(inboundMessage.getIssuer().getValue());
- } else if (messageContext.getInboundMessage() instanceof StatusResponseType) {
+ } else if (messageContext.getMessage() instanceof StatusResponseType) {
final StatusResponseType inboundMessage =
- (StatusResponseType) messageContext.getInboundMessage();
+ (StatusResponseType) messageContext.getMessage();
msg = new PvpSProfileResponse(inboundMessage);
+ msg.setEntityID(inboundMessage.getIssuer().getValue());
} else {
// create empty container if request type is unknown
msg = new InboundMessage();
- }
- if (messageContext.getPeerEntityMetadata() != null) {
- msg.setEntityID(messageContext.getPeerEntityMetadata().getEntityID());
- } else {
- log.info(
- "No Metadata found for OA with EntityID " + messageContext.getInboundMessageIssuer());
}
- msg.setVerified(true);
- msg.setRelayState(messageContext.getRelayState());
+ msg.setVerified(false);
+ msg.setRelayState(SAMLBindingSupport.getRelayState(messageContext));
return msg;
+
+// final BasicSAMLMessageContext<SAMLObject, ?, ?> messageContext =
+// new BasicSAMLMessageContext<>();
+// messageContext.setInboundMessageTransport(new HttpServletRequestAdapter(req));
+//
+// // set metadata descriptor type
+// if (isSpEndPoint) {
+// messageContext.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME);
+// decode.setURIComparator(comparator);
+//
+// } else {
+// messageContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
+// decode.setURIComparator(comparator);
+// }
+//
+// messageContext.setMetadataProvider(metadataProvider);
+//
+// final SAML2HTTPRedirectDeflateSignatureRule signatureRule =
+// new SAML2HTTPRedirectDeflateSignatureRule(
+// TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider));
+// final PvpAuthRequestSignedRole signedRole = new PvpAuthRequestSignedRole();
+// final BasicSecurityPolicy policy = new BasicSecurityPolicy();
+// policy.getPolicyRules().add(signedRole);
+// policy.getPolicyRules().add(signatureRule);
+// final SecurityPolicyResolver resolver = new StaticSecurityPolicyResolver(policy);
+// messageContext.setSecurityPolicyResolver(resolver);
+//
+// // set metadata descriptor type
+// if (isSpEndPoint) {
+// messageContext.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME);
+// } else {
+// messageContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
+// }
+//
+// SAML2AuthnRequestsSignedSecurityHandler
+//
+// try {
+// decode.decode(messageContext);
+//
+// // check signature
+// signatureRule.evaluate(messageContext);
+//
+// } catch (final SecurityException e) {
+// if (StringUtils.isEmpty(messageContext.getInboundMessageIssuer())) {
+// throw e;
+//
+// }
+//
+// if (metadataProvider instanceof IRefreshableMetadataProvider) {
+// log.debug("PVP2X message validation FAILED. Reload metadata for entityID: "
+// + messageContext.getInboundMessageIssuer());
+// if (!((IRefreshableMetadataProvider) metadataProvider)
+// .refreshMetadataProvider(messageContext.getInboundMessageIssuer())) {
+// throw e;
+// } else {
+// log.trace("PVP2X metadata reload finished. Check validate message again.");
+// decode.decode(messageContext);
+//
+// // check signature
+// signatureRule.evaluate(messageContext);
+//
+// }
+// log.trace("Second PVP2X message validation finished");
+//
+// } else {
+// throw e;
+//
+// }
+// }
+//
+// InboundMessage msg = null;
+// if (messageContext.getInboundMessage() instanceof RequestAbstractType) {
+// final RequestAbstractType inboundMessage =
+// (RequestAbstractType) messageContext.getInboundMessage();
+// msg = new PvpSProfileRequest(inboundMessage, getSaml2BindingName());
+//
+// } else if (messageContext.getInboundMessage() instanceof StatusResponseType) {
+// final StatusResponseType inboundMessage =
+// (StatusResponseType) messageContext.getInboundMessage();
+// msg = new PvpSProfileResponse(inboundMessage);
+//
+// } else {
+// // create empty container if request type is unknown
+// msg = new InboundMessage();
+// }
+//
+// if (messageContext.getPeerEntityMetadata() != null) {
+// msg.setEntityID(messageContext.getPeerEntityMetadata().getEntityID());
+// } else {
+// log.info(
+// "No Metadata found for OA with EntityID " + messageContext.getInboundMessageIssuer());
+// }
+//
+// msg.setVerified(true);
+// msg.setRelayState(messageContext.getRelayState());
+//
+// return msg;
}
@Override
public boolean handleDecode(final String action, final HttpServletRequest req) {
- return action.equals(PvpConstants.REDIRECT) || action.equals(PvpConstants.SINGLELOGOUT)
+ return (action.equals(PvpConstants.REDIRECT) || action.equals(PvpConstants.SINGLELOGOUT))
&& req.getMethod().equals("GET");
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/SoapBinding.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/SoapBinding.java
index 04266d37..e0df2d2a 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/SoapBinding.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/SoapBinding.java
@@ -19,8 +19,6 @@
package at.gv.egiz.eaaf.modules.pvp2.impl.binding;
-import java.util.List;
-
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -28,99 +26,105 @@ import at.gv.egiz.eaaf.core.api.IRequest;
import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
import at.gv.egiz.eaaf.modules.pvp2.api.binding.IDecoder;
import at.gv.egiz.eaaf.modules.pvp2.api.binding.IEncoder;
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
import at.gv.egiz.eaaf.modules.pvp2.exception.AttributQueryException;
import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
-import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileRequest;
-import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafDefaultSaml2Bootstrap;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SamlBindingException;
+import at.gv.egiz.eaaf.modules.pvp2.impl.verification.EaafMessageContextInitializationHandler;
+import at.gv.egiz.eaaf.modules.pvp2.impl.verification.PvpSamlMessageHandlerChain;
-import org.apache.commons.lang3.StringUtils;
-import org.opensaml.common.binding.BasicSAMLMessageContext;
+import org.opensaml.messaging.context.MessageContext;
import org.opensaml.messaging.decoder.MessageDecodingException;
-import org.opensaml.messaging.encoder.MessageEncodingException;
import org.opensaml.saml.common.SAMLObject;
+import org.opensaml.saml.common.binding.SAMLBindingSupport;
+import org.opensaml.saml.common.binding.impl.CheckMessageVersionHandler;
+import org.opensaml.saml.common.binding.impl.SAMLProtocolAndRoleHandler;
+import org.opensaml.saml.common.binding.impl.SAMLSOAPDecoderBodyHandler;
+import org.opensaml.saml.common.binding.security.impl.MessageLifetimeSecurityHandler;
+import org.opensaml.saml.common.binding.security.impl.SAMLProtocolMessageXMLSignatureSecurityHandler;
+import org.opensaml.saml.common.messaging.SAMLMessageSecuritySupport;
import org.opensaml.saml.common.xml.SAMLConstants;
import org.opensaml.saml.saml2.binding.decoding.impl.HTTPSOAP11Decoder;
+import org.opensaml.saml.saml2.binding.encoding.impl.HTTPSOAP11Encoder;
import org.opensaml.saml.saml2.core.RequestAbstractType;
import org.opensaml.saml.saml2.core.StatusResponseType;
-import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
-import org.opensaml.saml2.metadata.provider.MetadataProvider;
-import org.opensaml.security.credential.Credential;
-import org.opensaml.soap.soap11.Envelope;
-import org.opensaml.ws.transport.http.HttpServletRequestAdapter;
-import org.opensaml.ws.transport.http.HttpServletResponseAdapter;
-import org.opensaml.xmlsec.signature.SignableXMLObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Service;
+import lombok.extern.slf4j.Slf4j;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
import net.shibboleth.utilities.java.support.net.URIComparator;
-import net.shibboleth.utilities.java.support.xml.BasicParserPool;
-
-@Service("PVPSOAPBinding")
-public class SoapBinding implements IDecoder, IEncoder {
- private static final Logger log = LoggerFactory.getLogger(SoapBinding.class);
+@Slf4j
+public class SoapBinding extends AbstractBinding implements IDecoder, IEncoder {
@Override
public InboundMessageInterface decode(final HttpServletRequest req,
- final HttpServletResponse resp, final MetadataProvider metadataProvider,
+ final HttpServletResponse resp, final IPvp2MetadataProvider metadataProvider,
final boolean isSpEndPoint, final URIComparator comparator)
- throws MessageDecodingException, SecurityException, Pvp2Exception {
- final HTTPSOAP11Decoder soapDecoder = new HTTPSOAP11Decoder(new BasicParserPool());
- final BasicSAMLMessageContext<SAMLObject, ?, ?> messageContext =
- new BasicSAMLMessageContext<>();
- messageContext.setInboundMessageTransport(new HttpServletRequestAdapter(req));
- messageContext.setMetadataProvider(metadataProvider);
-
- // TODO: update in a futher version:
- // requires a special SignedSOAPRequestPolicyRole because
- // messageContext.getInboundMessage() is not directly signed
-
- // set security context
- // BasicSecurityPolicy policy = new BasicSecurityPolicy();
- // policy.getPolicyRules().add(
- // new MOAPVPSignedRequestPolicyRule(
- // TrustEngineFactory.getSignatureKnownKeysTrustEngine(),
- // SPSSODescriptor.DEFAULT_ELEMENT_NAME));
- // SecurityPolicyResolver resolver = new StaticSecurityPolicyResolver(
- // policy);
- // messageContext.setSecurityPolicyResolver(resolver);
-
- // decode message
- soapDecoder.decode(messageContext);
-
- final Envelope inboundMessage = (Envelope) messageContext.getInboundMessage();
-
- if (inboundMessage.getBody() != null) {
- final List<XMLObject> xmlElemList = inboundMessage.getBody().getUnknownXMLObjects();
-
- if (!xmlElemList.isEmpty()) {
- final SignableXMLObject attrReq = (SignableXMLObject) xmlElemList.get(0);
- final PvpSProfileRequest request = new PvpSProfileRequest(attrReq, getSaml2BindingName());
-
- if (messageContext.getPeerEntityMetadata() != null) {
- request.setEntityID(messageContext.getPeerEntityMetadata().getEntityID());
- } else if (attrReq instanceof RequestAbstractType) {
- final RequestAbstractType attributeRequest = (RequestAbstractType) attrReq;
- try {
- if (StringUtils.isNotEmpty(attributeRequest.getIssuer().getValue())
- && metadataProvider.getRole(attributeRequest.getIssuer().getValue(),
- SPSSODescriptor.DEFAULT_ELEMENT_NAME) != null) {
- request.setEntityID(attributeRequest.getIssuer().getValue());
- }
-
- } catch (final Exception e) {
- log.warn("No Metadata found with EntityID " + attributeRequest.getIssuer().getValue());
- }
- }
-
- request.setVerified(false);
- return request;
-
- }
+ throws Pvp2Exception {
+
+ try {
+ final HTTPSOAP11Decoder soapDecoder = new HTTPSOAP11Decoder();
+
+ final PvpSamlMessageHandlerChain messageValidatorChain = new PvpSamlMessageHandlerChain();
+ soapDecoder.setBodyHandler(messageValidatorChain);
+
+ final SAMLProtocolMessageXMLSignatureSecurityHandler msgSignatureValidationHandler =
+ new SAMLProtocolMessageXMLSignatureSecurityHandler();
+
+ messageValidatorChain.addHandler(new EaafMessageContextInitializationHandler());
+ messageValidatorChain.addHandler(new CheckMessageVersionHandler());
+ messageValidatorChain.addHandler(new SAMLProtocolAndRoleHandler());
+ messageValidatorChain.addHandler(msgSignatureValidationHandler);
+ messageValidatorChain.addHandler(new MessageLifetimeSecurityHandler());
+ messageValidatorChain.addHandler(new SAMLSOAPDecoderBodyHandler());
+
+ // decode message
+ soapDecoder.initialize();
+ soapDecoder.decode();
+
+ final MessageContext<SAMLObject> messageContext = soapDecoder.getMessageContext();
+ messageContext.getMessage();
+
+ } catch (MessageDecodingException | ComponentInitializationException e) {
+ throw new SamlBindingException("internal.pvp.95",
+ new Object[] { PvpConstants.POST, "decoding", e.getMessage() },
+ e);
}
+// final Envelope inboundMessage = (Envelope) messageContext.getMessage();
+//
+// if (inboundMessage.getBody() != null) {
+// final List<XMLObject> xmlElemList = inboundMessage.getBody().getUnknownXMLObjects();
+//
+// if (!xmlElemList.isEmpty()) {
+// final SignableXMLObject attrReq = (SignableXMLObject) xmlElemList.get(0);
+// final PvpSProfileRequest request = new PvpSProfileRequest(attrReq, getSaml2BindingName());
+//
+// if (messageContext.getPeerEntityMetadata() != null) {
+// request.setEntityID(messageContext.getPeerEntityMetadata().getEntityID());
+//
+// } else if (attrReq instanceof RequestAbstractType) {
+// final RequestAbstractType attributeRequest = (RequestAbstractType) attrReq;
+// try {
+// if (StringUtils.isNotEmpty(attributeRequest.getIssuer().getValue())
+// && metadataProvider.getRole(attributeRequest.getIssuer().getValue(),
+// SPSSODescriptor.DEFAULT_ELEMENT_NAME) != null) {
+// request.setEntityID(attributeRequest.getIssuer().getValue());
+// }
+//
+// } catch (final Exception e) {
+// log.warn("No Metadata found with EntityID " + attributeRequest.getIssuer().getValue());
+// }
+// }
+//
+// request.setVerified(false);
+// return request;
+//
+// }
+// }
+
log.error("Receive empty PVP 2.1 attributequery request.");
throw new AttributQueryException("Receive empty PVP 2.1 attributequery request.", null);
}
@@ -134,30 +138,47 @@ public class SoapBinding implements IDecoder, IEncoder {
@Override
public void encodeRequest(final HttpServletRequest req, final HttpServletResponse resp,
final RequestAbstractType request, final String targetLocation, final String relayState,
- final Credential credentials, final IRequest pendingReq)
- throws MessageEncodingException, SecurityException, Pvp2Exception {
+ final EaafX509Credential credentials, final IRequest pendingReq)
+ throws Pvp2Exception {
+ throw new RuntimeException("Method not supported!!!");
}
@Override
- public void encodeRespone(final HttpServletRequest req, final HttpServletResponse resp,
+ public void encodeResponse(final HttpServletRequest req, final HttpServletResponse resp,
final StatusResponseType response, final String targetLocation, final String relayState,
- final Credential credentials, final IRequest pendingReq)
- throws MessageEncodingException, SecurityException, Pvp2Exception {
+ final EaafX509Credential credentials, final IRequest pendingReq)
+ throws Pvp2Exception {
+
+ try {
+ final HTTPSOAP11Encoder encoder = new HTTPSOAP11Encoder();
+ encoder.setHttpServletResponse(resp);
+
+ // inject message context
+ final MessageContext<SAMLObject> messageContext = buildBasicMessageContext(encoder, response);
- // load default PVP security configurations
- EaafDefaultSaml2Bootstrap.initializeDefaultPvpConfiguration();
+ // inject signing context
+ messageContext.addSubcontext(injectSigningInfos(credentials));
- final HTTPSOAP11Encoder encoder = new HTTPSOAP11Encoder();
- final HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter(resp, true);
- final BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context =
- new BasicSAMLMessageContext<>();
- context.setOutboundSAMLMessageSigningCredential(credentials);
- context.setOutboundSAMLMessage(response);
- context.setOutboundMessageTransport(responseAdapter);
+ // set endpoint url
+ messageContext.addSubcontext(injectEndpointInfos(response, targetLocation));
- encoder.encode(context);
+ // set relayState of exists
+ SAMLBindingSupport.setRelayState(messageContext, relayState);
+ // sign SAML2 message
+ SAMLMessageSecuritySupport.signMessage(messageContext);
+
+ // encode message
+ encoder.initialize();
+ encoder.encode();
+ } catch (final Exception e) {
+ log.warn("Can not encode SAML2 SOAP-Binding response", e);
+ throw new SamlBindingException("internal.pvp.95",
+ new Object[] { PvpConstants.SOAP, "encoding", e.getMessage() },
+ e);
+
+ }
}
@Override
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/CitizenTokenBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/CitizenTokenBuilder.java
index 0bfd974e..1667a07d 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/CitizenTokenBuilder.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/CitizenTokenBuilder.java
@@ -21,8 +21,8 @@ package at.gv.egiz.eaaf.modules.pvp2.impl.builder;
import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
-import org.opensaml.core.config.Configuration;
import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
import org.opensaml.core.xml.schema.XSInteger;
import org.opensaml.core.xml.schema.XSString;
import org.opensaml.core.xml.schema.impl.XSIntegerBuilder;
@@ -46,7 +46,7 @@ public class CitizenTokenBuilder {
*/
public static XMLObject buildAttributeStringValue(final String value) {
final XSStringBuilder stringBuilder =
- (XSStringBuilder) Configuration.getBuilderFactory().getBuilder(XSString.TYPE_NAME);
+ (XSStringBuilder) XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(XSString.TYPE_NAME);
final XSString stringValue =
stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME);
stringValue.setValue(value);
@@ -61,7 +61,7 @@ public class CitizenTokenBuilder {
*/
public static XMLObject buildAttributeIntegerValue(final int value) {
final XSIntegerBuilder integerBuilder =
- (XSIntegerBuilder) Configuration.getBuilderFactory().getBuilder(XSInteger.TYPE_NAME);
+ (XSIntegerBuilder) XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(XSInteger.TYPE_NAME);
final XSInteger integerValue =
integerBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSInteger.TYPE_NAME);
integerValue.setValue(value);
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PvpMetadataBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PvpMetadataBuilder.java
index 9645c2c8..42f69a57 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PvpMetadataBuilder.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PvpMetadataBuilder.java
@@ -36,13 +36,13 @@ import javax.xml.transform.stream.StreamResult;
import at.gv.egiz.eaaf.core.exceptions.EaafException;
import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration;
-import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafDefaultSaml2Bootstrap;
import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider;
import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
import org.apache.commons.httpclient.auth.CredentialsNotAvailableException;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
import org.opensaml.core.xml.io.Marshaller;
import org.opensaml.core.xml.io.MarshallingException;
import org.opensaml.saml.common.xml.SAMLConstants;
@@ -176,12 +176,11 @@ public class PvpMetadataBuilder {
entitiesDescriptor.getEntityDescriptors().add(entityDescriptor);
// load default PVP security configurations
- EaafDefaultSaml2Bootstrap.initializeDefaultPvpConfiguration();
entitiesDescriptor.setSignature(signature);
// marshall document
final Marshaller out =
- org.opensaml.xml.Configuration.getMarshallerFactory().getMarshaller(entitiesDescriptor);
+ XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(entitiesDescriptor);
out.marshall(entitiesDescriptor, document);
} else {
@@ -192,7 +191,7 @@ public class PvpMetadataBuilder {
// marshall document
final Marshaller out =
- org.opensaml.xml.Configuration.getMarshallerFactory().getMarshaller(entityDescriptor);
+ XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(entityDescriptor);
out.marshall(entityDescriptor, document);
}
@@ -335,7 +334,8 @@ public class PvpMetadataBuilder {
attributeService.setIndex(0);
attributeService.setIsDefault(true);
final ServiceName serviceName = Saml2Utils.createSamlObject(ServiceName.class);
- serviceName.setName(new LocalizedString("Default Service", "en"));
+ serviceName.setValue("Default Service");
+ serviceName.setXMLLang("en");
attributeService.getNames().add(serviceName);
if (reqSpAttr != null && reqSpAttr.size() > 0) {
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/SamlAttributeGenerator.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/SamlAttributeGenerator.java
index 0499cffa..d37d6724 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/SamlAttributeGenerator.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/SamlAttributeGenerator.java
@@ -22,8 +22,8 @@ package at.gv.egiz.eaaf.modules.pvp2.impl.builder;
import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator;
import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
-import org.opensaml.core.config.Configuration;
import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
import org.opensaml.core.xml.schema.XSInteger;
import org.opensaml.core.xml.schema.XSString;
import org.opensaml.core.xml.schema.impl.XSIntegerBuilder;
@@ -35,7 +35,7 @@ public class SamlAttributeGenerator implements IAttributeGenerator<Attribute> {
private XMLObject buildAttributeStringValue(final String value) {
final XSStringBuilder stringBuilder =
- (XSStringBuilder) Configuration.getBuilderFactory().getBuilder(XSString.TYPE_NAME);
+ (XSStringBuilder) XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(XSString.TYPE_NAME);
final XSString stringValue =
stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME);
stringValue.setValue(value);
@@ -44,7 +44,7 @@ public class SamlAttributeGenerator implements IAttributeGenerator<Attribute> {
private XMLObject buildAttributeIntegerValue(final int value) {
final XSIntegerBuilder integerBuilder =
- (XSIntegerBuilder) Configuration.getBuilderFactory().getBuilder(XSInteger.TYPE_NAME);
+ (XSIntegerBuilder) XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(XSInteger.TYPE_NAME);
final XSInteger integerValue =
integerBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSInteger.TYPE_NAME);
integerValue.setValue(value);
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafExtensionImplementation.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafExtensionImplementation.java
index e61f5e6e..726a2960 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafExtensionImplementation.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafExtensionImplementation.java
@@ -19,7 +19,7 @@
package at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr;
-import org.opensaml.saml2.common.impl.ExtensionsImpl;
+import org.opensaml.saml.saml2.core.impl.ExtensionsImpl;
public class EaafExtensionImplementation extends ExtensionsImpl {
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestExtensionBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestExtensionBuilder.java
index 25cbc6ef..c77193fd 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestExtensionBuilder.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestExtensionBuilder.java
@@ -19,15 +19,15 @@
package at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr;
-import org.opensaml.common.impl.AbstractSAMLObjectBuilder;
-import org.opensaml.common.xml.SAMLConstants;
-import org.opensaml.saml2.common.Extensions;
+import org.opensaml.saml.common.AbstractSAMLObjectBuilder;
+import org.opensaml.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.saml2.core.Extensions;
public class EaafRequestExtensionBuilder extends AbstractSAMLObjectBuilder<Extensions> {
@Override
public Extensions buildObject() {
- return buildObject(SAMLConstants.SAML20P_NS, Extensions.LOCAL_NAME,
+ return buildObject(SAMLConstants.SAML20P_NS, Extensions.DEFAULT_ELEMENT_LOCAL_NAME,
SAMLConstants.SAML20P_PREFIX);
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeBuilder.java
index 81d8d192..fde79998 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeBuilder.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeBuilder.java
@@ -19,11 +19,11 @@
package at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr;
-import org.opensaml.common.impl.AbstractSAMLObjectBuilder;
-
import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute;
import at.gv.egiz.eaaf.modules.pvp2.impl.reqattr.EaafRequestedAttributeImpl;
+import org.opensaml.saml.common.AbstractSAMLObjectBuilder;
+
public class EaafRequestedAttributeBuilder
extends AbstractSAMLObjectBuilder<EaafRequestedAttribute> {
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeMarshaller.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeMarshaller.java
index 749310f2..4acee141 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeMarshaller.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeMarshaller.java
@@ -23,14 +23,16 @@ import java.util.Map.Entry;
import javax.xml.namespace.QName;
-import org.opensaml.common.impl.AbstractSAMLObjectMarshaller;
-import org.opensaml.xml.XMLObject;
-import org.opensaml.xml.io.MarshallingException;
-import org.opensaml.xml.util.XMLHelper;
+import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute;
+
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.saml.common.AbstractSAMLObjectMarshaller;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
-import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute;
+import net.shibboleth.utilities.java.support.xml.AttributeSupport;
public class EaafRequestedAttributeMarshaller extends AbstractSAMLObjectMarshaller {
@Override
@@ -60,10 +62,11 @@ public class EaafRequestedAttributeMarshaller extends AbstractSAMLObjectMarshall
Attr attr;
for (final Entry<QName, String> entry : requestedAttr.getUnknownAttributes().entrySet()) {
- attr = XMLHelper.constructAttribute(domElement.getOwnerDocument(), entry.getKey());
+
+ attr = AttributeSupport.constructAttribute(domElement.getOwnerDocument(), entry.getKey());
attr.setValue(entry.getValue());
domElement.setAttributeNodeNS(attr);
- if (org.opensaml.xml.Configuration.isIDAttribute(entry.getKey())
+ if (XMLObjectProviderRegistrySupport.isIDAttribute(entry.getKey())
|| requestedAttr.getUnknownAttributes().isIDAttribute(entry.getKey())) {
attr.getOwnerElement().setIdAttributeNode(attr, true);
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeUnmarshaller.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeUnmarshaller.java
index 35532e77..5313f340 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeUnmarshaller.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeUnmarshaller.java
@@ -21,15 +21,16 @@ package at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr;
import javax.xml.namespace.QName;
-import org.opensaml.common.impl.AbstractSAMLObjectUnmarshaller;
-import org.opensaml.xml.XMLObject;
-import org.opensaml.xml.io.UnmarshallingException;
-import org.opensaml.xml.util.XMLHelper;
-import org.w3c.dom.Attr;
-
import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.saml.common.AbstractSAMLObjectUnmarshaller;
+import org.w3c.dom.Attr;
+
+import net.shibboleth.utilities.java.support.xml.QNameSupport;
+
public class EaafRequestedAttributeUnmarshaller extends AbstractSAMLObjectUnmarshaller {
@Override
protected final void processChildElement(final XMLObject parentSamlObject,
@@ -64,7 +65,7 @@ public class EaafRequestedAttributeUnmarshaller extends AbstractSAMLObjectUnmars
requestedAttr.setIsRequired(attribute.getValue());
} else {
- final QName attribQName = XMLHelper.getNodeQName(attribute);
+ final QName attribQName = QNameSupport.getNodeQName(attribute);
if (attribute.isId()) {
requestedAttr.getUnknownAttributes().registerID(attribQName);
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesBuilder.java
index db08f87f..2d2de292 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesBuilder.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesBuilder.java
@@ -19,11 +19,11 @@
package at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr;
-import org.opensaml.common.impl.AbstractSAMLObjectBuilder;
-
import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttributes;
import at.gv.egiz.eaaf.modules.pvp2.impl.reqattr.EaafRequestedAttributesImpl;
+import org.opensaml.saml.common.AbstractSAMLObjectBuilder;
+
public class EaafRequestedAttributesBuilder
extends AbstractSAMLObjectBuilder<EaafRequestedAttributes> {
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesMarshaller.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesMarshaller.java
index 8aa70e5a..5d1e0679 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesMarshaller.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesMarshaller.java
@@ -19,7 +19,7 @@
package at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr;
-import org.opensaml.common.impl.AbstractSAMLObjectMarshaller;
+import org.opensaml.saml.common.AbstractSAMLObjectMarshaller;
public class EaafRequestedAttributesMarshaller extends AbstractSAMLObjectMarshaller {
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesUnmarshaller.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesUnmarshaller.java
index f616bbb0..9934c502 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesUnmarshaller.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesUnmarshaller.java
@@ -19,13 +19,13 @@
package at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr;
-import org.opensaml.common.impl.AbstractSAMLObjectUnmarshaller;
-import org.opensaml.xml.XMLObject;
-import org.opensaml.xml.io.UnmarshallingException;
-
import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute;
import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttributes;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.saml.common.AbstractSAMLObjectUnmarshaller;
+
public class EaafRequestedAttributesUnmarshaller extends AbstractSAMLObjectUnmarshaller {
@Override
protected final void processChildElement(final XMLObject parentObject,
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/logging/PvpModuleMessageSource.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/logging/PvpModuleMessageSource.java
new file mode 100644
index 00000000..961f29cb
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/logging/PvpModuleMessageSource.java
@@ -0,0 +1,17 @@
+package at.gv.egiz.eaaf.modules.pvp2.impl.logging;
+
+import java.util.Arrays;
+import java.util.List;
+
+import at.gv.egiz.eaaf.core.api.logging.IMessageSourceLocation;
+
+
+public class PvpModuleMessageSource implements IMessageSourceLocation {
+
+ @Override
+ public List<String> getMessageSourceLocation() {
+ return Arrays.asList("classpath:messages/pvp_messages");
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/InboundMessage.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/InboundMessage.java
index 002db86f..8a741b69 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/InboundMessage.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/InboundMessage.java
@@ -25,18 +25,18 @@ import java.io.Serializable;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
-import org.opensaml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml2.metadata.provider.MetadataProviderException;
+import at.gv.egiz.eaaf.core.impl.utils.DomUtils;
+import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.exception.NoMetadataInformationException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException;
+
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
-import at.gv.egiz.eaaf.core.impl.utils.DomUtils;
-import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface;
-import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataProvider;
-import at.gv.egiz.eaaf.modules.pvp2.exception.NoMetadataInformationException;
-
public class InboundMessage implements InboundMessageInterface, Serializable {
private static final Logger log = LoggerFactory.getLogger(InboundMessage.class);
@@ -56,7 +56,7 @@ public class InboundMessage implements InboundMessageInterface, Serializable {
* @return EntityDescriptor from metadata
* @throws NoMetadataInformationException In case of an error
*/
- public EntityDescriptor getEntityMetadata(final IPvpMetadataProvider metadataProvider)
+ public EntityDescriptor getEntityMetadata(final IPvp2MetadataProvider metadataProvider)
throws NoMetadataInformationException {
try {
if (metadataProvider == null) {
@@ -65,7 +65,7 @@ public class InboundMessage implements InboundMessageInterface, Serializable {
return metadataProvider.getEntityDescriptor(this.entityID);
- } catch (final MetadataProviderException e) {
+ } catch (final Pvp2MetadataException e) {
log.warn("No Metadata for EntitiyID " + entityID);
throw new NoMetadataInformationException();
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PvpSProfileRequest.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PvpSProfileRequest.java
index 8a2cce3e..c6068769 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PvpSProfileRequest.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PvpSProfileRequest.java
@@ -19,10 +19,11 @@
package at.gv.egiz.eaaf.modules.pvp2.impl.message;
-import org.opensaml.xml.io.Unmarshaller;
-import org.opensaml.xml.io.UnmarshallerFactory;
-import org.opensaml.xml.io.UnmarshallingException;
-import org.opensaml.xml.signature.SignableXMLObject;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.io.Unmarshaller;
+import org.opensaml.core.xml.io.UnmarshallerFactory;
+import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.xmlsec.signature.SignableXMLObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -56,7 +57,7 @@ public class PvpSProfileRequest extends InboundMessage {
*/
public SignableXMLObject getSamlRequest() {
final UnmarshallerFactory unmarshallerFactory =
- org.opensaml.xml.Configuration.getUnmarshallerFactory();
+ XMLObjectProviderRegistrySupport.getUnmarshallerFactory();
final Unmarshaller unmashaller = unmarshallerFactory.getUnmarshaller(getInboundMessage());
try {
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PvpSProfileResponse.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PvpSProfileResponse.java
index 8d1cbe8c..4ad21fbc 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PvpSProfileResponse.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PvpSProfileResponse.java
@@ -19,10 +19,11 @@
package at.gv.egiz.eaaf.modules.pvp2.impl.message;
-import org.opensaml.saml2.core.StatusResponseType;
-import org.opensaml.xml.io.Unmarshaller;
-import org.opensaml.xml.io.UnmarshallerFactory;
-import org.opensaml.xml.io.UnmarshallingException;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.io.Unmarshaller;
+import org.opensaml.core.xml.io.UnmarshallerFactory;
+import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.saml.saml2.core.StatusResponseType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -43,7 +44,7 @@ public class PvpSProfileResponse extends InboundMessage {
*/
public StatusResponseType getResponse() {
final UnmarshallerFactory unmarshallerFactory =
- org.opensaml.xml.Configuration.getUnmarshallerFactory();
+ XMLObjectProviderRegistrySupport.getUnmarshallerFactory();
final Unmarshaller unmashaller = unmarshallerFactory.getUnmarshaller(getInboundMessage());
try {
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/AbstractChainingMetadataProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/AbstractChainingMetadataProvider.java
index 4a9bb89a..ec59b1df 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/AbstractChainingMetadataProvider.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/AbstractChainingMetadataProvider.java
@@ -21,48 +21,59 @@ package at.gv.egiz.eaaf.modules.pvp2.impl.metadata;
import java.io.IOException;
import java.security.cert.CertificateException;
-import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Timer;
+import java.util.UUID;
+import javax.annotation.Nonnull;
+import javax.naming.ConfigurationException;
import javax.xml.namespace.QName;
-import org.apache.commons.lang3.StringUtils;
-import org.opensaml.saml2.metadata.EntitiesDescriptor;
-import org.opensaml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml2.metadata.RoleDescriptor;
-import org.opensaml.saml2.metadata.provider.ChainingMetadataProvider;
-import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider;
-import org.opensaml.saml2.metadata.provider.MetadataFilter;
-import org.opensaml.saml2.metadata.provider.MetadataProvider;
-import org.opensaml.saml2.metadata.provider.MetadataProviderException;
-import org.opensaml.saml2.metadata.provider.ObservableMetadataProvider;
-import org.opensaml.xml.XMLObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import at.gv.egiz.components.spring.api.IDestroyableObject;
import at.gv.egiz.eaaf.core.api.IGarbageCollectorProcessing;
import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;
-import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider;
-public abstract class AbstractChainingMetadataProvider extends SimpleMetadataProvider
- implements ObservableMetadataProvider, IGarbageCollectorProcessing,
- IRefreshableMetadataProvider, IDestroyableObject, IPvpMetadataProvider {
+import org.apache.commons.lang3.StringUtils;
+import org.opensaml.core.criterion.EntityIdCriterion;
+import org.opensaml.saml.metadata.resolver.ClearableMetadataResolver;
+import org.opensaml.saml.metadata.resolver.MetadataResolver;
+import org.opensaml.saml.metadata.resolver.RefreshableMetadataResolver;
+import org.opensaml.saml.metadata.resolver.filter.MetadataFilter;
+import org.opensaml.saml.metadata.resolver.impl.AbstractMetadataResolver;
+import org.opensaml.saml.saml2.metadata.EntitiesDescriptor;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml.saml2.metadata.RoleDescriptor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.component.IdentifiedComponent;
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+import net.shibboleth.utilities.java.support.resolver.ResolverException;
+
+public abstract class AbstractChainingMetadataProvider extends SimpleMetadataResolver
+ implements IGarbageCollectorProcessing, IRefreshableMetadataProvider, IDestroyableObject, IPvp2MetadataProvider,
+ RefreshableMetadataResolver, ClearableMetadataResolver {
private static final Logger log = LoggerFactory.getLogger(AbstractChainingMetadataProvider.class);
- private MetadataProvider internalProvider = null;
+ @Nonnull @NonnullElements private final List<MetadataResolver> internalResolvers;
private static Object mutex = new Object();
private Timer timer = null;
+ /**
+ * Build a chaining metadata resolver that requires valid metadata.
+ *
+ */
public AbstractChainingMetadataProvider() {
- internalProvider = new ChainingMetadataProvider();
+ internalResolvers = Collections.synchronizedList(Collections.emptyList());
}
@@ -102,30 +113,34 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataPro
}
+
+
@Override
- public synchronized boolean refreshMetadataProvider(final String entityID) {
+ public synchronized boolean refreshMetadataProvider(final String entityId) {
try {
// check if metadata provider is already loaded
try {
- if (internalProvider.getEntityDescriptor(entityID) != null) {
+ if (resolveEntityDescripor(entityId) != null) {
return true;
+
}
- } catch (final MetadataProviderException e) {
- log.debug("Metadata for EntityId: {} is not valid. Starting refresh ... ", entityID);
+ } catch (final ResolverException e) {
+ log.debug("Metadata for EntityId: {} is not valid. Starting refresh ... ", entityId);
}
// reload metadata provider
- final String metadataUrl = getMetadataUrl(entityID);
+ final String metadataUrl = getMetadataUrl(entityId);
if (StringUtils.isNotEmpty(metadataUrl)) {
- final Map<String, HTTPMetadataProvider> actuallyLoadedProviders =
- getAllActuallyLoadedProviders();
+ final Map<String, MetadataResolver> actuallyLoadedResolver =
+ getAllActuallyLoadedResolvers();
// check if MetadataProvider is actually loaded
- if (actuallyLoadedProviders.containsKey(metadataUrl)) {
- actuallyLoadedProviders.get(metadataUrl).refresh();
- log.info("SAML2 metadata for service provider: " + entityID + " is refreshed.");
+ final MetadataResolver loadedResover = actuallyLoadedResolver.get(metadataUrl);
+ if (loadedResover instanceof RefreshableMetadataResolver) {
+ ((RefreshableMetadataResolver)loadedResover).refresh();
+ log.info("SAML2 metadata for service provider: " + entityId + " is refreshed.");
return true;
} else {
@@ -134,32 +149,20 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataPro
timer = new Timer(true);
}
- final ChainingMetadataProvider chainProvider =
- (ChainingMetadataProvider) internalProvider;
- chainProvider.addMetadataProvider(createNewMetadataProvider(entityID));
+ internalResolvers.add(createNewMetadataProvider(metadataUrl));
- emitChangeEvent();
- log.info("SAML2 metadata for service provider: " + entityID + " is added.");
+ log.info("SAML2 metadata for service provider: " + entityId + " is added.");
return true;
}
} else {
log.debug(
- "Can not refresh SAML2 metadata: NO SAML2 metadata URL for SP with Id: " + entityID);
+ "Can not refresh SAML2 metadata: NO SAML2 metadata URL for SP with Id: " + entityId);
}
- } catch (final MetadataProviderException e) {
- log.warn("Refresh SAML2 metadata for service provider: " + entityID + " FAILED.", e);
-
- } catch (final IOException e) {
- log.warn("Refresh SAML2 metadata for service provider: " + entityID + " FAILED.", e);
-
- } catch (final EaafConfigurationException e) {
- log.warn("Refresh SAML2 metadata for service provider: " + entityID + " FAILED.", e);
-
- } catch (final CertificateException e) {
- log.warn("Refresh SAML2 metadata for service provider: " + entityID + " FAILED.", e);
+ } catch (final IOException | ResolverException | EaafConfigurationException | CertificateException e) {
+ log.warn("Refresh SAML2 metadata for service provider: " + entityId + " FAILED.", e);
}
@@ -172,55 +175,20 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataPro
*
*/
public void internalDestroy() {
- if (internalProvider != null && internalProvider instanceof ChainingMetadataProvider) {
- log.info("Destrorying PVP-Authentication MetaDataProvider.");
- final ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider;
-
- final List<MetadataProvider> providers = chainProvider.getProviders();
- for (final MetadataProvider provider : providers) {
- if (provider instanceof HTTPMetadataProvider) {
- final HTTPMetadataProvider httpprovider = (HTTPMetadataProvider) provider;
- log.debug("Destroy HTTPMetadataProvider +" + httpprovider.getMetadataURI());
- httpprovider.destroy();
+ log.info("Destroying chained metadata resolvers ...");
- } else {
- log.warn("MetadataProvider can not be destroyed.");
- }
+ for (final MetadataResolver resolver : internalResolvers) {
+ destroyMetadataResolver(resolver);
}
- internalProvider = new ChainingMetadataProvider();
+ internalResolvers.clear();
if (timer != null) {
timer.cancel();
}
- } else {
- log.warn(
- "ReInitalize MOAMetaDataProvider is not possible! MOA-ID Instance has to be restarted manualy");
- }
}
- /*
- * (non-Javadoc)
- *
- * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider#
- * requireValidMetadata()
- */
- @Override
- public boolean requireValidMetadata() {
- return internalProvider.requireValidMetadata();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider#
- * setRequireValidMetadata (boolean)
- */
- @Override
- public void setRequireValidMetadata(final boolean requireValidMetadata) {
- internalProvider.setRequireValidMetadata(requireValidMetadata);
- }
/*
* (non-Javadoc)
@@ -359,18 +327,6 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataPro
return result;
}
- /*
- * (non-Javadoc)
- *
- * @see
- * org.opensaml.saml2.metadata.provider.ObservableMetadataProvider#getObservers(
- * )
- */
- @Override
- public List<Observer> getObservers() {
- return ((ChainingMetadataProvider) internalProvider).getObservers();
- }
-
/**
* Get the URL to metadata for a specific entityID.
*
@@ -384,13 +340,13 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataPro
* Creates a new implementation specific SAML2 metadata provider.
*
* @param entityId EntityId
- * @return MetadataProvider
+ * @return MetadataResolver
* @throws EaafConfigurationException In case of an error
* @throws IOException In case of an error
* @throws CertificateException In case of an error
* @throws ConfigurationException In case of an error
*/
- protected abstract MetadataProvider createNewMetadataProvider(String entityId)
+ protected abstract MetadataResolver createNewMetadataProvider(String entityId)
throws EaafConfigurationException, IOException, CertificateException;
/**
@@ -398,33 +354,25 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataPro
*
* @throws EaafConfigurationException In case of an error
*/
+ @Nonnull
protected abstract List<String> getAllMetadataUrlsFromConfiguration()
throws EaafConfigurationException;
- protected void emitChangeEvent() {
- if (getObservers() == null || getObservers().size() == 0) {
- return;
- }
-
- final List<Observer> tempObserverList = new ArrayList<>(getObservers());
- for (final ObservableMetadataProvider.Observer observer : tempObserverList) {
- if (observer != null) {
- observer.onEvent(this);
- }
- }
- }
- private Map<String, HTTPMetadataProvider> getAllActuallyLoadedProviders() {
- final Map<String, HTTPMetadataProvider> loadedproviders =
+ private Map<String, MetadataResolver> getAllActuallyLoadedResolvers() {
+ final Map<String, MetadataResolver> loadedproviders =
new HashMap<>();
- final ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider;
// make a Map of all actually loaded HTTPMetadataProvider
- final List<MetadataProvider> providers = chainProvider.getProviders();
- for (final MetadataProvider provider : providers) {
- if (provider instanceof HTTPMetadataProvider) {
- final HTTPMetadataProvider httpprovider = (HTTPMetadataProvider) provider;
- loadedproviders.put(httpprovider.getMetadataURI(), httpprovider);
+ for (final MetadataResolver resolver : internalResolvers) {
+ if (resolver instanceof IdentifiedComponent) {
+ loadedproviders.put(((IdentifiedComponent) resolver).getId(), resolver);
+
+ } else {
+ final String uuid = UUID.randomUUID().toString();
+ loadedproviders.put(uuid, resolver);
+ log.debug("MetadatenResolver is not of type: {}. Mark it with id: {}",
+ IdentifiedComponent.class.getSimpleName(), uuid);
}
}
@@ -433,19 +381,17 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataPro
}
private void addAndRemoveMetadataProvider() throws EaafConfigurationException {
- if (internalProvider != null && internalProvider instanceof ChainingMetadataProvider) {
- log.info("Reload MOAMetaDataProvider.");
+ log.info("EAAF chaining metadata resolver starting internal managment task .... ");
/*
* OpenSAML ChainingMetadataProvider can not remove a MetadataProvider
* (UnsupportedOperationException) The ChainingMetadataProvider use internal a
* unmodifiableList to hold all registrated MetadataProviders.
*/
- final Map<String, MetadataProvider> providersinuse = new HashMap<>();
- final ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider;
+ final Map<String, MetadataResolver> providersinuse = new HashMap<>();
// get all actually loaded metadata providers
- final Map<String, HTTPMetadataProvider> loadedproviders = getAllActuallyLoadedProviders();
+ final Map<String, MetadataResolver> loadedproviders = getAllActuallyLoadedResolvers();
/*
* TODO: maybe add metadata provider destroy after timeout. But could be a
@@ -460,7 +406,6 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataPro
// compare actually loaded Providers with configured SAML2 SPs
final List<String> allMetadataUrls = getAllMetadataUrlsFromConfiguration();
- if (allMetadataUrls != null) {
final Iterator<String> metadataUrlInterator = allMetadataUrls.iterator();
while (metadataUrlInterator.hasNext()) {
final String metadataurl = metadataUrlInterator.next();
@@ -477,15 +422,15 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataPro
}
}
- }
+
// remove all actually loaded MetadataProviders with are not in ConfigurationDB
// any more
- final Collection<HTTPMetadataProvider> notusedproviders = loadedproviders.values();
- for (final HTTPMetadataProvider provider : notusedproviders) {
- final String metadataurl = provider.getMetadataURI();
- try {
- provider.destroy();
+ final Collection<MetadataResolver> notusedproviders = loadedproviders.values();
+ for (final MetadataResolver resolver : notusedproviders) {
+ log.info("Remove not used MetadataProvider with MetadataURL " + resolver.getId());
+ destroyMetadataResolver(resolver);
+ internalResolvers.remove(resolver);
/*
* OpenSAML ChainingMetadataProvider can not remove a MetadataProvider
@@ -493,31 +438,43 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataPro
* unmodifiableList to hold all registrated MetadataProviders.
*/
// chainProvider.removeMetadataProvider(provider);
- log.info("Remove not used MetadataProvider with MetadataURL " + metadataurl);
- } catch (final Throwable e) {
- log.error("HTTPMetadataProvider with URL " + metadataurl
- + " can not be removed from the list of actually loaded Providers.", e);
-
- }
}
+ }
+
+ private EntityDescriptor resolveEntityDescripor(String entityId) throws ResolverException {
+ final CriteriaSet criteria = new CriteriaSet();
+ criteria.add(new EntityIdCriterion(entityId));
+ for (final MetadataResolver resolver : internalResolvers) {
try {
- chainProvider.setProviders(new ArrayList<>(providersinuse.values()));
- emitChangeEvent();
+ final EntityDescriptor descriptors = resolver.resolveSingle(criteria);
+ if (descriptors != null) {
+ return descriptors;
+ }
- } catch (final MetadataProviderException e) {
- log.warn(
- "ReInitalize AbstractMetaDataProvider is not possible! Service has to be restarted manualy",
- e);
+ } catch (final ResolverException e) {
+ continue;
}
- } else {
- log.warn(
- "ReInitalize AbstractMetaDataProvider is not possible! Service has to be restarted manualy");
}
+ return null;
+
+ }
+
+ private void destroyMetadataResolver(MetadataResolver resolver) {
+ if (resolver instanceof AbstractMetadataResolver) {
+ final AbstractMetadataResolver httpprovider = (AbstractMetadataResolver) resolver;
+ log.debug("Destroy metadata resolver with id: {}", httpprovider.getId());
+ httpprovider.destroy();
+
+ } else {
+ log.warn("Metadata resolver: {} can not be destroyed. Reason: unsupported type: {}",
+ resolver.getId(), resolver.getClass().getName());
+
+ }
}
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/MetadataFilterChain.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/MetadataFilterChain.java
deleted file mode 100644
index ebc057df..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/MetadataFilterChain.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
- * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
- * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
- * compliance with the Licence. You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the Licence
- * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the Licence for the specific language governing permissions and limitations under
- * the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text file for details on the
- * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
- * works that you distribute must include a readable copy of the "NOTICE" text file.
-*/
-
-package at.gv.egiz.eaaf.modules.pvp2.impl.metadata;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.opensaml.saml2.metadata.provider.FilterException;
-import org.opensaml.saml2.metadata.provider.MetadataFilter;
-import org.opensaml.xml.XMLObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Metadata filter-chain implementation.
- *
- * @author tlenz
- *
- */
-public class MetadataFilterChain implements MetadataFilter {
- private static final Logger log = LoggerFactory.getLogger(MetadataFilterChain.class);
-
- private final List<MetadataFilter> filters = new ArrayList<>();
-
- /**
- * Return all actually used Metadata filters.
- *
- * @return List of Metadata filters
- */
- public List<MetadataFilter> getFilters() {
- return filters;
- }
-
- /**
- * Add a new Metadata filter to filterchain.
- *
- * @param filter add a metadata filter
- */
- public void addFilter(final MetadataFilter filter) {
- filters.add(filter);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * org.opensaml.saml2.metadata.provider.MetadataFilter#doFilter(org.opensaml.xml
- * .XMLObject)
- */
- @Override
- public void doFilter(final XMLObject arg0) throws FilterException {
- for (final MetadataFilter filter : filters) {
- log.trace("Use EAAFMetadataFilter " + filter.getClass().getName());
- filter.doFilter(arg0);
- }
-
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/SimpleMetadataProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/SimpleMetadataResolver.java
index d63950cb..35ad3f97 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/SimpleMetadataProvider.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/SimpleMetadataResolver.java
@@ -25,30 +25,29 @@ import java.util.Timer;
import javax.net.ssl.SSLHandshakeException;
-import org.apache.commons.httpclient.HttpClient;
-import org.opensaml.saml2.metadata.provider.FilesystemMetadataProvider;
-import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider;
-import org.opensaml.saml2.metadata.provider.MetadataFilter;
-import org.opensaml.saml2.metadata.provider.MetadataProvider;
-import org.opensaml.xml.parse.ParserPool;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-
import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
import at.gv.egiz.eaaf.core.impl.utils.FileUtils;
import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException;
import at.gv.egiz.eaaf.modules.pvp2.exception.SignatureValidationException;
+import org.apache.http.client.HttpClient;
+import org.opensaml.saml.metadata.resolver.MetadataResolver;
+import org.opensaml.saml.metadata.resolver.filter.MetadataFilter;
+import org.opensaml.saml.metadata.resolver.impl.FilesystemMetadataResolver;
+import org.opensaml.saml.metadata.resolver.impl.HTTPMetadataResolver;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import lombok.extern.slf4j.Slf4j;
+import net.shibboleth.utilities.java.support.xml.ParserPool;
+
/**
* Simple SAML2 metadata provider.
*
* @author tlenz
*
*/
-public abstract class SimpleMetadataProvider implements MetadataProvider {
- private static final Logger log = LoggerFactory.getLogger(SimpleMetadataProvider.class);
-
+@Slf4j
+public abstract class SimpleMetadataResolver implements MetadataResolver {
private static final String URI_PREFIX_HTTP = "http:";
private static final String URI_PREFIX_HTTPS = "https:";
private static final String URI_PREFIX_FILE = "file:";
@@ -56,6 +55,21 @@ public abstract class SimpleMetadataProvider implements MetadataProvider {
@Autowired
protected IConfiguration authConfig;
+ @Override
+ public final boolean isRequireValidMetadata() {
+ return true;
+
+ }
+
+ @Override
+ public final void setRequireValidMetadata(final boolean requireValidMetadata) {
+ log.warn("EAAF {} requires always valid metadata. Setting will be ignored",
+ SimpleMetadataResolver.class.getSimpleName());
+
+ }
+
+
+
/**
* Create a single SAML2 metadata provider.
*
@@ -74,7 +88,7 @@ public abstract class SimpleMetadataProvider implements MetadataProvider {
* @return SAML2 Metadata Provider, or null if the metadata provider can not
* initialized
*/
- protected MetadataProvider createNewSimpleMetadataProvider(final String metadataLocation,
+ protected MetadataResolver createNewSimpleMetadataProvider(final String metadataLocation,
final MetadataFilter filter, final String idForLogging, final Timer timer,
final ParserPool pool, final HttpClient httpClient) {
if (metadataLocation.startsWith(URI_PREFIX_HTTP)
@@ -130,24 +144,24 @@ public abstract class SimpleMetadataProvider implements MetadataProvider {
*
* @return SAML2 Metadata Provider
*/
- private MetadataProvider createNewFileSystemMetaDataProvider(final File metadataFile,
+ private MetadataResolver createNewFileSystemMetaDataProvider(final File metadataFile,
final MetadataFilter filter, final String idForLogging, final Timer timer,
final ParserPool pool) {
- FilesystemMetadataProvider fileSystemProvider = null;
+ FilesystemMetadataResolver fileSystemResolver = null;
try {
- fileSystemProvider = new FilesystemMetadataProvider(timer, metadataFile);
- fileSystemProvider.setParserPool(pool);
- fileSystemProvider.setRequireValidMetadata(true);
- fileSystemProvider.setMinRefreshDelay(1000 * 60 * 15); // 15 minutes
- fileSystemProvider.setMaxRefreshDelay(1000 * 60 * 60 * 24); // 24 hours
- // httpProvider.setRefreshDelayFactor(0.1F);
+ fileSystemResolver = new FilesystemMetadataResolver(timer, metadataFile);
+ fileSystemResolver.setParserPool(pool);
+ fileSystemResolver.setRequireValidMetadata(true);
+ fileSystemResolver.setMinRefreshDelay(1000 * 60 * 15); // 15 minutes
+ fileSystemResolver.setMaxRefreshDelay(1000 * 60 * 60 * 24); // 24 hours
- fileSystemProvider.setMetadataFilter(filter);
- fileSystemProvider.initialize();
+ fileSystemResolver.setMetadataFilter(filter);
+ fileSystemResolver.initialize();
+ fileSystemResolver.setId(metadataFile.getAbsolutePath());
- fileSystemProvider.setRequireValidMetadata(true);
+ fileSystemResolver.setRequireValidMetadata(true);
- return fileSystemProvider;
+ return fileSystemResolver;
} catch (final Exception e) {
log.warn("Failed to load Metadata file for " + idForLogging + "[ " + "File: "
@@ -156,8 +170,9 @@ public abstract class SimpleMetadataProvider implements MetadataProvider {
log.warn("Can not initialize SAML2 metadata provider from filesystem: "
+ metadataFile.getAbsolutePath() + " Reason: " + e.getMessage(), e);
- if (fileSystemProvider != null) {
- fileSystemProvider.destroy();
+ if (fileSystemResolver != null) {
+ fileSystemResolver.destroy();
+
}
}
@@ -178,24 +193,25 @@ public abstract class SimpleMetadataProvider implements MetadataProvider {
*
* @return SAML2 Metadata Provider
*/
- private MetadataProvider createNewHttpMetaDataProvider(final String metadataUrl,
+ private MetadataResolver createNewHttpMetaDataProvider(final String metadataUrl,
final MetadataFilter filter, final String idForLogging, final Timer timer,
final ParserPool pool, final HttpClient httpClient) {
- HTTPMetadataProvider httpProvider = null;
+ HTTPMetadataResolver httpMetadataResolver = null;
try {
- httpProvider = new HTTPMetadataProvider(timer, httpClient, metadataUrl);
- httpProvider.setParserPool(pool);
- httpProvider.setRequireValidMetadata(true);
- httpProvider.setMinRefreshDelay(1000 * 60 * 15); // 15 minutes
- httpProvider.setMaxRefreshDelay(1000 * 60 * 60 * 24); // 24 hours
+ httpMetadataResolver = new HTTPMetadataResolver(timer, httpClient, metadataUrl);
+ httpMetadataResolver.setParserPool(pool);
+ httpMetadataResolver.setRequireValidMetadata(true);
+ httpMetadataResolver.setMinRefreshDelay(1000 * 60 * 15); // 15 minutes
+ httpMetadataResolver.setMaxRefreshDelay(1000 * 60 * 60 * 24); // 24 hours
// httpProvider.setRefreshDelayFactor(0.1F);
- httpProvider.setMetadataFilter(filter);
- httpProvider.initialize();
+ httpMetadataResolver.setMetadataFilter(filter);
+ httpMetadataResolver.setId(metadataUrl);
+ httpMetadataResolver.initialize();
- httpProvider.setRequireValidMetadata(true);
+ httpMetadataResolver.setRequireValidMetadata(true);
- return httpProvider;
+ return httpMetadataResolver;
} catch (final Throwable e) {
if (e.getCause() != null && e.getCause().getCause() instanceof SSLHandshakeException) {
@@ -213,15 +229,11 @@ public abstract class SimpleMetadataProvider implements MetadataProvider {
log.warn("Failed to load Metadata file for " + idForLogging + "[ " + e.getMessage() + " ]",
e);
- if (httpProvider != null) {
+ if (httpMetadataResolver != null) {
log.debug("Destroy failed Metadata provider");
- httpProvider.destroy();
- }
+ httpMetadataResolver.destroy();
- // if (timer != null) {
- // log.debug("Destroy Timer.");
- // timer.cancel();
- // }
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpPostDecoder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpPostDecoder.java
new file mode 100644
index 00000000..dc60019a
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpPostDecoder.java
@@ -0,0 +1,77 @@
+package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.servlet.http.HttpServletRequest;
+
+import org.opensaml.messaging.decoder.MessageDecodingException;
+import org.opensaml.saml.saml2.binding.decoding.impl.HTTPPostDecoder;
+
+import com.google.common.base.Strings;
+import lombok.extern.slf4j.Slf4j;
+import net.shibboleth.utilities.java.support.codec.Base64Support;
+
+/**
+ * SAML2 Post-Binding decoder with same EAAF specific hardening regarding http
+ * request-parameter processing.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+public class EaafHttpPostDecoder extends HTTPPostDecoder {
+
+ @Override
+ protected InputStream getBase64DecodedMessage(final HttpServletRequest request)
+ throws MessageDecodingException {
+
+ log.debug("Getting Base64 encoded message from request");
+ String encodedMessage = getLastParameterFromRequest(request, "SAMLRequest");
+ if (Strings.isNullOrEmpty(encodedMessage)) {
+ encodedMessage = getLastParameterFromRequest(request, "SAMLResponse");
+ }
+
+
+
+ if (Strings.isNullOrEmpty(encodedMessage)) {
+ log.info("Request did not contain either a SAMLRequest or "
+ + "SAMLResponse paramter. Invalid request for SAML 2 HTTP POST binding.");
+ throw new MessageDecodingException("No SAML message present in request");
+ }
+
+ log.trace("Base64 decoding SAML message:\n{}", encodedMessage);
+ final byte[] decodedBytes = Base64Support.decode(encodedMessage);
+ if (decodedBytes == null) {
+ log.info("Unable to Base64 decode SAML message");
+ throw new MessageDecodingException("Unable to Base64 decode SAML message");
+ }
+
+ log.trace("Decoded SAML message:\n{}", new String(decodedBytes));
+ return new ByteArrayInputStream(decodedBytes);
+ }
+
+ /**
+ * Always read the last parameter with this name from request to get a strict deterministic behavior.
+ * <br><br>
+ * <b><i>If more than one parameters with the same name exists,
+ * this method always select the last parameter value.</i></b>
+ *
+ * @param request Incoming http request
+ * @param paramName Name of the http parameter
+ * @return the last parameter value with this name, or <code>null</code> if the parameter not exists
+ */
+ @Nullable
+ private String getLastParameterFromRequest(@Nonnull HttpServletRequest request, @Nonnull String paramName) {
+ final String[] values = request.getParameterValues(paramName);
+ if (values != null && values.length > 0) {
+ return values[values.length - 1];
+
+ }
+
+ return null;
+
+ }
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpRedirectDeflateDecoder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpRedirectDeflateDecoder.java
new file mode 100644
index 00000000..e9140f26
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpRedirectDeflateDecoder.java
@@ -0,0 +1,71 @@
+package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml;
+
+import java.io.InputStream;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.decoder.MessageDecodingException;
+import org.opensaml.saml.common.SAMLObject;
+import org.opensaml.saml.common.binding.SAMLBindingSupport;
+import org.opensaml.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.saml2.binding.decoding.impl.HTTPRedirectDeflateDecoder;
+
+import com.google.common.base.Strings;
+import lombok.extern.slf4j.Slf4j;
+import net.shibboleth.utilities.java.support.net.URISupport;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+
+/**
+ * SAML2 Redirect-Binding deflate decoder with same EAAF specific hardening
+ * regarding http request-parameter processing.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+public class EaafHttpRedirectDeflateDecoder extends HTTPRedirectDeflateDecoder {
+
+ @Override
+ protected void doDecode() throws MessageDecodingException {
+ final MessageContext<SAMLObject> messageContext = new MessageContext<>();
+ final HttpServletRequest request = getHttpServletRequest();
+
+ if (!"GET".equalsIgnoreCase(request.getMethod())) {
+ throw new MessageDecodingException("This message decoder only supports the HTTP GET method");
+ }
+
+ final String samlEncoding = StringSupport.trimOrNull(request.getParameter("SAMLEncoding"));
+ if (samlEncoding != null && !SAMLConstants.SAML2_BINDING_URL_ENCODING_DEFLATE_URI.equals(samlEncoding)) {
+ throw new MessageDecodingException("Request indicated an unsupported SAMLEncoding: " + samlEncoding);
+
+ }
+
+ final String relayState = request.getParameter("RelayState");
+ log.debug("Decoded RelayState: {}", relayState);
+ SAMLBindingSupport.setRelayState(messageContext, relayState);
+
+ final InputStream samlMessageIns;
+
+ // implement parameter extraction as same as in
+ // SAML2HTTPRedirectDeflateSignatureSecurityHandler.java
+ final String queryString = getHttpServletRequest().getQueryString();
+ if (!Strings.isNullOrEmpty(URISupport.getRawQueryStringParameter(queryString, "SAMLRequest"))) {
+ samlMessageIns = decodeMessage(URISupport.getRawQueryStringParameter(queryString, "SAMLRequest"));
+ } else if (!Strings.isNullOrEmpty(URISupport.getRawQueryStringParameter(queryString, "SAMLResponse"))) {
+ samlMessageIns = decodeMessage(URISupport.getRawQueryStringParameter(queryString, "SAMLResponse"));
+ } else {
+ throw new MessageDecodingException(
+ "No SAMLRequest or SAMLResponse query path parameter, invalid SAML 2 HTTP Redirect message");
+ }
+
+ final SAMLObject samlMessage = (SAMLObject) unmarshallMessage(samlMessageIns);
+ messageContext.setMessage(samlMessage);
+ log.debug("Decoded SAML message");
+
+ populateBindingContext(messageContext);
+
+ setMessageContext(messageContext);
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafKeyStoreX509CredentialAdapter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafKeyStoreX509CredentialAdapter.java
index 92d8f4b9..7c433c1c 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafKeyStoreX509CredentialAdapter.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafKeyStoreX509CredentialAdapter.java
@@ -21,7 +21,19 @@ package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml;
import java.security.KeyStore;
-import org.opensaml.xml.security.x509.X509Credential;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
+import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
+
+import org.opensaml.security.x509.X509Credential;
+import org.opensaml.security.x509.impl.KeyStoreX509CredentialAdapter;
+
+import lombok.extern.slf4j.Slf4j;
/**
* OpenSAML2 KeyStore adapter.
@@ -29,8 +41,11 @@ import org.opensaml.xml.security.x509.X509Credential;
* @author tlenz
*
*/
-public class EaafKeyStoreX509CredentialAdapter
- extends org.opensaml.xml.security.x509.KeyStoreX509CredentialAdapter {
+@Slf4j
+public class EaafKeyStoreX509CredentialAdapter extends KeyStoreX509CredentialAdapter
+ implements EaafX509Credential {
+
+ private String signatureAlgorithmtToUse;
/**
* Get an OpenSAML2 keystore.
@@ -38,10 +53,31 @@ public class EaafKeyStoreX509CredentialAdapter
* @param store Java KeyStore
* @param alias Key alias
* @param password key Password
+ * @param keyStoreFriendlyName Friendlyname of this keystore for logging purposes
+ * @throws CredentialsNotAvailableException In case of an initialization exception
*/
- public EaafKeyStoreX509CredentialAdapter(final KeyStore store, final String alias,
- final char[] password) {
+ public EaafKeyStoreX509CredentialAdapter(@Nonnull final KeyStore store, @Nonnull final String alias,
+ @Nullable final char[] password, @Nonnull String keyStoreFriendlyName) throws CredentialsNotAvailableException {
super(store, alias, password);
+
+ if (getPrivateKey() == null && getSecretKey() == null) {
+ log.error("KeyStore: {} Key with alias: {} not found or contains no PrivateKey.",
+ keyStoreFriendlyName, alias);
+ throw new CredentialsNotAvailableException("internal.pvp.00",
+ new Object[] { keyStoreFriendlyName, alias});
+
+ }
+
+ try {
+ setSignatureAlgorithmForSigning(Saml2Utils.getSignatureAlgorithm(this,
+ PvpConstants.DEFAULT_SIGNING_METHODE_RSA,
+ PvpConstants.DEFAULT_SIGNING_METHODE_EC));
+
+ } catch (final SamlSigningException e) {
+ throw new CredentialsNotAvailableException("internal.pvp.01", new Object[] {keyStoreFriendlyName, alias}, e);
+
+ }
+
}
@Override
@@ -49,4 +85,16 @@ public class EaafKeyStoreX509CredentialAdapter
return X509Credential.class;
}
+ @Override
+ public String getSignatureAlgorithmForSigning() {
+ return this.signatureAlgorithmtToUse;
+
+ }
+
+ @Override
+ public void setSignatureAlgorithmForSigning(String sigAlg) {
+ this.signatureAlgorithmtToUse = sigAlg;
+
+ }
+
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/HttpPostEncoderWithOwnTemplate.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/HttpPostEncoderWithOwnTemplate.java
index 404b4e8e..3650e617 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/HttpPostEncoderWithOwnTemplate.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/HttpPostEncoderWithOwnTemplate.java
@@ -19,6 +19,7 @@
package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml;
+
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
@@ -26,18 +27,21 @@ import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
-import org.apache.velocity.VelocityContext;
-import org.apache.velocity.app.VelocityEngine;
-import org.opensaml.common.binding.SAMLMessageContext;
-import org.opensaml.saml2.binding.encoding.HTTPPostEncoder;
-import org.opensaml.ws.message.encoder.MessageEncodingException;
-import org.opensaml.ws.transport.http.HTTPOutTransport;
-import org.opensaml.ws.transport.http.HTTPTransportUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import javax.servlet.http.HttpServletResponse;
import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiBuilderConfiguration;
import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiFormBuilder;
+import at.gv.egiz.eaaf.core.impl.gui.velocity.VelocityProvider;
+
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.Velocity;
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.encoder.MessageEncodingException;
+import org.opensaml.saml.common.SAMLObject;
+import org.opensaml.saml.saml2.binding.encoding.impl.HTTPPostEncoder;
+
+import lombok.extern.slf4j.Slf4j;
+import net.shibboleth.utilities.java.support.net.HttpServletSupport;
/**
* OpenSAML2 Post-Binding encoder that uses dynamic loaded templates.
@@ -45,10 +49,9 @@ import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiFormBuilder;
* @author tlenz
*
*/
+@Slf4j
public class HttpPostEncoderWithOwnTemplate extends HTTPPostEncoder {
- private static final Logger log = LoggerFactory.getLogger(HttpPostEncoderWithOwnTemplate.class);
- private final VelocityEngine velocityEngine;
private final IVelocityGuiBuilderConfiguration guiConfig;
private final IVelocityGuiFormBuilder guiBuilder;
@@ -57,29 +60,28 @@ public class HttpPostEncoderWithOwnTemplate extends HTTPPostEncoder {
*
* @param guiConfig GUI configuration
* @param guiBuilder GUI builder implementation
- * @param engine velocity engine
+ * @throws Exception In case of a {@link Velocity} initialization error
*/
public HttpPostEncoderWithOwnTemplate(final IVelocityGuiBuilderConfiguration guiConfig,
- final IVelocityGuiFormBuilder guiBuilder, final VelocityEngine engine) {
- super(engine, null);
- this.velocityEngine = engine;
+ final IVelocityGuiFormBuilder guiBuilder) throws Exception {
this.guiConfig = guiConfig;
this.guiBuilder = guiBuilder;
+ setVelocityEngine(VelocityProvider.getClassPathVelocityEngine());
+
}
/**
- * Base64 and POST encodes the outbound message and writes it to the outbound
+ * Base64 and POST encodes the out-bound message and writes it to the out-bound
* transport.
*
* @param messageContext current message context
- * @param endpointUrl endpoint URL to which to encode message
*
* @throws MessageEncodingException thrown if there is a problem encoding the
* message
*/
@Override
- protected void postEncode(final SAMLMessageContext messageContext, final String endpointUrl)
+ protected void postEncode(final MessageContext<SAMLObject> messageContext, final String endpointUrl)
throws MessageEncodingException {
log.debug("Invoking Velocity template to create POST body");
InputStream is = null;
@@ -91,19 +93,16 @@ public class HttpPostEncoderWithOwnTemplate extends HTTPPostEncoder {
// load template
is = guiBuilder.getTemplateInputStream(guiConfig);
- // populate velocity context with SAML2 parameters
populateVelocityContext(context, messageContext, endpointUrl);
- // populate transport parameter
- final HTTPOutTransport outTransport =
- (HTTPOutTransport) messageContext.getOutboundMessageTransport();
- HTTPTransportUtils.addNoCacheHeaders(outTransport);
- HTTPTransportUtils.setUTF8Encoding(outTransport);
- HTTPTransportUtils.setContentType(outTransport, "text/html");
+ final HttpServletResponse response = getHttpServletResponse();
- // evaluate template and write content to response
- final Writer out = new OutputStreamWriter(outTransport.getOutgoingStream(), "UTF-8");
- velocityEngine.evaluate(context, out, "SAML2_POST_BINDING",
+ HttpServletSupport.addNoCacheHeaders(response);
+ HttpServletSupport.setUTF8Encoding(response);
+ HttpServletSupport.setContentType(response, "text/html");
+
+ final Writer out = new OutputStreamWriter(response.getOutputStream(), "UTF-8");
+ getVelocityEngine().evaluate(context, out, "SAML2_POST_BINDING",
new BufferedReader(new InputStreamReader(is, "UTF-8")));
out.flush();
@@ -123,4 +122,5 @@ public class HttpPostEncoderWithOwnTemplate extends HTTPPostEncoder {
}
}
+
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/StringRedirectDeflateEncoder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/StringRedirectDeflateEncoder.java
index 8838daec..bd450518 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/StringRedirectDeflateEncoder.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/StringRedirectDeflateEncoder.java
@@ -19,15 +19,13 @@
package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml;
-import org.opensaml.common.binding.SAMLMessageContext;
-import org.opensaml.saml2.binding.encoding.HTTPRedirectDeflateEncoder;
-import org.opensaml.ws.message.MessageContext;
-import org.opensaml.ws.message.encoder.MessageEncodingException;
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.encoder.MessageEncodingException;
+import org.opensaml.saml.common.SAMLObject;
+import org.opensaml.saml.saml2.binding.encoding.impl.HTTPRedirectDeflateEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafDefaultSaml2Bootstrap;
-
/**
* Create deflate encoded SAML2 redirect-binding informations.
*
@@ -40,27 +38,18 @@ public class StringRedirectDeflateEncoder extends HTTPRedirectDeflateEncoder {
private String redirectUrl = null;
@Override
- public void encode(final MessageContext messageContext) throws MessageEncodingException {
- if (!(messageContext instanceof SAMLMessageContext)) {
- log.error("Invalid message context type, this encoder only support SAMLMessageContext");
- throw new MessageEncodingException(
- "Invalid message context type, this encoder only support SAMLMessageContext");
- }
-
- // load default PVP security configurations
- EaafDefaultSaml2Bootstrap.initializeDefaultPvpConfiguration();
-
- final SAMLMessageContext samlMsgCtx = (SAMLMessageContext) messageContext;
+ protected void doEncode() throws MessageEncodingException {
+ final MessageContext<SAMLObject> messageContext = getMessageContext();
+ final SAMLObject outboundMessage = messageContext.getMessage();
- final String endpointUrl = getEndpointURL(samlMsgCtx).buildURL();
+ final String endpointUrl = getEndpointURL(messageContext).toString();
- setResponseDestination(samlMsgCtx.getOutboundSAMLMessage(), endpointUrl);
+ removeSignature(outboundMessage);
- removeSignature(samlMsgCtx);
+ final String encodedMessage = deflateAndBase64Encode(outboundMessage);
- final String encodedMessage = deflateAndBase64Encode(samlMsgCtx.getOutboundSAMLMessage());
+ redirectUrl = buildRedirectURL(messageContext, endpointUrl, encodedMessage);
- redirectUrl = buildRedirectURL(samlMsgCtx, endpointUrl, encodedMessage);
}
/**
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafDefaultSaml2Bootstrap.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafDefaultSaml2Bootstrap.java
deleted file mode 100644
index 9625b591..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafDefaultSaml2Bootstrap.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
- * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
- * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
- * compliance with the Licence. You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the Licence
- * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the Licence for the specific language governing permissions and limitations under
- * the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text file for details on the
- * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
- * works that you distribute must include a readable copy of the "NOTICE" text file.
-*/
-
-package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize;
-
-import org.opensaml.DefaultBootstrap;
-import org.opensaml.xml.ConfigurationException;
-
-import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute;
-import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttributes;
-import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributeBuilder;
-import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributeMarshaller;
-import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributeUnmarshaller;
-import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributesBuilder;
-import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributesMarshaller;
-import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributesUnmarshaller;
-
-/**
- * EAAF specific OpenSAML Initializer.
- *
- * @author tlenz
- *
- */
-public class EaafDefaultSaml2Bootstrap extends DefaultBootstrap {
-
- /**
- * OpenSAML2 bootstrap.
- *
- * @throws ConfigurationException In case of an error
- */
- public static synchronized void bootstrap() throws ConfigurationException {
-
- initializeXMLSecurity();
-
- initializeXMLTooling();
-
- initializeArtifactBuilderFactories();
-
- initializeGlobalSecurityConfiguration();
-
- initializeParserPool();
-
- initializeESAPI();
-
- initializeExtenstions();
-
- }
-
- private static void initializeExtenstions() {
- org.opensaml.xml.Configuration.registerObjectProvider(
- EaafRequestedAttribute.DEFAULT_ELEMENT_NAME, new EaafRequestedAttributeBuilder(),
- new EaafRequestedAttributeMarshaller(), new EaafRequestedAttributeUnmarshaller());
-
- org.opensaml.xml.Configuration.registerObjectProvider(
- EaafRequestedAttributes.DEFAULT_ELEMENT_NAME, new EaafRequestedAttributesBuilder(),
- new EaafRequestedAttributesMarshaller(), new EaafRequestedAttributesUnmarshaller());
-
- }
-
- public static void initializeDefaultPvpConfiguration() {
- initializeGlobalSecurityConfiguration();
-
- }
-
- /**
- * Initializes the default global security configuration.
- */
- protected static void initializeGlobalSecurityConfiguration() {
- org.opensaml.xml.Configuration.setGlobalSecurityConfiguration(
- EaafDefaultSecurityConfigurationBootstrap.buildDefaultConfig());
- }
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafDefaultSecurityConfigurationBootstrap.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafDefaultSecurityConfigurationBootstrap.java
index f3e50e4e..97f0f225 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafDefaultSecurityConfigurationBootstrap.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafDefaultSecurityConfigurationBootstrap.java
@@ -19,14 +19,17 @@
package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize;
-import org.opensaml.xml.encryption.EncryptionConstants;
-import org.opensaml.xml.security.BasicSecurityConfiguration;
-import org.opensaml.xml.security.DefaultSecurityConfigurationBootstrap;
-import org.opensaml.xml.security.credential.BasicKeyInfoGeneratorFactory;
-import org.opensaml.xml.security.keyinfo.KeyInfoGeneratorManager;
-import org.opensaml.xml.security.keyinfo.NamedKeyInfoGeneratorManager;
-import org.opensaml.xml.security.x509.X509KeyInfoGeneratorFactory;
-import org.opensaml.xml.signature.SignatureConstants;
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.opensaml.xmlsec.config.impl.DefaultSecurityConfigurationBootstrap;
+import org.opensaml.xmlsec.encryption.support.EncryptionConstants;
+import org.opensaml.xmlsec.encryption.support.RSAOAEPParameters;
+import org.opensaml.xmlsec.impl.BasicDecryptionConfiguration;
+import org.opensaml.xmlsec.impl.BasicEncryptionConfiguration;
+import org.opensaml.xmlsec.impl.BasicSignatureSigningConfiguration;
+import org.opensaml.xmlsec.impl.BasicSignatureValidationConfiguration;
+import org.opensaml.xmlsec.signature.support.SignatureConstants;
/**
* EAAF specific OpenSAML2 security configuration.
@@ -38,102 +41,137 @@ public class EaafDefaultSecurityConfigurationBootstrap
extends DefaultSecurityConfigurationBootstrap {
/**
- * Build EAAF security configuration for OpenSAML2.
+ * Set EAAF specific encryption configuration to OpenSAML 3.x.
*
* @return
*/
- public static BasicSecurityConfiguration buildDefaultConfig() {
- final BasicSecurityConfiguration config = new BasicSecurityConfiguration();
-
- populateSignatureParams(config);
- populateEncryptionParams(config);
- populateKeyInfoCredentialResolverParams(config);
- populateKeyInfoGeneratorManager(config);
- populateKeyParams(config);
+ public static BasicEncryptionConfiguration buildEaafEncryptionConfiguration() {
+ final BasicEncryptionConfiguration config = new BasicEncryptionConfiguration();
+
+ config.setBlacklistedAlgorithms(Arrays.asList(
+ EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSA15,
+ EncryptionConstants.ALGO_ID_BLOCKCIPHER_TRIPLEDES,
+ EncryptionConstants.ALGO_ID_KEYWRAP_TRIPLEDES));
+
+ config.setDataEncryptionAlgorithms(Arrays.asList(
+ // The order of these is significant.
+ EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128,
+ EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES192,
+ EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256,
+
+ // register GCM algorithms
+ EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128_GCM,
+ EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES192_GCM,
+ EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256_GCM));
+
+ config.setKeyTransportEncryptionAlgorithms(Arrays.asList(
+ // The order of the RSA algos is significant.
+ EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP,
+ EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP11,
+
+ // The order of these is not significant.
+ // These aren't really "preferences" per se. They just need to be registered
+ // so that they can be used if a credential with a key of that type and size is
+ // seen.
+ EncryptionConstants.ALGO_ID_KEYWRAP_AES128,
+ EncryptionConstants.ALGO_ID_KEYWRAP_AES192,
+ EncryptionConstants.ALGO_ID_KEYWRAP_AES256));
+
+ config.setRSAOAEPParameters(new RSAOAEPParameters(
+ SignatureConstants.ALGO_ID_DIGEST_SHA1,
+ EncryptionConstants.ALGO_ID_MGF1_SHA1,
+ null));
+
+ config.setDataKeyInfoGeneratorManager(buildDataEncryptionKeyInfoGeneratorManager());
+ config.setKeyTransportKeyInfoGeneratorManager(buildKeyTransportEncryptionKeyInfoGeneratorManager());
return config;
}
- protected static void populateKeyInfoGeneratorManager(final BasicSecurityConfiguration config) {
- final NamedKeyInfoGeneratorManager namedManager = new NamedKeyInfoGeneratorManager();
- config.setKeyInfoGeneratorManager(namedManager);
-
- namedManager.setUseDefaultManager(true);
- final KeyInfoGeneratorManager defaultManager = namedManager.getDefaultManager();
+ /**
+ * Set EAAF specific decryption configuration to OpenSAML 3.x.
+ *
+ * @return
+ */
+ public static BasicDecryptionConfiguration buildEaaftDecryptionConfiguration() {
+ final BasicDecryptionConfiguration config = new BasicDecryptionConfiguration();
- final BasicKeyInfoGeneratorFactory basicFactory = new BasicKeyInfoGeneratorFactory();
- basicFactory.setEmitPublicKeyValue(true);
+ config.setBlacklistedAlgorithms(Collections.singletonList(
+ EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSA15));
- final X509KeyInfoGeneratorFactory x509Factory = new X509KeyInfoGeneratorFactory();
- x509Factory.setEmitEntityCertificate(true);
+ config.setEncryptedKeyResolver(buildBasicEncryptedKeyResolver());
- defaultManager.registerFactory(basicFactory);
- defaultManager.registerFactory(x509Factory);
+ return config;
}
- protected static void populateSignatureParams(final BasicSecurityConfiguration config) {
-
- // use SHA256 instead of SHA1
- config.registerSignatureAlgorithmURI("RSA", SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
-
- config.registerSignatureAlgorithmURI("DSA", "http://www.w3.org/2000/09/xmldsig#dsa-sha1");
-
- // use SHA256 instead of SHA1
- config.registerSignatureAlgorithmURI("EC", SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA256);
-
- // use SHA256 instead of SHA1
- config.registerSignatureAlgorithmURI("AES", SignatureConstants.ALGO_ID_MAC_HMAC_SHA256);
-
- config.registerSignatureAlgorithmURI("DESede", SignatureConstants.ALGO_ID_MAC_HMAC_SHA256);
-
- config.setSignatureCanonicalizationAlgorithm("http://www.w3.org/2001/10/xml-exc-c14n#");
- config.setSignatureHMACOutputLength(null);
+ /**
+ * Set EAAF specific signature-creation configuration to OpenSAML 3.x.
+ *
+ * @return
+ */
+ public static BasicSignatureSigningConfiguration buildEaafSignatureSigningConfiguration() {
+ final BasicSignatureSigningConfiguration config = new BasicSignatureSigningConfiguration();
+
+ config.setBlacklistedAlgorithms(Arrays.asList(
+ SignatureConstants.ALGO_ID_DIGEST_NOT_RECOMMENDED_MD5,
+ SignatureConstants.ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5,
+ SignatureConstants.ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5,
+ SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1,
+ SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA1,
+ SignatureConstants.ALGO_ID_SIGNATURE_DSA_SHA1,
+ SignatureConstants.ALGO_ID_DIGEST_SHA1));
+
+ config.setSignatureAlgorithms(Arrays.asList(
+ // The order within each key group is significant.
+ // The order of the key groups themselves is not significant.
+
+ // RSA
+ SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256,
+ SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA384,
+ SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA512,
+
+ // ECDSA
+ SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA256,
+ SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA384,
+ SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA512
+
+ // HMAC (all symmetric keys)
+ // SignatureConstants.ALGO_ID_MAC_HMAC_SHA256,
+ // SignatureConstants.ALGO_ID_MAC_HMAC_SHA384,
+ // SignatureConstants.ALGO_ID_MAC_HMAC_SHA512,
+ // SignatureConstants.ALGO_ID_MAC_HMAC_SHA1
+ ));
+
+ config.setSignatureReferenceDigestMethods(Arrays.asList(
+ // The order of these is significant.
+ SignatureConstants.ALGO_ID_DIGEST_SHA256,
+ SignatureConstants.ALGO_ID_DIGEST_SHA384,
+ SignatureConstants.ALGO_ID_DIGEST_SHA512));
+
+ config.setSignatureCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
+
+ config.setKeyInfoGeneratorManager(buildSignatureKeyInfoGeneratorManager());
- // use SHA256 instead of SHA1
- config.setSignatureReferenceDigestMethod(SignatureConstants.ALGO_ID_DIGEST_SHA256);
+ return config;
}
- protected static void populateEncryptionParams(final BasicSecurityConfiguration config) {
- config.registerDataEncryptionAlgorithmURI("AES", Integer.valueOf(128),
- "http://www.w3.org/2001/04/xmlenc#aes128-cbc");
- config.registerDataEncryptionAlgorithmURI("AES", Integer.valueOf(192),
- "http://www.w3.org/2001/04/xmlenc#aes192-cbc");
- config.registerDataEncryptionAlgorithmURI("AES", Integer.valueOf(256),
- "http://www.w3.org/2001/04/xmlenc#aes256-cbc");
-
- // support GCM mode
- config.registerDataEncryptionAlgorithmURI("AES", Integer.valueOf(128),
- EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128_GCM);
-
- config.registerDataEncryptionAlgorithmURI("AES", Integer.valueOf(192),
- EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES192_GCM);
-
- config.registerDataEncryptionAlgorithmURI("AES", Integer.valueOf(256),
- EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256_GCM);
-
- config.registerDataEncryptionAlgorithmURI("DESede", Integer.valueOf(168),
- "http://www.w3.org/2001/04/xmlenc#tripledes-cbc");
- config.registerDataEncryptionAlgorithmURI("DESede", Integer.valueOf(192),
- "http://www.w3.org/2001/04/xmlenc#tripledes-cbc");
-
- config.registerKeyTransportEncryptionAlgorithmURI("RSA", null, "AES",
- "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p");
-
- config.registerKeyTransportEncryptionAlgorithmURI("RSA", null, "DESede",
- "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p");
-
- config.registerKeyTransportEncryptionAlgorithmURI("AES", Integer.valueOf(128), null,
- "http://www.w3.org/2001/04/xmlenc#kw-aes128");
- config.registerKeyTransportEncryptionAlgorithmURI("AES", Integer.valueOf(192), null,
- "http://www.w3.org/2001/04/xmlenc#kw-aes192");
- config.registerKeyTransportEncryptionAlgorithmURI("AES", Integer.valueOf(256), null,
- "http://www.w3.org/2001/04/xmlenc#kw-aes256");
- config.registerKeyTransportEncryptionAlgorithmURI("DESede", Integer.valueOf(168), null,
- "http://www.w3.org/2001/04/xmlenc#kw-tripledes");
- config.registerKeyTransportEncryptionAlgorithmURI("DESede", Integer.valueOf(192), null,
- "http://www.w3.org/2001/04/xmlenc#kw-tripledes");
-
- config.setAutoGeneratedDataEncryptionKeyAlgorithmURI(
- "http://www.w3.org/2001/04/xmlenc#aes128-cbc");
+ /**
+ * Set EAAF specific signature-verification configuration to OpenSAML 3.x.
+ *
+ * @return
+ */
+ public static BasicSignatureValidationConfiguration buildEaafSignatureValidationConfiguration() {
+ final BasicSignatureValidationConfiguration config = new BasicSignatureValidationConfiguration();
+
+ config.setBlacklistedAlgorithms(Arrays.asList(
+ SignatureConstants.ALGO_ID_DIGEST_NOT_RECOMMENDED_MD5,
+ SignatureConstants.ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5,
+ SignatureConstants.ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5,
+ SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1,
+ SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA1,
+ SignatureConstants.ALGO_ID_SIGNATURE_DSA_SHA1,
+ SignatureConstants.ALGO_ID_DIGEST_SHA1));
+
+ return config;
}
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafOpenSaml3xInitializer.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafOpenSaml3xInitializer.java
new file mode 100644
index 00000000..42d4d736
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafOpenSaml3xInitializer.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+import javax.xml.XMLConstants;
+
+import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute;
+import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttributes;
+import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributeBuilder;
+import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributeMarshaller;
+import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributeUnmarshaller;
+import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributesBuilder;
+import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributesMarshaller;
+import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributesUnmarshaller;
+
+import org.opensaml.core.config.ConfigurationService;
+import org.opensaml.core.config.InitializationException;
+import org.opensaml.core.config.InitializationService;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.xmlsec.DecryptionConfiguration;
+import org.opensaml.xmlsec.EncryptionConfiguration;
+import org.opensaml.xmlsec.SignatureSigningConfiguration;
+import org.opensaml.xmlsec.SignatureValidationConfiguration;
+
+import lombok.extern.slf4j.Slf4j;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.xml.BasicParserPool;
+import net.shibboleth.utilities.java.support.xml.ParserPool;
+
+/**
+ * EAAF specific OpenSAML Initializer.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+public class EaafOpenSaml3xInitializer extends InitializationService {
+
+ /**
+ * EAAF specific OpenSAML3.x initialization.
+ *
+ * @throws InitializationException In case of an error
+ * @throws ComponentInitializationException
+ */
+ public static synchronized void eaafInitialize() throws InitializationException, ComponentInitializationException {
+ log.debug("Initializing OpenSAML 3.x ... ");
+ initialize();
+
+ log.debug("Injecting EAAF-specific configuration into OpenSAML 3.x ... ");
+ injectEaafSecurityProperty();
+ injectEaafExtenstions();
+
+ XMLObjectProviderRegistrySupport.setParserPool(eaafSecuredBasicParserPool());
+
+ log.info("OpenSAML3.x with EAAF extensions initialized");
+
+ }
+
+ private static void injectEaafSecurityProperty() {
+ ConfigurationService.register(EncryptionConfiguration.class,
+ EaafDefaultSecurityConfigurationBootstrap.buildEaafEncryptionConfiguration());
+
+ ConfigurationService.register(DecryptionConfiguration.class,
+ EaafDefaultSecurityConfigurationBootstrap.buildEaaftDecryptionConfiguration());
+
+ ConfigurationService.register(SignatureSigningConfiguration.class,
+ EaafDefaultSecurityConfigurationBootstrap.buildEaafSignatureSigningConfiguration());
+
+ ConfigurationService.register(SignatureValidationConfiguration.class,
+ EaafDefaultSecurityConfigurationBootstrap.buildEaafSignatureValidationConfiguration());
+
+ }
+
+ private static void injectEaafExtenstions() {
+ XMLObjectProviderRegistrySupport.registerObjectProvider(
+ EaafRequestedAttribute.DEFAULT_ELEMENT_NAME, new EaafRequestedAttributeBuilder(),
+ new EaafRequestedAttributeMarshaller(), new EaafRequestedAttributeUnmarshaller());
+
+ XMLObjectProviderRegistrySupport.registerObjectProvider(
+ EaafRequestedAttributes.DEFAULT_ELEMENT_NAME, new EaafRequestedAttributesBuilder(),
+ new EaafRequestedAttributesMarshaller(), new EaafRequestedAttributesUnmarshaller());
+
+ }
+
+ /**
+ * Build a secured OpenSAML 3.x XML parser-pool.
+ *
+ * @return {@link ParserPool}
+ * @throws ComponentInitializationException In case of an initialization error
+ */
+ @Nonnull
+ private static ParserPool eaafSecuredBasicParserPool() throws ComponentInitializationException {
+ // Get parser pool manager
+ final BasicParserPool ppMgr = new BasicParserPool();
+ // Note: this is necessary due to an unresolved Xerces deferred DOM issue/bug
+ ppMgr.setBuilderFeatures(getSecureDocumentBuilderFeatures());
+ ppMgr.setNamespaceAware(true);
+ ppMgr.setIgnoreComments(true);
+ ppMgr.setExpandEntityReferences(false);
+ ppMgr.setXincludeAware(false);
+ ppMgr.initialize();
+ return ppMgr;
+ }
+
+ @Nonnull
+ private static Map<String, Boolean> getSecureDocumentBuilderFeatures() {
+ final Map<String, Boolean> features = new HashMap<>();
+ features.put(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
+
+ // Ignore the external DTD completely
+ // Note: this is for Xerces only:
+ features.put("http://apache.org/xml/features/nonvalidating/load-external-dtd", Boolean.FALSE);
+ // This is the PRIMARY defense. If DTDs (doctypes) are disallowed, almost all
+ // XML entity attacks are prevented
+ // Xerces 2 only -
+ // http://xerces.apache.org/xerces2-j/features.html#disallow-doctype-decl
+ features.put("http://apache.org/xml/features/disallow-doctype-decl", Boolean.TRUE);
+
+ // If you can't completely disable DTDs, then at least do the following:
+ // Xerces 1 -
+ // http://xerces.apache.org/xerces-j/features.html#external-general-entities
+ // Xerces 2 -
+ // http://xerces.apache.org/xerces2-j/features.html#external-general-entities
+ features.put("http://xml.org/sax/features/external-general-entities", Boolean.FALSE);
+
+ // Xerces 1 -
+ // http://xerces.apache.org/xerces-j/features.html#external-parameter-entities
+ // Xerces 2 -
+ // http://xerces.apache.org/xerces2-j/features.html#external-parameter-entities
+ features.put("http://xml.org/sax/features/external-parameter-entities", Boolean.FALSE);
+
+ return features;
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EaafRequestedAttributeImpl.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EaafRequestedAttributeImpl.java
index e91ee19c..e391bb31 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EaafRequestedAttributeImpl.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EaafRequestedAttributeImpl.java
@@ -23,14 +23,14 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import org.opensaml.common.impl.AbstractSAMLObject;
-import org.opensaml.xml.XMLObject;
-import org.opensaml.xml.schema.XSBooleanValue;
-import org.opensaml.xml.util.AttributeMap;
-import org.opensaml.xml.util.XMLObjectChildrenList;
-
import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.schema.XSBooleanValue;
+import org.opensaml.core.xml.util.AttributeMap;
+import org.opensaml.core.xml.util.XMLObjectChildrenList;
+import org.opensaml.saml.common.AbstractSAMLObject;
+
public class EaafRequestedAttributeImpl extends AbstractSAMLObject
implements EaafRequestedAttribute {
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EaafRequestedAttributesImpl.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EaafRequestedAttributesImpl.java
index eefc166b..9c251233 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EaafRequestedAttributesImpl.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EaafRequestedAttributesImpl.java
@@ -23,13 +23,13 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import org.opensaml.common.impl.AbstractSAMLObject;
-import org.opensaml.xml.XMLObject;
-import org.opensaml.xml.util.IndexedXMLObjectChildrenList;
-
import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute;
import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttributes;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.util.IndexedXMLObjectChildrenList;
+import org.opensaml.saml.common.AbstractSAMLObject;
+
public class EaafRequestedAttributesImpl extends AbstractSAMLObject
implements EaafRequestedAttributes {
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/AbstractCredentialProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/AbstractCredentialProvider.java
index c0b015be..336741a0 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/AbstractCredentialProvider.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/AbstractCredentialProvider.java
@@ -29,18 +29,21 @@ import java.security.interfaces.RSAPrivateKey;
import javax.annotation.PostConstruct;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;
import at.gv.egiz.eaaf.core.exceptions.EaafException;
import at.gv.egiz.eaaf.core.impl.utils.KeyStoreUtils;
+import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException;
import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.EaafKeyStoreX509CredentialAdapter;
import org.apache.commons.lang3.StringUtils;
-import org.opensaml.xml.security.credential.Credential;
-import org.opensaml.xml.security.credential.UsageType;
-import org.opensaml.xml.security.x509.X509Credential;
-import org.opensaml.xml.signature.Signature;
-import org.opensaml.xml.signature.SignatureConstants;
+import org.opensaml.security.credential.Credential;
+import org.opensaml.security.credential.UsageType;
+import org.opensaml.xmlsec.signature.Signature;
+import org.opensaml.xmlsec.signature.support.SignatureConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -50,7 +53,10 @@ import org.springframework.core.io.ResourceLoader;
public abstract class AbstractCredentialProvider {
- @Autowired protected ResourceLoader resourceLoader;
+ @Autowired
+ protected ResourceLoader resourceLoader;
+ @Autowired
+ protected IConfiguration basicConfig;
private static final Logger log = LoggerFactory.getLogger(AbstractCredentialProvider.class);
@@ -127,24 +133,26 @@ public abstract class AbstractCredentialProvider {
* @return Credentials
* @throws CredentialsNotAvailableException In case of a credential error
*/
- public X509Credential getIdpMetaDataSigningCredential() throws CredentialsNotAvailableException {
+ public EaafX509Credential getIdpMetaDataSigningCredential() throws CredentialsNotAvailableException {
try {
final EaafKeyStoreX509CredentialAdapter credentials = new EaafKeyStoreX509CredentialAdapter(keyStore,
- getMetadataKeyAlias(), getMetadataKeyPassword().toCharArray());
+ getMetadataKeyAlias(), getMetadataKeyPassword().toCharArray(), getFriendlyName());
credentials.setUsageType(UsageType.SIGNING);
- if (credentials.getPrivateKey() == null && credentials.getSecretKey() == null) {
- log.error(getFriendlyName()
- + " Metadata Signing credentials is not found or contains no PrivateKey.");
- throw new CredentialsNotAvailableException("config.27",
- new Object[] { getFriendlyName() + " Assertion Signing credentials (Alias: "
- + getMetadataKeyAlias() + ") is not found or contains no PrivateKey." });
-
- }
+ credentials.setSignatureAlgorithmForSigning(Saml2Utils.getSignatureAlgorithm(
+ credentials,
+ basicConfig.getBasicConfiguration(
+ PvpConstants.CONFIG_PROP_SEC_SIGNING_RSA_ALG,
+ PvpConstants.DEFAULT_SIGNING_METHODE_RSA),
+ basicConfig.getBasicConfiguration(
+ PvpConstants.CONFIG_PROP_SEC_SIGNING_RSA_ALG,
+ PvpConstants.DEFAULT_SIGNING_METHODE_EC)));
return credentials;
- } catch (final Exception e) {
- log.error("Failed to generate " + getFriendlyName() + " Metadata Signing credentials", e);
- throw new CredentialsNotAvailableException("config.27", new Object[] { e.getMessage() }, e);
+
+ } catch (final SamlSigningException e) {
+ throw new CredentialsNotAvailableException("internal.pvp.01",
+ new Object[] { getFriendlyName(), getMetadataKeyAlias() }, e);
+
}
}
@@ -154,25 +162,27 @@ public abstract class AbstractCredentialProvider {
* @return Credentials
* @throws CredentialsNotAvailableException In case of a credential error
*/
- public X509Credential getIdpAssertionSigningCredential() throws CredentialsNotAvailableException {
+ public EaafX509Credential getIdpAssertionSigningCredential() throws CredentialsNotAvailableException {
try {
final EaafKeyStoreX509CredentialAdapter credentials = new EaafKeyStoreX509CredentialAdapter(keyStore,
- getSignatureKeyAlias(), getSignatureKeyPassword().toCharArray());
+ getSignatureKeyAlias(), getSignatureKeyPassword().toCharArray(), getFriendlyName());
credentials.setUsageType(UsageType.SIGNING);
- if (credentials.getPrivateKey() == null && credentials.getSecretKey() == null) {
- log.error(getFriendlyName()
- + " Assertion Signing credentials is not found or contains no PrivateKey.");
- throw new CredentialsNotAvailableException("config.27",
- new Object[] { getFriendlyName() + " Assertion Signing credentials (Alias: "
- + getSignatureKeyAlias() + ") is not found or contains no PrivateKey." });
-
- }
+ credentials.setSignatureAlgorithmForSigning(Saml2Utils.getSignatureAlgorithm(
+ credentials,
+ basicConfig.getBasicConfiguration(
+ PvpConstants.CONFIG_PROP_SEC_SIGNING_RSA_ALG,
+ PvpConstants.DEFAULT_SIGNING_METHODE_RSA),
+ basicConfig.getBasicConfiguration(
+ PvpConstants.CONFIG_PROP_SEC_SIGNING_RSA_ALG,
+ PvpConstants.DEFAULT_SIGNING_METHODE_EC)));
return credentials;
+
} catch (final Exception e) {
- log.error("Failed to generate " + getFriendlyName() + " Assertion Signing credentials", e);
- throw new CredentialsNotAvailableException("config.27", new Object[] { e.getMessage() }, e);
+ throw new CredentialsNotAvailableException("internal.pvp.01",
+ new Object[] { getFriendlyName(), getSignatureKeyAlias() }, e);
+
}
}
@@ -182,34 +192,18 @@ public abstract class AbstractCredentialProvider {
* @return Credentials
* @throws CredentialsNotAvailableException In case of a credential error
*/
- public X509Credential getIdpAssertionEncryptionCredential()
+ public EaafX509Credential getIdpAssertionEncryptionCredential()
throws CredentialsNotAvailableException {
- try {
- // if no encryption key is configured return null
- if (StringUtils.isEmpty(getEncryptionKeyAlias())) {
- return null;
- }
-
- final EaafKeyStoreX509CredentialAdapter credentials = new EaafKeyStoreX509CredentialAdapter(keyStore,
- getEncryptionKeyAlias(), getEncryptionKeyPassword().toCharArray());
-
- credentials.setUsageType(UsageType.ENCRYPTION);
-
- if (credentials.getPrivateKey() == null && credentials.getSecretKey() == null) {
- log.error(getFriendlyName()
- + " Assertion Encryption credentials is not found or contains no PrivateKey.");
- throw new CredentialsNotAvailableException("config.27",
- new Object[] { getFriendlyName() + " Assertion Encryption credentials (Alias: "
- + getEncryptionKeyAlias() + ") is not found or contains no PrivateKey." });
-
- }
+ // if no encryption key is configured return null
+ if (StringUtils.isEmpty(getEncryptionKeyAlias())) {
+ return null;
+ }
- return credentials;
+ final EaafKeyStoreX509CredentialAdapter credentials = new EaafKeyStoreX509CredentialAdapter(keyStore,
+ getEncryptionKeyAlias(), getEncryptionKeyPassword().toCharArray(), getFriendlyName());
+ credentials.setUsageType(UsageType.ENCRYPTION);
+ return credentials;
- } catch (final Exception e) {
- log.error("Failed to generate " + getFriendlyName() + " Assertion Encryption credentials", e);
- throw new CredentialsNotAvailableException("config.27", new Object[] { e.getMessage() }, e);
- }
}
/**
@@ -218,6 +212,7 @@ public abstract class AbstractCredentialProvider {
* @param credentials Credentials for signing
* @return OpenSAML Signature object
*/
+ @Deprecated
public static Signature getIdpSignature(final Credential credentials) {
final PrivateKey privatekey = credentials.getPrivateKey();
final Signature signer = Saml2Utils.createSamlObject(Signature.class);
@@ -250,7 +245,7 @@ public abstract class AbstractCredentialProvider {
if (keyStore == null) {
throw new EaafConfigurationException("module.00",
- new Object[] {getFriendlyName(), "KeyStore initialization failed. Maybe wrong password"});
+ new Object[] { getFriendlyName(), "KeyStore initialization failed. Maybe wrong password" });
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/Saml2Utils.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/Saml2Utils.java
index 1a282b55..8b1b041b 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/Saml2Utils.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/Saml2Utils.java
@@ -20,8 +20,13 @@
package at.gv.egiz.eaaf.modules.pvp2.impl.utils;
import java.io.IOException;
+import java.security.PrivateKey;
+import java.security.interfaces.ECPrivateKey;
+import java.security.interfaces.ECPublicKey;
+import java.security.interfaces.RSAPrivateKey;
import java.util.List;
+import javax.annotation.Nonnull;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@@ -31,35 +36,60 @@ import javax.xml.transform.dom.DOMSource;
import javax.xml.validation.Schema;
import javax.xml.validation.Validator;
+import at.gv.egiz.eaaf.core.impl.utils.Random;
+import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
+import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException;
+
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
-import org.opensaml.common.xml.SAMLSchemaBuilder;
-import org.opensaml.saml2.core.Attribute;
-import org.opensaml.saml2.core.Status;
-import org.opensaml.saml2.core.StatusCode;
-import org.opensaml.saml2.metadata.AssertionConsumerService;
-import org.opensaml.saml2.metadata.SPSSODescriptor;
-import org.opensaml.ws.soap.soap11.Body;
-import org.opensaml.ws.soap.soap11.Envelope;
-import org.opensaml.xml.XMLObject;
-import org.opensaml.xml.XMLObjectBuilderFactory;
-import org.opensaml.xml.io.Marshaller;
-import org.opensaml.xml.io.MarshallingException;
-import org.opensaml.xml.schema.XSString;
-import org.opensaml.xml.schema.impl.XSStringBuilder;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.XMLObjectBuilderFactory;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.io.Marshaller;
+import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.schema.XSString;
+import org.opensaml.core.xml.schema.impl.XSStringBuilder;
+import org.opensaml.saml.common.SAMLObjectContentReference;
+import org.opensaml.saml.common.xml.SAMLSchemaBuilder;
+import org.opensaml.saml.common.xml.SAMLSchemaBuilder.SAML1Version;
+import org.opensaml.saml.saml2.core.Attribute;
+import org.opensaml.saml.saml2.core.Status;
+import org.opensaml.saml.saml2.core.StatusCode;
+import org.opensaml.saml.saml2.metadata.AssertionConsumerService;
+import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
+import org.opensaml.security.SecurityException;
+import org.opensaml.security.x509.X509Credential;
+import org.opensaml.soap.soap11.Body;
+import org.opensaml.soap.soap11.Envelope;
+import org.opensaml.xmlsec.SecurityConfigurationSupport;
+import org.opensaml.xmlsec.SignatureSigningConfiguration;
+import org.opensaml.xmlsec.keyinfo.KeyInfoGenerator;
+import org.opensaml.xmlsec.keyinfo.KeyInfoGeneratorFactory;
+import org.opensaml.xmlsec.keyinfo.KeyInfoGeneratorManager;
+import org.opensaml.xmlsec.keyinfo.NamedKeyInfoGeneratorManager;
+import org.opensaml.xmlsec.keyinfo.impl.BasicKeyInfoGeneratorFactory;
+import org.opensaml.xmlsec.signature.KeyInfo;
+import org.opensaml.xmlsec.signature.SignableXMLObject;
+import org.opensaml.xmlsec.signature.Signature;
+import org.opensaml.xmlsec.signature.support.ContentReference;
+import org.opensaml.xmlsec.signature.support.SignatureConstants;
+import org.opensaml.xmlsec.signature.support.SignatureException;
+import org.opensaml.xmlsec.signature.support.Signer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
-import at.gv.egiz.eaaf.core.impl.utils.Random;
-import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
-import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute;
-
public class Saml2Utils {
private static final Logger log = LoggerFactory.getLogger(Saml2Utils.class);
private static DocumentBuilder builder;
+ private static SAMLSchemaBuilder schemaBuilder;
static {
+ schemaBuilder = new SAMLSchemaBuilder(SAML1Version.SAML_11);
+
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
@@ -73,16 +103,144 @@ public class Saml2Utils {
}
/**
+ * Sign a OpenSAML 3.x object with a {@link X509Credential}.
+ * <br>
+ * <p>This method used {@link PvpConstants.DEFAULT_SIGNING_METHODE_RSA}
+ * or {@link PvpConstants.DEFAULT_SIGNING_METHODE_EC} as algorithm</p>
+ *
+ * @param <T> {@link SignableXMLObject}
+ * @param toSign object that should be signed
+ * @param signingCredential Credentials that should be used for signing
+ * @param injectCertificate true, if certificate should be part of the signature
+ * @return Signed object
+ * @throws SamlSigningException In case of a signing error
+ */
+ public static <T extends SignableXMLObject> T signSamlObject(@Nonnull T toSign,
+ @Nonnull EaafX509Credential signingCredential, boolean injectCertificate) throws SamlSigningException {
+
+ try {
+ final String usedSigAlg = getSignatureAlgorithm(signingCredential,
+ PvpConstants.DEFAULT_SIGNING_METHODE_RSA,
+ PvpConstants.DEFAULT_SIGNING_METHODE_EC);
+
+ final Signature signature = createSignature(signingCredential, usedSigAlg, injectCertificate);
+ toSign.setSignature(signature);
+
+ final String digestAlgorithm = getDigestAlgorithm(usedSigAlg);
+ final List<ContentReference> contentReferences = signature.getContentReferences();
+ if (!CollectionUtils.isEmpty(contentReferences)) {
+ ((SAMLObjectContentReference) contentReferences.get(0)).setDigestAlgorithm(digestAlgorithm);
+
+ } else {
+ log.error("Unable to set DigestMethodAlgorithm - algorithm {} not set", digestAlgorithm);
+
+ }
+
+ log.trace("Marshall samlToken.");
+ XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(toSign).marshall(toSign);
+
+ log.trace("Sign samlToken.");
+ Signer.signObject(signature);
+
+ return toSign;
+
+ } catch (final SignatureException | MarshallingException | SecurityException e) {
+ throw new SamlSigningException("internal.pvp.96",
+ new Object[] {signingCredential.getEntityId(), e.getMessage()}, e);
+
+ }
+
+ }
+
+ /**
+ * Select signature algorithm for a given credential.
+ *
+ * @param credentials {@link X509Credential} that will be used for signing
+ * @param rsaSigAlgorithm RSA based signing algorithm that should be used in case of RSA credential
+ * @param ecSigAlgorithm EC based signing algorithm that should be used in case of RSA credential
+ * @return either the rsaSigAlgorithm or the ecSigAlgorithm
+ * @throws SamlSigningException In case of an unsupported credential
+ */
+ public static String getSignatureAlgorithm(X509Credential credentials,
+ String rsaSigAlgorithm, String ecSigAlgorithm) throws SamlSigningException {
+ final PrivateKey privatekey = credentials.getPrivateKey();
+ if (privatekey instanceof RSAPrivateKey) {
+ return rsaSigAlgorithm;
+
+ } else if (privatekey instanceof ECPrivateKey) {
+ return ecSigAlgorithm;
+
+ } else {
+ log.warn("Could NOT evaluate the Private-Key type from " + credentials.getEntityId()
+ + " credential.");
+ throw new SamlSigningException("internal.pvp.97",
+ new Object[] {credentials.getEntityId(), privatekey.getClass().getName()});
+
+ }
+ }
+
+ /**
+ * Select a digest algorithm for a already selected signing algorithm.
+ *
+ * @param signatureAlgorithmName Signing algorithm that will be used
+ * @return Digest algorithm identifier
+ */
+ public static String getDigestAlgorithm(String signatureAlgorithmName) {
+ if (StringUtils.isBlank(signatureAlgorithmName)) {
+ return PvpConstants.DEFAULT_DIGESTMETHODE;
+ }
+
+ final String canonicalAlgorithm = signatureAlgorithmName.trim();
+ final String digestAlgorithm = PvpConstants.SIGNATURE_TO_DIGEST_ALGORITHM_MAP.get(canonicalAlgorithm);
+ if (null != digestAlgorithm) {
+ return digestAlgorithm;
+
+ }
+
+ log.warn("Signing algorithm: {} does not contain a known digist algorithm. Use: {} as default",
+ signatureAlgorithmName, PvpConstants.DEFAULT_DIGESTMETHODE);
+ return PvpConstants.DEFAULT_DIGESTMETHODE;
+
+ }
+
+ /**
+ * Get a {@link KeyInfoGenerator} that injects key information into XML signature.
+ *
+ * @param credential @link X509Credential} that will be used for signing
+ * @param injectCertificate Set <code>true</code> if the certificate should be added to KeyInfo
+ * @return Generator for a XML signature key-information
+ */
+ public static KeyInfoGenerator getKeyInfoGenerator(X509Credential credential, boolean injectCertificate) {
+ //OpenSAML3 only support RSA and DSA for direct key injection
+ KeyInfoGeneratorFactory keyInfoGenFac = null;
+ if (injectCertificate || credential.getPublicKey() instanceof ECPublicKey) {
+ final SignatureSigningConfiguration secConfiguration = SecurityConfigurationSupport
+ .getGlobalSignatureSigningConfiguration();
+ final NamedKeyInfoGeneratorManager keyInfoManager = secConfiguration.getKeyInfoGeneratorManager();
+ final KeyInfoGeneratorManager keyInfoGenManager = keyInfoManager.getDefaultManager();
+ keyInfoGenFac = keyInfoGenManager.getFactory(credential);
+
+ } else {
+ keyInfoGenFac = createKeyInfoWithoutCertificate(credential);
+
+ }
+
+ return keyInfoGenFac.newInstance();
+
+ }
+
+
+ /**
* Create a SAML2 object.
*
- * @param <T> SAML2 object class
+ * @param <T> SAML2 object class
* @param clazz object class
* @return SAML2 object
*/
public static <T> T createSamlObject(final Class<T> clazz) {
try {
final XMLObjectBuilderFactory builderFactory =
- org.opensaml.xml.Configuration.getBuilderFactory();
+ XMLObjectProviderRegistrySupport.getBuilderFactory();
final QName defaultElementName =
(QName) clazz.getDeclaredField("DEFAULT_ELEMENT_NAME").get(null);
@@ -119,7 +277,7 @@ public class Saml2Utils {
throws IOException, MarshallingException, TransformerException {
final Document document = builder.newDocument();
final Marshaller out =
- org.opensaml.xml.Configuration.getMarshallerFactory().getMarshaller(object);
+ XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(object);
out.marshall(object, document);
return document;
}
@@ -132,7 +290,7 @@ public class Saml2Utils {
public static Status getSuccessStatus() {
final Status status = Saml2Utils.createSamlObject(Status.class);
final StatusCode statusCode = Saml2Utils.createSamlObject(StatusCode.class);
- statusCode.setValue(StatusCode.SUCCESS_URI);
+ statusCode.setValue(StatusCode.SUCCESS);
status.setStatusCode(statusCode);
return status;
}
@@ -165,7 +323,7 @@ public class Saml2Utils {
* @return
*/
public static Envelope buildSoap11Envelope(final XMLObject payload) {
- final XMLObjectBuilderFactory bf = org.opensaml.xml.Configuration.getBuilderFactory();
+ final XMLObjectBuilderFactory bf = XMLObjectProviderRegistrySupport.getBuilderFactory();
final Envelope envelope = (Envelope) bf.getBuilder(Envelope.DEFAULT_ELEMENT_NAME)
.buildObject(Envelope.DEFAULT_ELEMENT_NAME);
final Body body =
@@ -211,7 +369,8 @@ public class Saml2Utils {
*/
public static void schemeValidation(final XMLObject xmlObject) throws Exception {
try {
- final Schema test = SAMLSchemaBuilder.getSAML11Schema();
+
+ final Schema test = schemaBuilder.getSAMLSchema();
final Validator val = test.newValidator();
final DOMSource source = new DOMSource(xmlObject.getDOM());
val.validate(source);
@@ -227,11 +386,37 @@ public class Saml2Utils {
private static XMLObject createAttributeValue(final QName attributeValueType,
final String value) {
- final XSStringBuilder stringBuilder = (XSStringBuilder) org.opensaml.xml.Configuration
+ final XSStringBuilder stringBuilder = (XSStringBuilder) XMLObjectProviderRegistrySupport
.getBuilderFactory().getBuilder(XSString.TYPE_NAME);
final XSString stringValue = stringBuilder.buildObject(attributeValueType, XSString.TYPE_NAME);
stringValue.setValue(value);
return stringValue;
}
+
+ private static Signature createSignature(X509Credential signingCredential,
+ String usedSigAlg, boolean injectCertificate)
+ throws SecurityException, SamlSigningException {
+ log.trace("Generating OpenSAML signature object ... ");
+ final Signature signature = (Signature) XMLObjectProviderRegistrySupport.getBuilderFactory()
+ .getBuilder(Signature.DEFAULT_ELEMENT_NAME)
+ .buildObject(Signature.DEFAULT_ELEMENT_NAME);
+ signature.setSigningCredential(signingCredential);
+ signature.setSignatureAlgorithm(usedSigAlg);
+ final KeyInfo keyInfo = getKeyInfoGenerator(signingCredential, injectCertificate).generate(signingCredential);
+ signature.setKeyInfo(keyInfo);
+ signature.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
+ return signature;
+
+ }
+
+ private static KeyInfoGeneratorFactory createKeyInfoWithoutCertificate(X509Credential credential) {
+ final KeyInfoGeneratorFactory keyInfoGenFac = new BasicKeyInfoGeneratorFactory();
+ ((BasicKeyInfoGeneratorFactory)keyInfoGenFac).setEmitPublicKeyValue(true);
+ ((BasicKeyInfoGeneratorFactory)keyInfoGenFac).setEmitEntityIDAsKeyName(true);
+ ((BasicKeyInfoGeneratorFactory)keyInfoGenFac).setEmitKeyNames(true);
+ ((BasicKeyInfoGeneratorFactory)keyInfoGenFac).setEmitPublicDEREncodedKeyValue(true);
+ return keyInfoGenFac;
+ }
+
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/EaafUriCompare.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/EaafUriCompare.java
index ca37d6e5..9015c40b 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/EaafUriCompare.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/EaafUriCompare.java
@@ -19,10 +19,11 @@
package at.gv.egiz.eaaf.modules.pvp2.impl.validation;
-import org.opensaml.common.binding.decoding.URIComparator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import net.shibboleth.utilities.java.support.net.URIComparator;
+
public class EaafUriCompare implements URIComparator {
private static final Logger log = LoggerFactory.getLogger(EaafUriCompare.class);
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/TrustEngineFactory.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/TrustEngineFactory.java
index 6497ce06..1591198c 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/TrustEngineFactory.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/TrustEngineFactory.java
@@ -22,41 +22,39 @@ package at.gv.egiz.eaaf.modules.pvp2.impl.validation;
import java.util.ArrayList;
import java.util.List;
-import org.opensaml.saml2.metadata.provider.MetadataProvider;
-import org.opensaml.security.MetadataCredentialResolver;
-import org.opensaml.xml.security.keyinfo.BasicProviderKeyInfoCredentialResolver;
-import org.opensaml.xml.security.keyinfo.KeyInfoCredentialResolver;
-import org.opensaml.xml.security.keyinfo.KeyInfoProvider;
-import org.opensaml.xml.security.keyinfo.provider.DSAKeyValueProvider;
-import org.opensaml.xml.security.keyinfo.provider.InlineX509DataProvider;
-import org.opensaml.xml.security.keyinfo.provider.RSAKeyValueProvider;
-import org.opensaml.xml.signature.SignatureTrustEngine;
-import org.opensaml.xml.signature.impl.ExplicitKeySignatureTrustEngine;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+
+import org.opensaml.saml.metadata.resolver.impl.PredicateRoleDescriptorResolver;
+import org.opensaml.saml.security.impl.MetadataCredentialResolver;
+import org.opensaml.xmlsec.keyinfo.impl.BasicProviderKeyInfoCredentialResolver;
+import org.opensaml.xmlsec.keyinfo.impl.KeyInfoProvider;
+import org.opensaml.xmlsec.keyinfo.impl.provider.DSAKeyValueProvider;
+import org.opensaml.xmlsec.keyinfo.impl.provider.InlineX509DataProvider;
+import org.opensaml.xmlsec.keyinfo.impl.provider.RSAKeyValueProvider;
+import org.opensaml.xmlsec.signature.support.SignatureTrustEngine;
+import org.opensaml.xmlsec.signature.support.impl.ExplicitKeySignatureTrustEngine;
public class TrustEngineFactory {
/**
* Get OpenSAML2 TrustEngine.
*
- * @param provider Metadata provider
+ * @param mdResolver Metadata provider
* @return
*/
public static SignatureTrustEngine getSignatureKnownKeysTrustEngine(
- final MetadataProvider provider) {
- MetadataCredentialResolver resolver;
-
- resolver = new MetadataCredentialResolver(provider);
+ final IPvp2MetadataProvider mdResolver) {
+ final MetadataCredentialResolver resolver = new MetadataCredentialResolver();
+ resolver.setRoleDescriptorResolver(new PredicateRoleDescriptorResolver(mdResolver));
final List<KeyInfoProvider> keyInfoProvider = new ArrayList<>();
keyInfoProvider.add(new DSAKeyValueProvider());
keyInfoProvider.add(new RSAKeyValueProvider());
keyInfoProvider.add(new InlineX509DataProvider());
- final KeyInfoCredentialResolver keyInfoResolver =
- new BasicProviderKeyInfoCredentialResolver(keyInfoProvider);
-
final ExplicitKeySignatureTrustEngine engine =
- new ExplicitKeySignatureTrustEngine(resolver, keyInfoResolver);
+ new ExplicitKeySignatureTrustEngine(resolver,
+ new BasicProviderKeyInfoCredentialResolver(keyInfoProvider));
return engine;
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/AbstractMetadataSignatureFilter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/AbstractMetadataSignatureFilter.java
index d1eb66a3..c28dd7fb 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/AbstractMetadataSignatureFilter.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/AbstractMetadataSignatureFilter.java
@@ -23,22 +23,24 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
-import org.opensaml.saml2.metadata.EntitiesDescriptor;
-import org.opensaml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml2.metadata.provider.MetadataFilter;
-import org.opensaml.xml.XMLObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import javax.annotation.Nullable;
import at.gv.egiz.eaaf.core.exceptions.EaafException;
import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException;
import at.gv.egiz.eaaf.modules.pvp2.exception.SignatureValidationException;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.saml.metadata.resolver.filter.MetadataFilter;
+import org.opensaml.saml.saml2.metadata.EntitiesDescriptor;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
public abstract class AbstractMetadataSignatureFilter implements MetadataFilter {
private static final Logger log = LoggerFactory.getLogger(AbstractMetadataSignatureFilter.class);
@Override
- public void doFilter(final XMLObject metadata) throws SignatureValidationException {
+ public XMLObject filter(@Nullable final XMLObject metadata) throws SignatureValidationException {
try {
if (metadata instanceof EntitiesDescriptor) {
final EntitiesDescriptor entitiesDescriptor = (EntitiesDescriptor) metadata;
@@ -68,6 +70,9 @@ public abstract class AbstractMetadataSignatureFilter implements MetadataFilter
throw new SignatureValidationException(e);
}
+
+ return metadata;
+
}
/**
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/PvpEntityCategoryFilter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/PvpEntityCategoryFilter.java
index 66c3fb9e..efbeb7e5 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/PvpEntityCategoryFilter.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/PvpEntityCategoryFilter.java
@@ -22,29 +22,28 @@ package at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata;
import java.util.ArrayList;
import java.util.List;
-import org.opensaml.common.xml.SAMLConstants;
-import org.opensaml.saml2.common.Extensions;
-import org.opensaml.saml2.core.Attribute;
-import org.opensaml.saml2.metadata.AttributeConsumingService;
-import org.opensaml.saml2.metadata.EntitiesDescriptor;
-import org.opensaml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml2.metadata.LocalizedString;
-import org.opensaml.saml2.metadata.RequestedAttribute;
-import org.opensaml.saml2.metadata.SPSSODescriptor;
-import org.opensaml.saml2.metadata.ServiceName;
-import org.opensaml.saml2.metadata.provider.FilterException;
-import org.opensaml.saml2.metadata.provider.MetadataFilter;
-import org.opensaml.samlext.saml2mdattr.EntityAttributes;
-import org.opensaml.xml.XMLObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import at.gv.egiz.eaaf.core.impl.data.Triple;
import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException;
import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpAttributeBuilder;
import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.ext.saml2mdattr.EntityAttributes;
+import org.opensaml.saml.metadata.resolver.filter.FilterException;
+import org.opensaml.saml.metadata.resolver.filter.MetadataFilter;
+import org.opensaml.saml.saml2.core.Attribute;
+import org.opensaml.saml.saml2.metadata.AttributeConsumingService;
+import org.opensaml.saml.saml2.metadata.EntitiesDescriptor;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml.saml2.metadata.Extensions;
+import org.opensaml.saml.saml2.metadata.RequestedAttribute;
+import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
+import org.opensaml.saml.saml2.metadata.ServiceName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* Metadata filter that inject requested attributes based on Metadata
* EntityCategories.
@@ -76,7 +75,7 @@ public class PvpEntityCategoryFilter implements MetadataFilter {
* .XMLObject)
*/
@Override
- public void doFilter(final XMLObject metadata) throws FilterException {
+ public XMLObject filter(final XMLObject metadata) throws FilterException {
if (isUsed) {
log.trace("Map PVP EntityCategory to single PVP Attributes ... ");
@@ -109,8 +108,11 @@ public class PvpEntityCategoryFilter implements MetadataFilter {
} else {
log.trace("Filter to map PVP EntityCategory to single PVP Attributes is deactivated");
+
}
+ return metadata;
+
}
private void resolveEntityCategoriesToAttributes(final EntityDescriptor metadata) {
@@ -190,7 +192,8 @@ public class PvpEntityCategoryFilter implements MetadataFilter {
attributeService.setIndex(0);
attributeService.setIsDefault(true);
final ServiceName serviceName = Saml2Utils.createSamlObject(ServiceName.class);
- serviceName.setName(new LocalizedString("Default Service", "en"));
+ serviceName.setValue("Default Service");
+ serviceName.setXMLLang("en");
attributeService.getNames().add(serviceName);
if (attrList != null && !attrList.isEmpty()) {
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SchemaValidationFilter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SchemaValidationFilter.java
index 6dcc3234..73a11c49 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SchemaValidationFilter.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SchemaValidationFilter.java
@@ -23,20 +23,23 @@ import javax.xml.transform.dom.DOMSource;
import javax.xml.validation.Schema;
import javax.xml.validation.Validator;
-import org.opensaml.common.xml.SAMLSchemaBuilder;
-import org.opensaml.saml2.metadata.provider.FilterException;
-import org.opensaml.saml2.metadata.provider.MetadataFilter;
-import org.opensaml.xml.XMLObject;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException;
+
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.saml.common.xml.SAMLSchemaBuilder;
+import org.opensaml.saml.common.xml.SAMLSchemaBuilder.SAML1Version;
+import org.opensaml.saml.metadata.resolver.filter.FilterException;
+import org.opensaml.saml.metadata.resolver.filter.MetadataFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
-import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException;
-
public class SchemaValidationFilter implements MetadataFilter {
private static final Logger log = LoggerFactory.getLogger(SchemaValidationFilter.class);
private boolean isActive = true;
+ private static SAMLSchemaBuilder schemaBuilder = new SAMLSchemaBuilder(SAML1Version.SAML_11);
+
public SchemaValidationFilter() {
}
@@ -53,18 +56,17 @@ public class SchemaValidationFilter implements MetadataFilter {
* .XMLObject)
*/
@Override
- public void doFilter(final XMLObject arg0) throws FilterException {
+ public XMLObject filter(final XMLObject arg0) throws FilterException {
String errString = null;
if (isActive) {
try {
- final Schema test = SAMLSchemaBuilder.getSAML11Schema();
+ final Schema test = schemaBuilder.getSAMLSchema();
final Validator val = test.newValidator();
final DOMSource source = new DOMSource(arg0.getDOM());
val.validate(source);
log.info("Metadata Schema validation check done OK");
- return;
} catch (final SAXException e) {
if (log.isDebugEnabled() || log.isTraceEnabled()) {
@@ -91,8 +93,10 @@ public class SchemaValidationFilter implements MetadataFilter {
} else {
log.info("Metadata Schema validation check is DEACTIVATED!");
+
}
+ return arg0;
}
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/AbstractRequestSignedSecurityPolicyRule.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/AbstractRequestSignedSecurityPolicyRule.java
index 6d78b775..380e735c 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/AbstractRequestSignedSecurityPolicyRule.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/AbstractRequestSignedSecurityPolicyRule.java
@@ -24,28 +24,27 @@ import javax.xml.transform.dom.DOMSource;
import javax.xml.validation.Schema;
import javax.xml.validation.Validator;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException;
+
import org.apache.commons.lang3.StringUtils;
-import org.opensaml.common.SignableSAMLObject;
-import org.opensaml.common.xml.SAMLConstants;
-import org.opensaml.common.xml.SAMLSchemaBuilder;
+import org.opensaml.core.criterion.EntityIdCriterion;
+import org.opensaml.saml.common.SignableSAMLObject;
+import org.opensaml.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.common.xml.SAMLSchemaBuilder;
+import org.opensaml.saml.common.xml.SAMLSchemaBuilder.SAML1Version;
+import org.opensaml.saml.security.impl.SAMLSignatureProfileValidator;
import org.opensaml.security.MetadataCriteria;
-import org.opensaml.security.SAMLSignatureProfileValidator;
-import org.opensaml.ws.message.MessageContext;
+import org.opensaml.security.credential.UsageType;
+import org.opensaml.security.criteria.UsageCriterion;
import org.opensaml.ws.security.SecurityPolicyException;
import org.opensaml.ws.security.SecurityPolicyRule;
-import org.opensaml.xml.XMLObject;
-import org.opensaml.xml.security.CriteriaSet;
-import org.opensaml.xml.security.credential.UsageType;
-import org.opensaml.xml.security.criteria.EntityIDCriteria;
-import org.opensaml.xml.security.criteria.UsageCriteria;
-import org.opensaml.xml.signature.SignatureTrustEngine;
-import org.opensaml.xml.validation.ValidationException;
+import org.opensaml.xmlsec.signature.support.SignatureTrustEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
-import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException;
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
/**
* Signature Policy for SAML2 redirect-binding.
@@ -58,6 +57,8 @@ public abstract class AbstractRequestSignedSecurityPolicyRule implements Securit
private static final Logger log =
LoggerFactory.getLogger(AbstractRequestSignedSecurityPolicyRule.class);
+ private static SAMLSchemaBuilder schemaBuilder = new SAMLSchemaBuilder(SAML1Version.SAML_11);
+
private SignatureTrustEngine trustEngine = null;
private QName peerEntityRole = null;
@@ -136,9 +137,9 @@ public abstract class AbstractRequestSignedSecurityPolicyRule implements Securit
}
final CriteriaSet criteriaSet = new CriteriaSet();
- criteriaSet.add(new EntityIDCriteria(context.getInboundMessageIssuer()));
+ criteriaSet.add(new EntityIdCriterion(context.getInboundMessageIssuer()));
criteriaSet.add(new MetadataCriteria(peerEntityRole, SAMLConstants.SAML20P_NS));
- criteriaSet.add(new UsageCriteria(UsageType.SIGNING));
+ criteriaSet.add(new UsageCriterion(UsageType.SIGNING));
try {
if (!trustEngine.validate(samlObj.getSignature(), criteriaSet)) {
@@ -164,7 +165,7 @@ public abstract class AbstractRequestSignedSecurityPolicyRule implements Securit
String err = null;
try {
- final Schema test = SAMLSchemaBuilder.getSAML11Schema();
+ final Schema test = schemaBuilder.getSAMLSchema();
final Validator val = test.newValidator();
val.validate(new DOMSource(source));
log.debug("Schema validation check done OK");
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafMessageContextInitializationHandler.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafMessageContextInitializationHandler.java
new file mode 100644
index 00000000..2672bef2
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafMessageContextInitializationHandler.java
@@ -0,0 +1,23 @@
+package at.gv.egiz.eaaf.modules.pvp2.impl.verification;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.handler.AbstractMessageHandler;
+import org.opensaml.messaging.handler.MessageHandlerException;
+import org.opensaml.saml.common.SAMLObject;
+import org.opensaml.saml.common.messaging.context.SAMLMessageInfoContext;
+import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class EaafMessageContextInitializationHandler extends AbstractMessageHandler<SAMLObject> {
+
+ @Override
+ protected void doInvoke(MessageContext<SAMLObject> messageContext) throws MessageHandlerException {
+ log.trace("Injecting sub-context to SAML2 message ... ");
+ messageContext.addSubcontext(new SAMLPeerEntityContext());
+ messageContext.addSubcontext(new SAMLMessageInfoContext());
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpAuthRequestSignedRole.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpAuthRequestSignedRole.java
deleted file mode 100644
index 42d7d6a1..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpAuthRequestSignedRole.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
- * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
- * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
- * compliance with the Licence. You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the Licence
- * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the Licence for the specific language governing permissions and limitations under
- * the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text file for details on the
- * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
- * works that you distribute must include a readable copy of the "NOTICE" text file.
-*/
-
-package at.gv.egiz.eaaf.modules.pvp2.impl.verification;
-
-import java.util.List;
-
-import org.opensaml.common.binding.SAMLMessageContext;
-import org.opensaml.saml2.binding.security.SAML2AuthnRequestsSignedRule;
-import org.opensaml.ws.transport.http.HTTPInTransport;
-import org.opensaml.xml.util.DatatypeHelper;
-
-public class PvpAuthRequestSignedRole extends SAML2AuthnRequestsSignedRule {
-
- @Override
- protected boolean isMessageSigned(final SAMLMessageContext messageContext) {
- // This handles HTTP-Redirect and HTTP-POST-SimpleSign bindings.
- final HTTPInTransport inTransport =
- (HTTPInTransport) messageContext.getInboundMessageTransport();
-
- // Check signature parameter exists only once and is not empty
- final List<String> sigParam = inTransport.getParameterValues("Signature");
- final boolean isValidSigned = sigParam.size() == 1 && !DatatypeHelper.isEmpty(sigParam.get(0));
-
- // Check signature-algorithm parameter exists only once and is not empty
- final List<String> sigAlgParam = inTransport.getParameterValues("SigAlg");
- final boolean isValidSigAlgExists =
- sigAlgParam.size() == 1 && !DatatypeHelper.isEmpty(sigAlgParam.get(0));
-
- // Check signature-content parameter exists only once and is not empty
- final List<String> samlReqParam = inTransport.getParameterValues("SAMLRequest");
- final List<String> samlRespParam = inTransport.getParameterValues("SAMLResponse");
- final boolean isValidContent =
- (samlReqParam.size() == 1 && !DatatypeHelper.isEmpty(samlReqParam.get(0))
- || samlRespParam.size() == 1 && !DatatypeHelper.isEmpty(samlRespParam.get(0)))
- && !(samlReqParam.size() == 1 && samlRespParam.size() == 1);
-
- return isValidSigned && isValidSigAlgExists && isValidContent;
-
- }
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSamlMessageHandlerChain.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSamlMessageHandlerChain.java
new file mode 100644
index 00000000..e43d0423
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSamlMessageHandlerChain.java
@@ -0,0 +1,71 @@
+package at.gv.egiz.eaaf.modules.pvp2.impl.verification;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.handler.MessageHandler;
+import org.opensaml.messaging.handler.MessageHandlerChain;
+import org.opensaml.messaging.handler.MessageHandlerException;
+import org.opensaml.saml.common.SAMLObject;
+
+import lombok.extern.slf4j.Slf4j;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+
+@Slf4j
+public class PvpSamlMessageHandlerChain implements MessageHandlerChain<SAMLObject> {
+ private final List<MessageHandler<SAMLObject>> handlers = new ArrayList<>();
+ private boolean isInitialized = false;
+
+ @Override
+ public void invoke(MessageContext<SAMLObject> messageContext) throws MessageHandlerException {
+ if (!isInitialized) {
+ throw new RuntimeException("Component: "
+ + PvpSamlMessageHandlerChain.class.getName() + " not initialized");
+
+ }
+ for (final MessageHandler<SAMLObject> handler : getHandlers()) {
+ log.trace("Initializing SAML message handler: {}", handler.getClass().getName());
+ handler.invoke(messageContext);
+
+ }
+
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return isInitialized;
+
+ }
+
+ @Override
+ public void initialize() throws ComponentInitializationException {
+ if (!isInitialized) {
+ for (final MessageHandler<SAMLObject> handler : getHandlers()) {
+ log.trace("Initializing SAML message handler: {}", handler.getClass().getName());
+ handler.initialize();
+
+ }
+
+ isInitialized = true;
+ }
+
+ }
+
+ @Override
+ public List<MessageHandler<SAMLObject>> getHandlers() {
+ return handlers;
+
+ }
+
+ public void addHandler(MessageHandler<SAMLObject> handler) {
+ handlers.add(handler);
+
+ }
+
+ public void addHandlers(List<MessageHandler<SAMLObject>> handlerList) {
+ handlers.addAll(handlerList);
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSignedRequestPolicyRule.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSignedRequestPolicyRule.java
index c7a43b0b..9c02221c 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSignedRequestPolicyRule.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSignedRequestPolicyRule.java
@@ -21,13 +21,12 @@ package at.gv.egiz.eaaf.modules.pvp2.impl.verification;
import javax.xml.namespace.QName;
-import org.opensaml.common.SignableSAMLObject;
-import org.opensaml.saml2.metadata.provider.MetadataProvider;
-import org.opensaml.xml.XMLObject;
-import org.opensaml.xml.signature.SignatureTrustEngine;
-
import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider;
+import org.opensaml.saml.common.SignableSAMLObject;
+import org.opensaml.saml2.metadata.provider.MetadataProvider;
+import org.opensaml.xmlsec.signature.support.SignatureTrustEngine;
+
public class PvpSignedRequestPolicyRule extends AbstractRequestSignedSecurityPolicyRule {
private IRefreshableMetadataProvider metadataProvider = null;
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SamlVerificationEngine.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SamlVerificationEngine.java
index df91ce53..658dfe16 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SamlVerificationEngine.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SamlVerificationEngine.java
@@ -24,43 +24,44 @@ import javax.xml.transform.dom.DOMSource;
import javax.xml.validation.Schema;
import javax.xml.validation.Validator;
-import org.apache.commons.lang3.StringUtils;
-import org.opensaml.common.xml.SAMLConstants;
-import org.opensaml.common.xml.SAMLSchemaBuilder;
-import org.opensaml.saml2.core.RequestAbstractType;
-import org.opensaml.saml2.core.StatusResponseType;
-import org.opensaml.saml2.metadata.IDPSSODescriptor;
-import org.opensaml.saml2.metadata.SPSSODescriptor;
-import org.opensaml.security.MetadataCriteria;
-import org.opensaml.security.SAMLSignatureProfileValidator;
-import org.opensaml.xml.security.CriteriaSet;
-import org.opensaml.xml.security.credential.UsageType;
-import org.opensaml.xml.security.criteria.EntityIDCriteria;
-import org.opensaml.xml.security.criteria.UsageCriteria;
-import org.opensaml.xml.signature.SignatureTrustEngine;
-import org.opensaml.xml.validation.ValidationException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.w3c.dom.Element;
-import org.xml.sax.SAXException;
-
import at.gv.egiz.eaaf.core.exceptions.EaafProtocolException;
import at.gv.egiz.eaaf.core.exceptions.InvalidProtocolRequestException;
-import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider;
import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException;
import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage;
import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileRequest;
import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileResponse;
-@Service("SAMLVerificationEngine")
+import org.apache.commons.lang3.StringUtils;
+import org.opensaml.core.criterion.EntityIdCriterion;
+import org.opensaml.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.common.xml.SAMLSchemaBuilder;
+import org.opensaml.saml.common.xml.SAMLSchemaBuilder.SAML1Version;
+import org.opensaml.saml.criterion.EntityRoleCriterion;
+import org.opensaml.saml.criterion.ProtocolCriterion;
+import org.opensaml.saml.saml2.core.RequestAbstractType;
+import org.opensaml.saml.saml2.core.StatusResponseType;
+import org.opensaml.saml.saml2.metadata.IDPSSODescriptor;
+import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
+import org.opensaml.saml.security.impl.SAMLSignatureProfileValidator;
+import org.opensaml.security.credential.UsageType;
+import org.opensaml.security.criteria.UsageCriterion;
+import org.opensaml.xmlsec.signature.support.SignatureException;
+import org.opensaml.xmlsec.signature.support.SignatureTrustEngine;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+import lombok.extern.slf4j.Slf4j;
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+
+@Slf4j
public class SamlVerificationEngine {
- private static final Logger log = LoggerFactory.getLogger(SamlVerificationEngine.class);
+ private static SAMLSchemaBuilder schemaBuilder = new SAMLSchemaBuilder(SAML1Version.SAML_11);
@Autowired(required = true)
- IPvpMetadataProvider metadataProvider;
+ IPvp2MetadataProvider metadataProvider;
/**
* Verify signature of a signed SAML2 object.
@@ -72,7 +73,7 @@ public class SamlVerificationEngine {
* @throws Exception In case of a general error
*/
public void verify(final InboundMessage msg, final SignatureTrustEngine sigTrustEngine)
- throws org.opensaml.xml.security.SecurityException, Exception {
+ throws SecurityException, Exception {
try {
if (msg instanceof PvpSProfileRequest
&& ((PvpSProfileRequest) msg).getSamlRequest() instanceof RequestAbstractType) {
@@ -135,7 +136,7 @@ public class SamlVerificationEngine {
profileValidator.validate(samlObj.getSignature());
performSchemaValidation(samlObj.getDOM());
- } catch (final ValidationException e) {
+ } catch (final SignatureException e) {
log.warn("Signature is not conform to SAML signature profile", e);
throw new InvalidProtocolRequestException("pvp2.21", new Object[] {});
@@ -145,15 +146,16 @@ public class SamlVerificationEngine {
}
final CriteriaSet criteriaSet = new CriteriaSet();
- criteriaSet.add(new EntityIDCriteria(samlObj.getIssuer().getValue()));
- criteriaSet.add(new MetadataCriteria(defaultElementName, SAMLConstants.SAML20P_NS));
- criteriaSet.add(new UsageCriteria(UsageType.SIGNING));
+ criteriaSet.add(new EntityIdCriterion(samlObj.getIssuer().getValue()));
+ criteriaSet.add(new ProtocolCriterion(SAMLConstants.SAML20P_NS));
+ criteriaSet.add(new EntityRoleCriterion(defaultElementName));
+ criteriaSet.add(new UsageCriterion(UsageType.SIGNING));
try {
if (!sigTrustEngine.validate(samlObj.getSignature(), criteriaSet)) {
throw new InvalidProtocolRequestException("pvp2.21", new Object[] {});
}
- } catch (final org.opensaml.xml.security.SecurityException e) {
+ } catch (final org.opensaml.security.SecurityException e) {
log.warn("PVP2x message signature validation FAILED.", e);
throw new InvalidProtocolRequestException("pvp2.21", new Object[] {});
}
@@ -166,7 +168,7 @@ public class SamlVerificationEngine {
profileValidator.validate(samlObj.getSignature());
performSchemaValidation(samlObj.getDOM());
- } catch (final ValidationException e) {
+ } catch (final SignatureException e) {
log.warn("Signature is not conform to SAML signature profile", e);
throw new InvalidProtocolRequestException("pvp2.21", new Object[] {});
@@ -176,16 +178,16 @@ public class SamlVerificationEngine {
}
final CriteriaSet criteriaSet = new CriteriaSet();
- criteriaSet.add(new EntityIDCriteria(samlObj.getIssuer().getValue()));
- criteriaSet
- .add(new MetadataCriteria(SPSSODescriptor.DEFAULT_ELEMENT_NAME, SAMLConstants.SAML20P_NS));
- criteriaSet.add(new UsageCriteria(UsageType.SIGNING));
+ criteriaSet.add(new EntityIdCriterion(samlObj.getIssuer().getValue()));
+ criteriaSet.add(new ProtocolCriterion(SAMLConstants.SAML20P_NS));
+ criteriaSet.add(new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME));
+ criteriaSet.add(new UsageCriterion(UsageType.SIGNING));
try {
if (!sigTrustEngine.validate(samlObj.getSignature(), criteriaSet)) {
throw new InvalidProtocolRequestException("pvp2.21", new Object[] {});
}
- } catch (final org.opensaml.xml.security.SecurityException e) {
+ } catch (final org.opensaml.security.SecurityException e) {
log.warn("PVP2x message signature validation FAILED.", e);
throw new InvalidProtocolRequestException("pvp2.21", new Object[] {});
}
@@ -195,7 +197,7 @@ public class SamlVerificationEngine {
String err = null;
try {
- final Schema test = SAMLSchemaBuilder.getSAML11Schema();
+ final Schema test = schemaBuilder.getSAMLSchema();
final Validator val = test.newValidator();
val.validate(new DOMSource(source));
log.debug("Schema validation check done OK");
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/eaaf_pvp.beans.xml b/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/eaaf_pvp.beans.xml
index ee4d3864..2d5dc6ea 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/eaaf_pvp.beans.xml
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/eaaf_pvp.beans.xml
@@ -10,16 +10,19 @@
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
- <bean id="PVPMetadataBuilder"
- class="at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpMetadataBuilder" />
-
- <bean id="PVPPOSTBinding"
- class="at.gv.egiz.eaaf.modules.pvp2.impl.binding.PostBinding" />
+ <bean id="pvpLogMessageSource"
+ class="at.gv.egiz.eaaf.modules.pvp2.impl.logging.PvpModuleMessageSource" />
- <bean id="PVPRedirectBinding"
- class="at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding" />
+ <bean id="PVPMetadataBuilder"
+ class="at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpMetadataBuilder" />
- <bean id="PVPSOAPBinding"
- class="at.gv.egiz.eaaf.modules.pvp2.impl.binding.SoapBinding" />
+ <bean id="PvpPostBinding"
+ class="at.gv.egiz.eaaf.modules.pvp2.impl.binding.PostBinding" />
+
+ <bean id="PvpRedirectBinding"
+ class="at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding" />
+
+ <bean id="PvpSoapBinding"
+ class="at.gv.egiz.eaaf.modules.pvp2.impl.binding.SoapBinding" />
</beans> \ No newline at end of file
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/messages/pvp_messages.properties b/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/messages/pvp_messages.properties
new file mode 100644
index 00000000..6e647bd0
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/messages/pvp_messages.properties
@@ -0,0 +1,12 @@
+internal.pvp.00=KeyStore: {0} Key with alias: {0} not found or contains no PrivateKey.
+internal.pvp.01=KeyStore: {0} contains an unsupported key with alias: {1}
+internal.pvp.02=PVP message contains no signature.
+
+internal.pvp.95=OpenSAML {0}-binding message {1} failed. Reason: {2}
+internal.pvp.96=OpenSAML signing FAILED with key: {0}. Reason: {1}
+internal.pvp.97=Key with EntityIdentifier: {0} has an unsupported type: {1}
+internal.pvp.98=PVP module has an internal error. Reason: {0}
+internal.pvp.99=PVP module has an generic internal error.
+
+
+
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/PostBindingTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/PostBindingTest.java
new file mode 100644
index 00000000..6adce26e
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/PostBindingTest.java
@@ -0,0 +1,448 @@
+package at.gv.egiz.eaaf.modules.pvp2.test.binding;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Base64;
+import java.util.Map;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiBuilderConfiguration;
+import at.gv.egiz.eaaf.core.impl.idp.module.gui.DummyGuiBuilderConfigurationFactory;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;
+import at.gv.egiz.eaaf.core.impl.utils.DomUtils;
+import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
+import at.gv.egiz.eaaf.modules.pvp2.impl.binding.PostBinding;
+import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer;
+import at.gv.egiz.eaaf.modules.pvp2.impl.validation.EaafUriCompare;
+import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opensaml.core.config.InitializationException;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.io.Unmarshaller;
+import org.opensaml.core.xml.io.UnmarshallerFactory;
+import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
+import org.opensaml.messaging.decoder.MessageDecodingException;
+import org.opensaml.messaging.encoder.MessageEncodingException;
+import org.opensaml.saml.common.SignableSAMLObject;
+import org.opensaml.saml.saml2.core.RequestAbstractType;
+import org.opensaml.saml.saml2.core.StatusResponseType;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.net.URIComparator;
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration({"/spring/test_eaaf_pvp.beans.xml"})
+@TestPropertySource(locations = {"/config/config_1.props"})
+public class PostBindingTest {
+
+ public static final String HTTP_FORM_RELAYSTATE = "RelayState=";
+ public static final String HTTP_FORM_SAMLREQ = "SAMLRequest=";
+ public static final String HTTP_FORM_SAMLRESP = "SAMLResponse=";
+
+ @Autowired private PostBinding bindingImpl;
+ @Autowired private DummyCredentialProvider credentialProvider;
+ @Autowired private DummyGuiBuilderConfigurationFactory guiBuilderFactory;
+
+ protected MockHttpServletRequest httpReq;
+ protected MockHttpServletResponse httpResp;
+ protected IRequest pendingReq;
+
+ @BeforeClass
+ public static void classInitializer() throws InitializationException, ComponentInitializationException {
+ EaafOpenSaml3xInitializer.eaafInitialize();
+
+ }
+
+ /**
+ * Test initializer.
+ *
+ */
+ @Before
+ public void initialize() {
+ httpReq = new MockHttpServletRequest();
+ httpResp = new MockHttpServletResponse();
+
+ pendingReq = new TestRequestImpl();
+
+ }
+
+ @Test
+ public void checkCanHandle() {
+ httpReq.setMethod("POST");
+ Assert.assertTrue("Wrong canHandle result", bindingImpl.handleDecode("Post", httpReq));
+ Assert.assertFalse("Wrong canHandle result", bindingImpl.handleDecode("Redirect", httpReq));
+
+ httpReq.setMethod("GET");
+ Assert.assertFalse("Wrong canHandle result", bindingImpl.handleDecode("Post", httpReq));
+ Assert.assertFalse("Wrong canHandle result", bindingImpl.handleDecode("Redirect", httpReq));
+ }
+
+ @Test
+ public void decodeRequestSuccess() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception {
+ final String serviceUrl = "http://testservice.org";
+
+ final IPvp2MetadataProvider metadataProvider = null;
+
+ final boolean isSpEndPoint = false;
+ final URIComparator comparator = new EaafUriCompare(serviceUrl);
+
+ final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray(
+ PostBindingTest.class.getResourceAsStream("/data/AuthRequest_with_sig_1.xml")));
+ httpReq.setMethod("POST");
+ httpReq.addParameter("SAMLRequest", b64AuthnReq);
+
+
+ final InboundMessageInterface msg =
+ bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, comparator);
+
+ Assert.assertNotNull("PVP msg is null", msg);
+ Assert.assertNull("RelayState is not null", msg.getRelayState());
+ Assert.assertNotNull("AuthnReq is null", msg.getInboundMessage());
+ Assert.assertNotNull("EntityId is null", msg.getEntityID());
+ Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg.getEntityID());
+ Assert.assertFalse("Wrong isVerified flag", msg.isVerified());
+
+ }
+
+ @Test
+ public void decodeRequestSuccessWithRelayState() throws MessageDecodingException, SecurityException,
+ IOException, Pvp2Exception {
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = RandomStringUtils.randomAlphanumeric(10);
+
+ final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray(
+ PostBindingTest.class.getResourceAsStream("/data/AuthRequest_with_sig_1.xml")));
+ httpReq.setMethod("POST");
+ httpReq.addParameter("SAMLRequest", b64AuthnReq);
+ httpReq.addParameter("RelayState", relayState);
+
+ final IPvp2MetadataProvider metadataProvider = null;
+
+ final boolean isSpEndPoint = false;
+ final URIComparator comparator = new EaafUriCompare(serviceUrl);
+
+
+ final InboundMessageInterface msg =
+ bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, comparator);
+
+ Assert.assertNotNull("PVP msg is null", msg);
+ Assert.assertNotNull("RelayState is not null", msg.getRelayState());
+ Assert.assertEquals("RelayState not match", relayState, msg.getRelayState());
+ Assert.assertNotNull("AuthnReq is null", msg.getInboundMessage());
+ Assert.assertNotNull("EntityId is null", msg.getEntityID());
+ Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg.getEntityID());
+ Assert.assertFalse("Wrong isVerified flag", msg.isVerified());
+
+ }
+
+ @Test
+ public void decodeResponseSuccess() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception {
+ final String serviceUrl = "http://testservice.org";
+
+ final IPvp2MetadataProvider metadataProvider = null;
+
+ final boolean isSpEndPoint = false;
+ final URIComparator comparator = new EaafUriCompare(serviceUrl);
+
+ final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray(
+ PostBindingTest.class.getResourceAsStream("/data/Response_with_sig_1.xml")));
+ httpReq.setMethod("POST");
+ httpReq.addParameter("SAMLRequest", b64AuthnReq);
+
+
+ final InboundMessageInterface msg =
+ bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, comparator);
+
+ Assert.assertNotNull("PVP msg is null", msg);
+ Assert.assertNull("RelayState is not null", msg.getRelayState());
+ Assert.assertNotNull("Response is null", msg.getInboundMessage());
+ Assert.assertNotNull("EntityId is null", msg.getEntityID());
+ Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata", msg.getEntityID());
+ Assert.assertFalse("Wrong isVerified flag", msg.isVerified());
+
+ }
+
+ @Test
+ public void decodeResponseSuccessWithRelayState() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception {
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = RandomStringUtils.randomAlphanumeric(10);
+
+ final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray(
+ PostBindingTest.class.getResourceAsStream("/data/Response_with_sig_1.xml")));
+ httpReq.setMethod("POST");
+ httpReq.addParameter("SAMLRequest", b64AuthnReq);
+ httpReq.addParameter("RelayState", relayState);
+
+ final IPvp2MetadataProvider metadataProvider = null;
+
+ final boolean isSpEndPoint = false;
+ final URIComparator comparator = new EaafUriCompare(serviceUrl);
+
+
+ final InboundMessageInterface msg =
+ bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, comparator);
+
+ Assert.assertNotNull("PVP msg is null", msg);
+ Assert.assertNotNull("RelayState is not null", msg.getRelayState());
+ Assert.assertEquals("RelayState not match", relayState, msg.getRelayState());
+ Assert.assertNotNull("Response is null", msg.getInboundMessage());
+ Assert.assertNotNull("EntityId is null", msg.getEntityID());
+ Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata", msg.getEntityID());
+ Assert.assertFalse("Wrong isVerified flag", msg.isVerified());
+
+ }
+
+ @Test
+ public void encodeRequestSuccess() throws MessageDecodingException, SecurityException,
+ MessageEncodingException, XMLParserException, UnmarshallingException,
+ CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception {
+ //build test data
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = null;
+ guiBuilderFactory.setVelocityBuilderConfig(createDummyGuiConfig());
+ final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml"));
+
+ bindingImpl.encodeRequest(httpReq, httpResp, authnReq, serviceUrl, relayState,
+ credentialProvider.getIdpMetaDataSigningCredential(), pendingReq);
+
+ //validate
+ Assert.assertEquals("http StatusCode", 200, httpResp.getStatus());
+ Assert.assertNotNull("PVP msg is null", httpResp.getContentLength());
+
+ Assert.assertEquals("ContentType", "text/html", httpResp.getContentType());
+ Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding());
+
+ final String http = httpResp.getContentAsString();
+ Assert.assertNotNull("http body is null", http);
+ Assert.assertFalse("http body is empty", http.isEmpty());
+
+ Assert.assertFalse("RelayState parameter", http.contains(HTTP_FORM_RELAYSTATE));
+
+ Assert.assertTrue("SAMLRequest parameter", http.contains(HTTP_FORM_SAMLREQ));
+ final String httpSamlReq = extractParamFromHttpForm(http, HTTP_FORM_SAMLREQ);
+ checkSamlMessageSigned(httpSamlReq);
+
+ }
+
+ @Test
+ public void encodeRequestSuccessEcdsa() throws MessageDecodingException, SecurityException,
+ MessageEncodingException, XMLParserException, UnmarshallingException,
+ CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception {
+ //build test data
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = null;
+ guiBuilderFactory.setVelocityBuilderConfig(createDummyGuiConfig());
+ final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml"));
+
+ bindingImpl.encodeRequest(httpReq, httpResp, authnReq, serviceUrl, relayState,
+ credentialProvider.getIdpAssertionSigningCredential(), pendingReq);
+
+ //validate
+ Assert.assertEquals("http StatusCode", 200, httpResp.getStatus());
+ Assert.assertNotNull("PVP msg is null", httpResp.getContentLength());
+
+ Assert.assertEquals("ContentType", "text/html", httpResp.getContentType());
+ Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding());
+
+ final String http = httpResp.getContentAsString();
+ Assert.assertNotNull("http body is null", http);
+ Assert.assertFalse("http body is empty", http.isEmpty());
+
+ Assert.assertFalse("RelayState parameter", http.contains(HTTP_FORM_RELAYSTATE));
+
+ Assert.assertTrue("SAMLRequest parameter", http.contains(HTTP_FORM_SAMLREQ));
+ final String httpSamlReq = extractParamFromHttpForm(http, HTTP_FORM_SAMLREQ);
+ checkSamlMessageSigned(httpSamlReq);
+
+ }
+
+ @Test
+ public void encodeRequestSuccessWithRelayState() throws MessageDecodingException, SecurityException,
+ MessageEncodingException, XMLParserException, UnmarshallingException,
+ CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception {
+
+ //build test data
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = RandomStringUtils.randomAlphabetic(10);
+ guiBuilderFactory.setVelocityBuilderConfig(createDummyGuiConfig());
+ final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml"));
+
+ bindingImpl.encodeRequest(httpReq, httpResp, authnReq, serviceUrl, relayState,
+ credentialProvider.getIdpMetaDataSigningCredential(), pendingReq);
+
+
+ //validate
+ Assert.assertEquals("http StatusCode", 200, httpResp.getStatus());
+ Assert.assertNotNull("PVP msg is null", httpResp.getContentLength());
+
+ Assert.assertEquals("ContentType", "text/html", httpResp.getContentType());
+ Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding());
+
+ final String http = httpResp.getContentAsString();
+ Assert.assertNotNull("http body is null", http);
+ Assert.assertFalse("http body is empty", http.isEmpty());
+
+ Assert.assertTrue("RelayState parameter", http.contains(HTTP_FORM_RELAYSTATE));
+ final String httpRelayState = extractParamFromHttpForm(http, HTTP_FORM_RELAYSTATE);
+ Assert.assertEquals("Wrong RelayState", relayState, httpRelayState);
+
+ Assert.assertTrue("SAMLRequest parameter", http.contains(HTTP_FORM_SAMLREQ));
+ final String httpSamlReq = extractParamFromHttpForm(http, HTTP_FORM_SAMLREQ);
+ checkSamlMessageSigned(httpSamlReq);
+
+ }
+
+ @Test
+ public void encodeResponseSuccessWithRelayState() throws MessageDecodingException, SecurityException,
+ MessageEncodingException, XMLParserException, UnmarshallingException,
+ CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception {
+
+ //build test data
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = RandomStringUtils.randomAlphabetic(10);
+ guiBuilderFactory.setVelocityBuilderConfig(createDummyGuiConfig());
+ final StatusResponseType authnReq = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ PostBindingTest.class.getResourceAsStream("/data/Response_without_sig_1.xml"));
+
+ bindingImpl.encodeResponse(httpReq, httpResp, authnReq, serviceUrl, relayState,
+ credentialProvider.getIdpMetaDataSigningCredential(), pendingReq);
+
+
+ //validate
+ Assert.assertEquals("http StatusCode", 200, httpResp.getStatus());
+ Assert.assertNotNull("PVP msg is null", httpResp.getContentLength());
+
+ Assert.assertEquals("ContentType", "text/html", httpResp.getContentType());
+ Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding());
+
+ final String http = httpResp.getContentAsString();
+ Assert.assertNotNull("http body is null", http);
+ Assert.assertFalse("http body is empty", http.isEmpty());
+
+ Assert.assertTrue("RelayState parameter", http.contains(HTTP_FORM_RELAYSTATE));
+ final String httpRelayState = extractParamFromHttpForm(http, HTTP_FORM_RELAYSTATE);
+ Assert.assertEquals("Wrong RelayState", relayState, httpRelayState);
+
+ Assert.assertTrue("SAMLRequest parameter", http.contains(HTTP_FORM_SAMLRESP));
+ final String httpSamlReq = extractParamFromHttpForm(http, HTTP_FORM_SAMLRESP);
+ checkSamlMessageSigned(httpSamlReq);
+
+ }
+
+ @Test
+ public void encodeResponseSuccess() throws MessageDecodingException, SecurityException,
+ MessageEncodingException, XMLParserException, UnmarshallingException,
+ CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception {
+
+ //build test data
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = null;
+ guiBuilderFactory.setVelocityBuilderConfig(createDummyGuiConfig());
+ final StatusResponseType authnReq = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ PostBindingTest.class.getResourceAsStream("/data/Response_without_sig_1.xml"));
+
+ bindingImpl.encodeResponse(httpReq, httpResp, authnReq, serviceUrl, relayState,
+ credentialProvider.getIdpMetaDataSigningCredential(), pendingReq);
+
+
+ //validate
+ Assert.assertEquals("http StatusCode", 200, httpResp.getStatus());
+ Assert.assertNotNull("PVP msg is null", httpResp.getContentLength());
+
+ Assert.assertEquals("ContentType", "text/html", httpResp.getContentType());
+ Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding());
+
+ final String http = httpResp.getContentAsString();
+ Assert.assertNotNull("http body is null", http);
+ Assert.assertFalse("http body is empty", http.isEmpty());
+
+ Assert.assertFalse("RelayState parameter", http.contains(HTTP_FORM_RELAYSTATE));
+
+ Assert.assertTrue("SAMLRequest parameter", http.contains(HTTP_FORM_SAMLRESP));
+ final String httpSamlReq = extractParamFromHttpForm(http, HTTP_FORM_SAMLRESP);
+ checkSamlMessageSigned(httpSamlReq);
+
+ }
+
+ private IVelocityGuiBuilderConfiguration createDummyGuiConfig() {
+ return new IVelocityGuiBuilderConfiguration() {
+
+ @Override
+ public Map<String, Object> getViewParameters() {
+ return null;
+ }
+
+ @Override
+ public String getViewName() {
+ return "SAML2 Post-Binding";
+ }
+
+ @Override
+ public String getDefaultContentType() {
+ return null;
+ }
+
+ @Override
+ public InputStream getTemplate(String viewName) {
+ return PostBindingTest.class.getResourceAsStream("/data/pvp_postbinding_template.html");
+ }
+
+ @Override
+ public String getClasspathTemplateDir() {
+ return null;
+
+ }
+ };
+ }
+
+ private void checkSamlMessageSigned(String b64Msg) throws ParserConfigurationException,
+ SAXException, IOException, UnmarshallingException {
+ final Element httpSamlReqElment = DomUtils.parseXmlNonValidating(
+ new ByteArrayInputStream(Base64.getDecoder().decode(b64Msg)));
+
+ final UnmarshallerFactory unmarshallerFactory = XMLObjectProviderRegistrySupport.getUnmarshallerFactory();
+ final Unmarshaller unmarshaller = unmarshallerFactory.getUnmarshaller(httpSamlReqElment);
+ final SignableSAMLObject msg = (SignableSAMLObject) unmarshaller.unmarshall(httpSamlReqElment);
+ Assert.assertTrue("SAML msg not signed", msg.isSigned());
+
+ }
+
+ private String extractParamFromHttpForm(String http, String httpFormRelaystate) {
+ final int startIndex = http.indexOf(httpFormRelaystate) + httpFormRelaystate.length();
+ final int endIndex = http.indexOf("\"", startIndex);
+ return http.substring(startIndex, endIndex);
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/RedirectBindingTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/RedirectBindingTest.java
new file mode 100644
index 00000000..80dfc400
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/RedirectBindingTest.java
@@ -0,0 +1,490 @@
+package at.gv.egiz.eaaf.modules.pvp2.test.binding;
+
+import java.io.IOException;
+import java.net.URLDecoder;
+import java.util.Base64;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;
+import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
+import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
+import at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding;
+import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer;
+import at.gv.egiz.eaaf.modules.pvp2.impl.validation.EaafUriCompare;
+import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opensaml.core.config.InitializationException;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
+import org.opensaml.messaging.decoder.MessageDecodingException;
+import org.opensaml.messaging.encoder.MessageEncodingException;
+import org.opensaml.saml.saml2.core.RequestAbstractType;
+import org.opensaml.saml.saml2.core.StatusResponseType;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.xml.sax.SAXException;
+
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.net.URIComparator;
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration({"/spring/test_eaaf_pvp.beans.xml"})
+@TestPropertySource(locations = {"/config/config_1.props"})
+public class RedirectBindingTest {
+
+ public static final String HTTP_FORM_RELAYSTATE = "RelayState=";
+ public static final String HTTP_FORM_SAMLREQ = "SAMLRequest=";
+ public static final String HTTP_FORM_SAMLRESP = "SAMLResponse=";
+
+ public static final String HTTP_REDIRECT_SIGALG = "SigAlg=";
+ public static final String HTTP_REDIRECT_SIGNATURE = "Signature=";
+
+ @Autowired private RedirectBinding bindingImpl;
+ @Autowired private DummyCredentialProvider credentialProvider;
+
+ protected MockHttpServletRequest httpReq;
+ protected MockHttpServletResponse httpResp;
+ protected IRequest pendingReq;
+
+ @BeforeClass
+ public static void classInitializer() throws InitializationException, ComponentInitializationException {
+ EaafOpenSaml3xInitializer.eaafInitialize();
+
+ }
+
+ /**
+ * Test initializer.
+ *
+ */
+ @Before
+ public void initialize() {
+ httpReq = new MockHttpServletRequest();
+ httpResp = new MockHttpServletResponse();
+
+ pendingReq = new TestRequestImpl();
+
+ }
+
+ @Test
+ public void checkCanHandle() {
+ httpReq.setMethod("POST");
+ Assert.assertFalse("Wrong canHandle result", bindingImpl.handleDecode("Post", httpReq));
+ Assert.assertFalse("Wrong canHandle result", bindingImpl.handleDecode("Redirect", httpReq));
+
+ httpReq.setMethod("GET");
+ Assert.assertFalse("Wrong canHandle result", bindingImpl.handleDecode("Post", httpReq));
+ Assert.assertTrue("Wrong canHandle result", bindingImpl.handleDecode("Redirect", httpReq));
+ }
+
+ @Test
+ public void decodeRequestSuccess() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception {
+ final String serviceUrl = "http://testservice.org";
+
+ final IPvp2MetadataProvider metadataProvider = null;
+
+ final boolean isSpEndPoint = false;
+ final URIComparator comparator = new EaafUriCompare(serviceUrl);
+
+ httpReq.setMethod("GET");
+ httpReq.setRequestURI("http://testservice.org");
+ httpReq.setParameter("SAMLRequest","nVRNb9swDD13wP6DoXvkr/RjQuzCSFAgQDd0TbfDLoVi0642Wcok2kn766c4duABWw++SdQj+fhIanF7qKXXgrFCq4SENCAeqFwXQlUJ+fZ0N7sht+nC8lpGO5Y1+KIe4XcDFj3nqCw7vSSkMYppboVlitdgGeZsk32+ZxEN2M5o1LmWxMusBYMu1VIr29RgNmBakcNaFXBw6R0C0Yhtg3BCOBp/Qxy/lcsuFMeO8Qvijvk+Ops9Aak2FfHWq4Q8c4BtySHO4eomLCEuipyXURjzeVQGYRE7mLWNC22RK0xIFITzWRDPgsun4IrFn1gQ0evryx/E+z4o5OohvR6sczZjId7XgQ/VE+9Om5rj+/CjRRSzsoMyUCjwlaTHgq2ruIBaU6jEG61ayrG777RBLp+PR6krofyFP2Y68N4025+Q4xTi6ccPFxd9mC8Ot15NI9T7umiDpSd1nrUT4kFLkb96mZR6vzTAERKCpoEpCu6OPbTohCRThtc/U+s3AIpuH9ygIhwm7cNYzXGspXSKP0I5qUP9Ruz3e2pRm1+00i2Fxne77ecCxRuor1l2Dy1Ifz6o/6/so+78p+b0/Dz+GdI/");
+ httpReq.setParameter("SigAlg","http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
+ httpReq.setParameter("Signature","DOVMqh17xn4wl+yvifm4McMsBjKDVf1eqph9ss362ZEbp2nkAIXUzkNWv72I96iNK3r+YbAxY9dwZ8Z7jKzCGiJ9Qm34YSfPvzXWl3EVrdI869U+H6HGIMqVew3cVdr4q3Qv9ZBIhdRxbrDu/+nMjdf8mzbgcQnfjSQiQIYWxOIXZFyxKsyrxJtIam4hoNwUT7mMN6RjgzvyeS3mARsTJdcI0Vn4ItiprhLgIkD18V9WIdeSZR0gfRaFj8PKdmXCD/Ia0cKgjhVKoiIZisV4vcthBOeDIqBORL2Ad3XhcNRQ3+cpAf65zHGMBAv1aRy7Bmv0++OvCavufykqI2EHtg==");
+
+
+
+
+ final InboundMessageInterface msg =
+ bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, comparator);
+
+ Assert.assertNotNull("PVP msg is null", msg);
+ Assert.assertNull("RelayState is not null", msg.getRelayState());
+ Assert.assertNotNull("AuthnReq is null", msg.getInboundMessage());
+ Assert.assertNotNull("EntityId is null", msg.getEntityID());
+ Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg.getEntityID());
+ Assert.assertFalse("Wrong isVerified flag", msg.isVerified());
+
+ }
+
+ @Ignore
+ @Test
+ public void decodeRequestSuccessWithRelayState() throws MessageDecodingException,
+ SecurityException, IOException, Pvp2Exception {
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = RandomStringUtils.randomAlphanumeric(10);
+
+ final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray(
+ RedirectBindingTest.class.getResourceAsStream("/data/AuthRequest_with_sig_1.xml")));
+ httpReq.setMethod("POST");
+ httpReq.addParameter("SAMLRequest", b64AuthnReq);
+ httpReq.addParameter("RelayState", relayState);
+
+ final IPvp2MetadataProvider metadataProvider = null;
+
+ final boolean isSpEndPoint = false;
+ final URIComparator comparator = new EaafUriCompare(serviceUrl);
+
+
+ final InboundMessageInterface msg =
+ bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, comparator);
+
+ Assert.assertNotNull("PVP msg is null", msg);
+ Assert.assertNotNull("RelayState is not null", msg.getRelayState());
+ Assert.assertEquals("RelayState not match", relayState, msg.getRelayState());
+ Assert.assertNotNull("AuthnReq is null", msg.getInboundMessage());
+ Assert.assertNotNull("EntityId is null", msg.getEntityID());
+ Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg.getEntityID());
+ Assert.assertFalse("Wrong isVerified flag", msg.isVerified());
+
+ }
+
+ @Ignore
+ @Test
+ public void decodeResponseSuccess() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception {
+ final String serviceUrl = "http://testservice.org";
+
+ final IPvp2MetadataProvider metadataProvider = null;
+
+ final boolean isSpEndPoint = false;
+ final URIComparator comparator = new EaafUriCompare(serviceUrl);
+
+ final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray(
+ RedirectBindingTest.class.getResourceAsStream("/data/Response_with_sig_1.xml")));
+ httpReq.setMethod("POST");
+ httpReq.addParameter("SAMLRequest", b64AuthnReq);
+
+
+ final InboundMessageInterface msg =
+ bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, comparator);
+
+ Assert.assertNotNull("PVP msg is null", msg);
+ Assert.assertNull("RelayState is not null", msg.getRelayState());
+ Assert.assertNotNull("Response is null", msg.getInboundMessage());
+ Assert.assertNotNull("EntityId is null", msg.getEntityID());
+ Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata", msg.getEntityID());
+ Assert.assertFalse("Wrong isVerified flag", msg.isVerified());
+
+ }
+
+ @Ignore
+ @Test
+ public void decodeResponseSuccessWithRelayState() throws MessageDecodingException, SecurityException,
+ IOException, Pvp2Exception {
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = RandomStringUtils.randomAlphanumeric(10);
+
+ final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray(
+ RedirectBindingTest.class.getResourceAsStream("/data/Response_with_sig_1.xml")));
+ httpReq.setMethod("POST");
+ httpReq.addParameter("SAMLRequest", b64AuthnReq);
+ httpReq.addParameter("RelayState", relayState);
+
+ final IPvp2MetadataProvider metadataProvider = null;
+
+ final boolean isSpEndPoint = false;
+ final URIComparator comparator = new EaafUriCompare(serviceUrl);
+
+
+ final InboundMessageInterface msg =
+ bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, comparator);
+
+ Assert.assertNotNull("PVP msg is null", msg);
+ Assert.assertNotNull("RelayState is not null", msg.getRelayState());
+ Assert.assertEquals("RelayState not match", relayState, msg.getRelayState());
+ Assert.assertNotNull("Response is null", msg.getInboundMessage());
+ Assert.assertNotNull("EntityId is null", msg.getEntityID());
+ Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata", msg.getEntityID());
+ Assert.assertFalse("Wrong isVerified flag", msg.isVerified());
+
+ }
+
+ @Test
+ public void encodeRequestSuccess() throws MessageDecodingException, SecurityException,
+ MessageEncodingException, XMLParserException, UnmarshallingException,
+ CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception {
+ //build test data
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = null;
+ final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ RedirectBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml"));
+
+ bindingImpl.encodeRequest(httpReq, httpResp, authnReq, serviceUrl, relayState,
+ credentialProvider.getIdpMetaDataSigningCredential(), pendingReq);
+
+ //validate
+ Assert.assertEquals("http StatusCode", 302, httpResp.getStatus());
+ Assert.assertEquals("PVP msg is null", 0, httpResp.getContentLength());
+
+ Assert.assertNull("ContentType", httpResp.getContentType());
+ Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding());
+
+ final String locationHeader = httpResp.getHeader("Location");
+ Assert.assertNotNull("Location header is null", locationHeader);
+ Assert.assertFalse("Location header is empty", locationHeader.isEmpty());
+
+ Assert.assertTrue("Wrong redirect URL",
+ locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLREQ));
+
+ final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLREQ, true);
+ Assert.assertNotNull("Saml msg is null", respSamlMsg);
+ Assert.assertFalse("Saml msg is empty", respSamlMsg.isEmpty());
+
+ final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG, true);
+ Assert.assertNotNull("SigAlg is null", sigAlg);
+ Assert.assertFalse("SigAlg is empty", sigAlg.isEmpty());
+ Assert.assertEquals("SigAlg not match", PvpConstants.DEFAULT_SIGNING_METHODE_RSA,
+ URLDecoder.decode(sigAlg, "UTF-8"));
+
+ final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE, true);
+ Assert.assertNotNull("Saml signature null", samlSig);
+ Assert.assertFalse("Saml signature is empty", samlSig.isEmpty());
+
+ final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE, false);
+ Assert.assertNull("RelayState parameter", respRelayState);
+
+ }
+
+
+ @Test
+ public void encodeRequestSuccessEcdsa() throws MessageDecodingException, SecurityException,
+ MessageEncodingException, XMLParserException, UnmarshallingException,
+ CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception {
+ //build test data
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = null;
+ final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ RedirectBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml"));
+
+ bindingImpl.encodeRequest(httpReq, httpResp, authnReq, serviceUrl, relayState,
+ credentialProvider.getIdpAssertionSigningCredential(), pendingReq);
+
+ //validate
+ //validate
+ Assert.assertEquals("http StatusCode", 302, httpResp.getStatus());
+ Assert.assertEquals("PVP msg is null", 0, httpResp.getContentLength());
+
+ Assert.assertNull("ContentType", httpResp.getContentType());
+ Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding());
+
+ final String locationHeader = httpResp.getHeader("Location");
+ Assert.assertNotNull("Location header is null", locationHeader);
+ Assert.assertFalse("Location header is empty", locationHeader.isEmpty());
+
+ Assert.assertTrue("Wrong redirect URL",
+ locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLREQ));
+
+ final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLREQ, true);
+ Assert.assertNotNull("Saml msg is null", respSamlMsg);
+ Assert.assertFalse("Saml msg is empty", respSamlMsg.isEmpty());
+
+ final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG, true);
+ Assert.assertNotNull("SigAlg is null", sigAlg);
+ Assert.assertFalse("SigAlg is empty", sigAlg.isEmpty());
+ Assert.assertEquals("SigAlg not match", PvpConstants.DEFAULT_SIGNING_METHODE_EC,
+ URLDecoder.decode(sigAlg, "UTF-8"));
+
+ final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE, true);
+ Assert.assertNotNull("Saml signature null", samlSig);
+ Assert.assertFalse("Saml signature is empty", samlSig.isEmpty());
+
+ final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE, false);
+ Assert.assertNull("RelayState parameter", respRelayState);
+
+
+ }
+
+ @Test
+ public void encodeRequestSuccessWithRelayState() throws MessageDecodingException, SecurityException,
+ MessageEncodingException, XMLParserException, UnmarshallingException,
+ CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception {
+
+ //build test data
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = RandomStringUtils.randomAlphabetic(10);
+ final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ RedirectBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml"));
+
+ bindingImpl.encodeRequest(httpReq, httpResp, authnReq, serviceUrl, relayState,
+ credentialProvider.getIdpMetaDataSigningCredential(), pendingReq);
+
+
+ //validate
+ Assert.assertEquals("http StatusCode", 302, httpResp.getStatus());
+ Assert.assertEquals("PVP msg is null", 0, httpResp.getContentLength());
+
+ Assert.assertNull("ContentType", httpResp.getContentType());
+ Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding());
+
+ final String locationHeader = httpResp.getHeader("Location");
+ Assert.assertNotNull("Location header is null", locationHeader);
+ Assert.assertFalse("Location header is empty", locationHeader.isEmpty());
+
+ Assert.assertTrue("Wrong redirect URL",
+ locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLREQ));
+
+ final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLREQ, true);
+ Assert.assertNotNull("Saml msg is null", respSamlMsg);
+ Assert.assertFalse("Saml msg is empty", respSamlMsg.isEmpty());
+
+ final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG, true);
+ Assert.assertNotNull("SigAlg is null", sigAlg);
+ Assert.assertFalse("SigAlg is empty", sigAlg.isEmpty());
+ Assert.assertEquals("SigAlg not match", PvpConstants.DEFAULT_SIGNING_METHODE_RSA,
+ URLDecoder.decode(sigAlg, "UTF-8"));
+
+ final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE, true);
+ Assert.assertNotNull("Saml signature null", samlSig);
+ Assert.assertFalse("Saml signature is empty", samlSig.isEmpty());
+
+ final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE, false);
+ Assert.assertNotNull("RelayState parameter", respRelayState);
+ Assert.assertEquals("RelayState not match", relayState,
+ URLDecoder.decode(respRelayState, "UTF-8"));
+
+
+ }
+
+ @Test
+ public void encodeResponseSuccessWithRelayState() throws MessageDecodingException, SecurityException,
+ MessageEncodingException, XMLParserException, UnmarshallingException,
+ CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception {
+
+ //build test data
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = RandomStringUtils.randomAlphabetic(10);
+ final StatusResponseType authnReq = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ RedirectBindingTest.class.getResourceAsStream("/data/Response_without_sig_1.xml"));
+
+ bindingImpl.encodeResponse(httpReq, httpResp, authnReq, serviceUrl, relayState,
+ credentialProvider.getIdpMetaDataSigningCredential(), pendingReq);
+
+
+ //validate
+ Assert.assertEquals("http StatusCode", 302, httpResp.getStatus());
+ Assert.assertEquals("PVP msg is null", 0, httpResp.getContentLength());
+
+ Assert.assertNull("ContentType", httpResp.getContentType());
+ Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding());
+
+ final String locationHeader = httpResp.getHeader("Location");
+ Assert.assertNotNull("Location header is null", locationHeader);
+ Assert.assertFalse("Location header is empty", locationHeader.isEmpty());
+
+ Assert.assertTrue("Wrong redirect URL",
+ locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLRESP));
+
+ final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLRESP, true);
+ Assert.assertNotNull("Saml msg is null", respSamlMsg);
+ Assert.assertFalse("Saml msg is empty", respSamlMsg.isEmpty());
+
+ final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG, true);
+ Assert.assertNotNull("SigAlg is null", sigAlg);
+ Assert.assertFalse("SigAlg is empty", sigAlg.isEmpty());
+ Assert.assertEquals("SigAlg not match", PvpConstants.DEFAULT_SIGNING_METHODE_RSA,
+ URLDecoder.decode(sigAlg, "UTF-8"));
+
+ final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE, true);
+ Assert.assertNotNull("Saml signature null", samlSig);
+ Assert.assertFalse("Saml signature is empty", samlSig.isEmpty());
+
+ final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE, false);
+ Assert.assertNotNull("RelayState parameter", respRelayState);
+ Assert.assertEquals("RelayState not match", relayState,
+ URLDecoder.decode(respRelayState, "UTF-8"));
+
+ }
+
+ @Test
+ public void encodeResponseSuccess() throws MessageDecodingException, SecurityException,
+ MessageEncodingException, XMLParserException, UnmarshallingException,
+ CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception {
+
+ //build test data
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = null;
+ final StatusResponseType authnReq = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ RedirectBindingTest.class.getResourceAsStream("/data/Response_without_sig_1.xml"));
+
+ bindingImpl.encodeResponse(httpReq, httpResp, authnReq, serviceUrl, relayState,
+ credentialProvider.getIdpMetaDataSigningCredential(), pendingReq);
+
+
+ //validate
+ Assert.assertEquals("http StatusCode", 302, httpResp.getStatus());
+ Assert.assertEquals("PVP msg is null", 0, httpResp.getContentLength());
+
+ Assert.assertNull("ContentType", httpResp.getContentType());
+ Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding());
+
+ final String locationHeader = httpResp.getHeader("Location");
+ Assert.assertNotNull("Location header is null", locationHeader);
+ Assert.assertFalse("Location header is empty", locationHeader.isEmpty());
+
+ Assert.assertTrue("Wrong redirect URL",
+ locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLRESP));
+
+ final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLRESP, true);
+ Assert.assertNotNull("Saml msg is null", respSamlMsg);
+ Assert.assertFalse("Saml msg is empty", respSamlMsg.isEmpty());
+
+ final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG, true);
+ Assert.assertNotNull("SigAlg is null", sigAlg);
+ Assert.assertFalse("SigAlg is empty", sigAlg.isEmpty());
+ Assert.assertEquals("SigAlg not match", PvpConstants.DEFAULT_SIGNING_METHODE_RSA,
+ URLDecoder.decode(sigAlg, "UTF-8"));
+
+ final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE, true);
+ Assert.assertNotNull("Saml signature null", samlSig);
+ Assert.assertFalse("Saml signature is empty", samlSig.isEmpty());
+
+ final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE, false);
+ Assert.assertNull("RelayState parameter", respRelayState);
+
+ }
+
+ private String checkMessagePart(String locationHeader, String httpFormSamlreq, boolean isRequired) {
+ final int startIndex = locationHeader.indexOf(httpFormSamlreq);
+ int endIndex = locationHeader.indexOf("&", startIndex);
+
+ if (isRequired && startIndex == -1) {
+ Assert.fail("Element: " + httpFormSamlreq + " NOT found");
+
+ } else if (startIndex == -1) {
+ return null;
+
+ }
+
+ if (endIndex == -1) {
+ endIndex = locationHeader.length();
+
+ }
+
+ return locationHeader.substring(startIndex + httpFormSamlreq.length(), endIndex);
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/dummy/DummyCredentialProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/dummy/DummyCredentialProvider.java
new file mode 100644
index 00000000..6930790d
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/dummy/DummyCredentialProvider.java
@@ -0,0 +1,70 @@
+package at.gv.egiz.eaaf.modules.pvp2.test.dummy;
+
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class DummyCredentialProvider extends AbstractCredentialProvider {
+
+ @Autowired IConfiguration basicConfig;
+
+ public static final String KEYSTORE_PATH = "keystore.path";
+ public static final String KEYSTORE_PASSWORD = "keystore.pass";
+
+ public static final String KEY_METADATA_ALIAS = "key.metadata.alias";
+ public static final String KEY_METADATA_PASSWORD = "key.metadata.pass";
+
+ public static final String KEY_SIGNING_ALIAS = "key.sig.alias";
+ public static final String KEY_SIGNING_PASSWORD = "key.sig.pass";
+
+ public static final String KEY_ENCRYPTION_ALIAS = "key.enc.alias";
+ public static final String KEY_ENCRYPTION_PASSWORD = "key.enc.pass";
+
+ @Override
+ public String getFriendlyName() {
+ return "jUnit test credential provider";
+ }
+
+ @Override
+ public String getKeyStoreFilePath() throws EaafException {
+ return basicConfig.getBasicConfiguration(KEYSTORE_PATH);
+ }
+
+ @Override
+ public String getKeyStorePassword() {
+ return basicConfig.getBasicConfiguration(KEYSTORE_PASSWORD);
+ }
+
+ @Override
+ public String getMetadataKeyAlias() {
+ return basicConfig.getBasicConfiguration(KEY_METADATA_ALIAS);
+ }
+
+ @Override
+ public String getMetadataKeyPassword() {
+ return basicConfig.getBasicConfiguration(KEY_METADATA_PASSWORD);
+ }
+
+ @Override
+ public String getSignatureKeyAlias() {
+ return basicConfig.getBasicConfiguration(KEY_SIGNING_ALIAS);
+ }
+
+ @Override
+ public String getSignatureKeyPassword() {
+ return basicConfig.getBasicConfiguration(KEY_SIGNING_PASSWORD);
+ }
+
+ @Override
+ public String getEncryptionKeyAlias() {
+ return basicConfig.getBasicConfiguration(KEY_ENCRYPTION_ALIAS);
+ }
+
+ @Override
+ public String getEncryptionKeyPassword() {
+ return basicConfig.getBasicConfiguration(KEY_ENCRYPTION_PASSWORD);
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_1.props b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_1.props
new file mode 100644
index 00000000..74b805ba
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_1.props
@@ -0,0 +1,8 @@
+keystore.path=classpath:/data/junit.jks
+keystore.pass=password
+key.metadata.alias=meta
+key.metadata.pass=password
+key.sig.alias=sig
+key.sig.pass=password
+key.enc.alias=
+key.enc.pass= \ No newline at end of file
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_with_sig_1.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_with_sig_1.xml
new file mode 100644
index 00000000..f9de11c4
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_with_sig_1.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceIndex="1" AttributeConsumingServiceIndex="0" Destination="https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/post" ID="_aeebfae3ce681fe3ddcaf213a42f01d3" IssueInstant="2014-03-05T06:39:02.775Z" Version="2.0">
+ <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_demologin/</saml2:Issuer>
+ <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+ <ds:SignedInfo>
+ <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+ <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
+ <ds:Reference URI="#_aeebfae3ce681fe3ddcaf213a42f01d3">
+ <ds:Transforms>
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+ </ds:Transforms>
+ <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
+ <ds:DigestValue>sBVJQf9b+QIxRfH8YuTbF6hBrf4=</ds:DigestValue>
+ </ds:Reference>
+ </ds:SignedInfo>
+ <ds:SignatureValue>JK68H5XqmD2OEA8O/UCZFenVj0TrvauPhaKJt73pbHbi//hO1hBcRQbV2Qg3gQ11EcJ9Q+TM3TCe9nT6tdU/z7ry3qdZvlOfrkMF13fY4HOIuvB9AcySdxq2yKA3V5O9sLhf5S9qCyx9lMnTARC7wkVs4j2Pv00R6P/iROOHD5ryGF2J0FdtMp9VqhvQJ9yRGM2lTduF98MqxWA2EMk6AMo7qij0Bvha1B2OyFSU9HM3fyfRQpXDeiLnKHcjLpzu5TDNkKrP75c7vv85DDr7s2I0p74nAOVLMuLau5tEQ91Crk9QoqoqqEecKWcNJDXTO9MahCQw77hUDL1WOEMFFg==</ds:SignatureValue>
+ <ds:KeyInfo>
+ <ds:KeyValue>
+ <ds:RSAKeyValue>
+ <ds:Modulus>nEPzKMh3TovnfBnTyv+TMYFsGep8Uil7iNbfVyfLoBfqRdeGDOk4es2qWkgB6az+kM/9Js2H06m4
+pjEY7/RIjd0lMWqgi8eqdjilMmbFQykkYYQhlZbvi8KqoBcCKzj5N3GY4qh8A5qN4y85Q3sZj23T
+iiIY1rphE+ZTOHCm6CKeRso9jj409YHP1xAXfPvtIYx2TA1uuagxOmL75OC/hr7gcUm0tmuKiSeq
++TO4VZw2Q7K7YESZ1WkiBoG2i4cHdcBFKnVrGNtyxl6UkjWxXRJSU9aNLs5QxsE6iFwCvFoIO+IU
+cVWxfFHqOGbRtAcRUb4fk+KFHE2o1DLmfwZaUQ==</ds:Modulus>
+ <ds:Exponent>AQAB</ds:Exponent>
+ </ds:RSAKeyValue>
+ </ds:KeyValue>
+ </ds:KeyInfo>
+ </ds:Signature>
+ <saml2:Subject xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
+ <saml2:NameID>https://demo.egiz.gv.at/demoportal_demologin/</saml2:NameID>
+ </saml2:Subject>
+ <saml2p:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/>
+ <saml2p:RequestedAuthnContext>
+ <saml2:AuthnContextClassRef xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://www.stork.gov.eu/1.0/citizenQAALevel/4</saml2:AuthnContextClassRef>
+ </saml2p:RequestedAuthnContext>
+</saml2p:AuthnRequest>
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_without_sig_1.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_without_sig_1.xml
new file mode 100644
index 00000000..ef35ea92
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_without_sig_1.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceIndex="1" AttributeConsumingServiceIndex="0" Destination="https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/post" ID="_aeebfae3ce681fe3ddcaf213a42f01d3" IssueInstant="2014-03-05T06:39:02.775Z" Version="2.0">
+ <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_demologin/</saml2:Issuer>
+ <saml2:Subject xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
+ <saml2:NameID>https://demo.egiz.gv.at/demoportal_demologin/</saml2:NameID>
+ </saml2:Subject>
+ <saml2p:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/>
+ <saml2p:RequestedAuthnContext>
+ <saml2:AuthnContextClassRef xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://www.stork.gov.eu/1.0/citizenQAALevel/4</saml2:AuthnContextClassRef>
+ </saml2p:RequestedAuthnContext>
+</saml2p:AuthnRequest>
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_with_sig_1.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_with_sig_1.xml
new file mode 100644
index 00000000..2654f2e8
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_with_sig_1.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://demo.egiz.gv.at/demoportal_demologin/securearea.action" InResponseTo="_aeebfae3ce681fe3ddcaf213a42f01d3" IssueInstant="2014-03-05T06:39:51.017Z" Version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata</saml2:Issuer>
+ <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+ <ds:SignedInfo>
+ <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+ <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
+ <ds:Reference URI="">
+ <ds:Transforms>
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
+ <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs"/>
+ </ds:Transform>
+ </ds:Transforms>
+ <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
+ <ds:DigestValue>fCE31ZeXZybQLOuNQBePLjFrCtKdvCmeyJ1tUW/ghtA=</ds:DigestValue>
+ </ds:Reference>
+ </ds:SignedInfo>
+ <ds:SignatureValue>vUFR3YPk5wiBJnrLh6Er7V46FNDMuB5Jcu73Rw7tipgr+bnV0reRNcZ5TGT+VMjNhtKJMcqgjrQWJ6tACe1r0mzhpRSVQkw7yFkTvIhQHX1a08yqJ4yy3qiN13ctDo4VgP9qHUim7b797oOKNhRXFk+2GJA5hRcpRliUjhBlzTYrxpkY5NcYDRhDPlvMx+l11oa1iDGuAylN+ty4h3P4fIoIgL9Tz1m3l65LqkV5RBc6avSeHw9OASMigPsjd5b0IBvhvJ611xLgzC1BOtJshiw1k/p8alv8TaUmYZ/kJbRN1tuTBL129edbS0Rz0faT0tniF42QHteJ214brK3rCg==</ds:SignatureValue>
+ <ds:KeyInfo>
+ <ds:KeyValue>
+ <ds:RSAKeyValue>
+ <ds:Modulus>xRE83dJy1dj+KVBp5Syo91fjGeG1MmJDSuTZ5MwdDzvIZrbK3YPh0jbJz4lOSrw9urRacavZX4m2
+XAKfSRxaowP3GqTh3Ew4WJE7yXEnWiic7bUz8uMIr020bsvqHCvY48+oPARbz/cEOf5NgMBWqo9E
+nibdIyU5+AmfFzDaMwNocJEANoXrjLTpduCHvT0Qt/wH+7rVdgjX1djMrBhyMWs7GQyIBRfuf58m
+8kdcoiMSm9AWA4d4GzXch+bi1QRzj+Ib80DeWdcXP3Hc6pcyp/+L+hya2jZ9NMS8yup6xuoAeh7w
+6JNpfE9QnO3/CPrDZTtmjPK2OIRkhgn4Yi+iBQ==</ds:Modulus>
+ <ds:Exponent>AQAB</ds:Exponent>
+ </ds:RSAKeyValue>
+ </ds:KeyValue>
+ </ds:KeyInfo>
+ </ds:Signature>
+ <saml2p:Status>
+ <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
+ </saml2p:Status>
+ <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_602c3236bffaf71ac3ac88674e76ff9f" IssueInstant="2014-03-05T06:39:51.017Z" Version="2.0">
+ <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata</saml2:Issuer>
+ <saml2:Subject>
+ <saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" NameQualifier="urn:publicid:gv.at:cdid+BF">QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:NameID>
+ <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
+ <saml2:SubjectConfirmationData InResponseTo="_aeebfae3ce681fe3ddcaf213a42f01d3" NotOnOrAfter="2014-03-05T06:44:51.017Z" Recipient="https://demo.egiz.gv.at/demoportal_demologin/securearea.action"/>
+ </saml2:SubjectConfirmation>
+ </saml2:Subject>
+ <saml2:Conditions NotBefore="2014-03-05T06:39:51.017Z" NotOnOrAfter="2014-03-05T06:44:51.017Z">
+ <saml2:AudienceRestriction>
+ <saml2:Audience>https://demo.egiz.gv.at/demoportal_demologin/</saml2:Audience>
+ </saml2:AudienceRestriction>
+ </saml2:Conditions>
+ <saml2:AuthnStatement AuthnInstant="2014-03-05T06:39:51.017Z" SessionIndex="_c0c683509a8ff6ac372a9cf9c5c5a406">
+ <saml2:AuthnContext>
+ <saml2:AuthnContextClassRef>http://www.stork.gov.eu/1.0/citizenQAALevel/4</saml2:AuthnContextClassRef>
+ </saml2:AuthnContext>
+ </saml2:AuthnStatement>
+ <saml2:AttributeStatement>
+ <saml2:Attribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">2.1</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Mustermann</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Max</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">1940-01-01</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">BF:QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="EID-CITIZEN-QAA-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.94" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:integer">4</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">AT</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">urn:publicid:gv.at:cdid+BF</saml2:AttributeValue>
+ </saml2:Attribute>
+ </saml2:AttributeStatement>
+ </saml2:Assertion>
+</saml2p:Response>
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_without_sig_1.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_without_sig_1.xml
new file mode 100644
index 00000000..3607cbc4
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_without_sig_1.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://demo.egiz.gv.at/demoportal_demologin/securearea.action" InResponseTo="_aeebfae3ce681fe3ddcaf213a42f01d3" IssueInstant="2014-03-05T06:39:51.017Z" Version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata</saml2:Issuer>
+ <saml2p:Status>
+ <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
+ </saml2p:Status>
+ <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_602c3236bffaf71ac3ac88674e76ff9f" IssueInstant="2014-03-05T06:39:51.017Z" Version="2.0">
+ <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata</saml2:Issuer>
+ <saml2:Subject>
+ <saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" NameQualifier="urn:publicid:gv.at:cdid+BF">QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:NameID>
+ <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
+ <saml2:SubjectConfirmationData InResponseTo="_aeebfae3ce681fe3ddcaf213a42f01d3" NotOnOrAfter="2014-03-05T06:44:51.017Z" Recipient="https://demo.egiz.gv.at/demoportal_demologin/securearea.action"/>
+ </saml2:SubjectConfirmation>
+ </saml2:Subject>
+ <saml2:Conditions NotBefore="2014-03-05T06:39:51.017Z" NotOnOrAfter="2014-03-05T06:44:51.017Z">
+ <saml2:AudienceRestriction>
+ <saml2:Audience>https://demo.egiz.gv.at/demoportal_demologin/</saml2:Audience>
+ </saml2:AudienceRestriction>
+ </saml2:Conditions>
+ <saml2:AuthnStatement AuthnInstant="2014-03-05T06:39:51.017Z" SessionIndex="_c0c683509a8ff6ac372a9cf9c5c5a406">
+ <saml2:AuthnContext>
+ <saml2:AuthnContextClassRef>http://www.stork.gov.eu/1.0/citizenQAALevel/4</saml2:AuthnContextClassRef>
+ </saml2:AuthnContext>
+ </saml2:AuthnStatement>
+ <saml2:AttributeStatement>
+ <saml2:Attribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">2.1</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Mustermann</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Max</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">1940-01-01</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">BF:QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="EID-CITIZEN-QAA-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.94" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:integer">4</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">AT</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">urn:publicid:gv.at:cdid+BF</saml2:AttributeValue>
+ </saml2:Attribute>
+ </saml2:AttributeStatement>
+ </saml2:Assertion>
+</saml2p:Response>
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit.jks b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit.jks
new file mode 100644
index 00000000..b5262cb8
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit.jks
Binary files differ
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_postbinding_template.html b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_postbinding_template.html
new file mode 100644
index 00000000..a0d31907
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_postbinding_template.html
@@ -0,0 +1,3 @@
+#if($RelayState)RelayState=${RelayState}"}#end
+#if($SAMLRequest)SAMLRequest=${SAMLRequest}"}#end
+#if($SAMLResponse)SAMLResponse=${SAMLResponse}"}#end \ No newline at end of file
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core.beans.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core.beans.xml
new file mode 100644
index 00000000..de3cfbd1
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core.beans.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
+
+ <bean id="dummyAuthConfig"
+ class="at.gv.egiz.eaaf.core.impl.idp.module.test.DummyAuthConfig" />
+
+ <bean id="dummyVelocityGuiBuilder"
+ class="at.gv.egiz.eaaf.core.impl.idp.module.gui.DummyVelocityGuiFormBuilder" />
+
+ <bean id="dummyGuiBuilderConfigFactory"
+ class="at.gv.egiz.eaaf.core.impl.idp.module.gui.DummyGuiBuilderConfigurationFactory" />
+
+</beans> \ No newline at end of file
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_pvp.beans.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_pvp.beans.xml
new file mode 100644
index 00000000..f261e893
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_pvp.beans.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
+
+ <import resource="test_eaaf_core.beans.xml"/>
+
+ <bean id="dummyCredentialProvider"
+ class="at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider" />
+
+ <bean id="PvpPostBinding"
+ class="at.gv.egiz.eaaf.modules.pvp2.impl.binding.PostBinding" />
+
+ <bean id="PvpRedirectBinding"
+ class="at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding" />
+
+ <bean id="PvpSoapBinding"
+ class="at.gv.egiz.eaaf.modules.pvp2.impl.binding.SoapBinding" />
+
+
+
+</beans> \ No newline at end of file