diff options
86 files changed, 4753 insertions, 1231 deletions
| diff --git a/eaaf_core_api/pom.xml b/eaaf_core_api/pom.xml index c16bf39c..d26e3483 100644 --- a/eaaf_core_api/pom.xml +++ b/eaaf_core_api/pom.xml @@ -41,6 +41,10 @@        <artifactId>slf4j-api</artifactId>      </dependency>      <dependency> +      <groupId>javax.annotation</groupId> +      <artifactId>javax.annotation-api</artifactId> +    </dependency> +    <dependency>        <groupId>com.google.code.findbugs</groupId>        <artifactId>jsr305</artifactId>      </dependency> diff --git a/eaaf_modules/eaaf_module_pvp2_core/pom.xml b/eaaf_modules/eaaf_module_pvp2_core/pom.xml index 62973ac5..ef56624b 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/pom.xml +++ b/eaaf_modules/eaaf_module_pvp2_core/pom.xml @@ -71,6 +71,11 @@        <scope>test</scope>        <type>test-jar</type>      </dependency> +    <dependency> +      <groupId>com.squareup.okhttp3</groupId> +      <artifactId>mockwebserver</artifactId> +      <scope>test</scope> +    </dependency>    </dependencies> @@ -86,15 +91,34 @@            <source>1.8</source>            <target>1.8</target>          </configuration> +        <executions> +        	<execution> +        		<goals> +        			<goal>compile</goal> +        			<goal>testCompile</goal> +        		</goals> +        	</execution> +        </executions>        </plugin> +      <plugin> +    	<groupId>org.apache.maven.plugins</groupId> +    	<artifactId>maven-jar-plugin</artifactId> +    	<version>3.1.0</version> +    	<executions> +        	<execution> +            	<goals> +                	<goal>test-jar</goal> +            	</goals> +        	</execution> +    	</executions> +	  </plugin> -      <!-- enable co-existence of testng and junit --> +      <!-- enable co-existence of testng and junit -->                        <plugin>          <artifactId>maven-surefire-plugin</artifactId>          <version>${surefire.version}</version>          <configuration> -          <threadCount>1</threadCount> -          <argLine>--add-modules java.xml.bind</argLine> +          <threadCount>1</threadCount>                    </configuration>          <dependencies>            <dependency> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/Pvp2SProfileCoreSpringResourceProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/Pvp2SProfileCoreSpringResourceProvider.java index 2779ee1d..232e4ae9 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/Pvp2SProfileCoreSpringResourceProvider.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/Pvp2SProfileCoreSpringResourceProvider.java @@ -19,11 +19,11 @@  package at.gv.egiz.eaaf.modules.pvp2; +import at.gv.egiz.components.spring.api.SpringResourceProvider; +  import org.springframework.core.io.ClassPathResource;  import org.springframework.core.io.Resource; -import at.gv.egiz.components.spring.api.SpringResourceProvider; -  public class Pvp2SProfileCoreSpringResourceProvider implements SpringResourceProvider {    @Override 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 b1ac8e75..69b94255 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 @@ -36,11 +36,15 @@ import org.opensaml.xmlsec.signature.support.SignatureConstants;  import com.google.common.collect.ImmutableMap;  public interface PvpConstants extends PvpAttributeDefinitions { -  //module configuration parameters +  // 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 CONFIG_PROP_SEC_ENCRYPTION_DATA = "pvp2.security.alg.enc.data"; +  String CONFIG_PROP_SEC_ENCRYPTION_KEY_RSA_ALG = "pvp2.security.alg.enc.key.rsa"; +  String CONFIG_PROP_SEC_ENCRYPTION_KEY_EC_ALG = "pvp2.security.alg.enc.key.ec"; +  String CONFIG_PROPERTY_PVP2_ENABLE_ENCRYPTION = "pvp2.assertion.encryption.active"; -  //Default values +  // Default values    String DEFAULT_SIGNING_METHODE_RSA =        SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256;    String DEFAULT_SIGNING_METHODE_EC = @@ -49,12 +53,13 @@ public interface PvpConstants extends PvpAttributeDefinitions {    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_BLOCKCIPHER_AES128_GCM; +  String DEFAULT_ASYM_ENCRYPTION_METHODE_RSA =        EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP; +  String DEFAULT_ASYM_ENCRYPTION_METHODE_EC = +      EncryptionConstants.ALGO_ID_KEYAGREEMENT_DH; - -  //PVP entity categories +  // 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"; @@ -152,19 +157,22 @@ public interface PvpConstants extends PvpAttributeDefinitions {    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(); +          .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 e8da499c..83bfee84 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 @@ -21,6 +21,7 @@ package at.gv.egiz.eaaf.modules.pvp2.api.binding;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; +import javax.xml.namespace.QName;  import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface;  import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; @@ -30,7 +31,7 @@ import net.shibboleth.utilities.java.support.net.URIComparator;  public interface IDecoder {    InboundMessageInterface decode(HttpServletRequest req, HttpServletResponse resp, -      IPvp2MetadataProvider metadataProvider, boolean isSpEndPoint, URIComparator comparator) +      IPvp2MetadataProvider metadataProvider, QName peerEntityRole, 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 691d6574..5a8bc4fb 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 @@ -60,7 +60,7 @@ 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 SecurityException        In case of an error +   * @throws SecurityException In case of an error     */    void encodeResponse(HttpServletRequest req, HttpServletResponse resp,        StatusResponseType response, String targetLocation, String relayState, EaafX509Credential credentials, 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 index 568b617d..ce6451c0 100644 --- 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 @@ -4,7 +4,6 @@ import javax.annotation.Nonnull;  import org.opensaml.security.x509.X509Credential; -  public interface EaafX509Credential extends X509Credential {    /** diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataBuilderConfiguration.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataBuilderConfiguration.java index 128d4c2f..3d9125fe 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataBuilderConfiguration.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataBuilderConfiguration.java @@ -22,15 +22,15 @@ package at.gv.egiz.eaaf.modules.pvp2.api.metadata;  import java.util.Collection;  import java.util.List; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +  import org.opensaml.saml.saml2.core.Attribute;  import org.opensaml.saml.saml2.metadata.ContactPerson;  import org.opensaml.saml.saml2.metadata.Organization;  import org.opensaml.saml.saml2.metadata.RequestedAttribute;  import org.opensaml.security.credential.Credential; -import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; -import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; -  /**   * PVP Metadata builder configuration.   * diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IRefreshableMetadataProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IRefreshableMetadataProvider.java index 39536771..cc492345 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IRefreshableMetadataProvider.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IRefreshableMetadataProvider.java @@ -27,7 +27,7 @@ import org.opensaml.saml.metadata.resolver.RefreshableMetadataResolver;   * @author tlenz   *   */ -public interface IRefreshableMetadataProvider extends RefreshableMetadataResolver{ +public interface IRefreshableMetadataProvider extends RefreshableMetadataResolver {    /**     * Refresh a entity or load a entity in a metadata provider. diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/IAuthnRequestPostProcessor.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/IAuthnRequestPostProcessor.java index 2e84413e..9f7a5980 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/IAuthnRequestPostProcessor.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/IAuthnRequestPostProcessor.java @@ -31,7 +31,8 @@ import org.opensaml.saml.saml2.metadata.SPSSODescriptor;   * SAML2 Authn. request post-processor.   *   * <p> - * Implementations of this interface are executed before user authentication starts. + * Implementations of this interface are executed before user authentication + * starts.   * </p>   *   * @author tlenz @@ -42,12 +43,13 @@ public interface IAuthnRequestPostProcessor {    /**     * Authn. request post-processor     * -   * @param httpReq http request -   * @param pendingReq current pending request -   * @param authReq received SAML2 authentication request +   * @param httpReq         http request +   * @param pendingReq      current pending request +   * @param authReq         received SAML2 authentication request     * @param spSsoDescriptor Metadata descriptor of the requested SP -   * @throws AuthnRequestValidatorException In case of a validation error, -   *     if post processor implements additional validation +   * @throws AuthnRequestValidatorException In case of a validation error, if post +   *                                        processor implements additional +   *                                        validation     */    void process(HttpServletRequest httpReq, IRequest pendingReq, AuthnRequest authReq,        SPSSODescriptor spSsoDescriptor) throws AuthnRequestValidatorException; diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/Pvp2InternalErrorException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/Pvp2InternalErrorException.java new file mode 100644 index 00000000..0b69897b --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/Pvp2InternalErrorException.java @@ -0,0 +1,12 @@ +package at.gv.egiz.eaaf.modules.pvp2.exception; + +public class Pvp2InternalErrorException extends Pvp2Exception { + +  private static final long serialVersionUID = 496637421176810375L; + +  public Pvp2InternalErrorException(Throwable wrapped) { +    super("internal.pvp.98", new Object[] { wrapped.getMessage() }, wrapped); + +  } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlMessageValidationException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlMessageValidationException.java new file mode 100644 index 00000000..774d0927 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlMessageValidationException.java @@ -0,0 +1,12 @@ +package at.gv.egiz.eaaf.modules.pvp2.exception; + +public class SamlMessageValidationException extends Pvp2Exception { + +  private static final long serialVersionUID = 2545822499416501014L; + +  public SamlMessageValidationException(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/SamlMetadataSignatureException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlMetadataSignatureException.java index 711fa41f..9ef3a673 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlMetadataSignatureException.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlMetadataSignatureException.java @@ -21,17 +21,33 @@ package at.gv.egiz.eaaf.modules.pvp2.exception;  import org.opensaml.saml.saml2.core.StatusCode; -public class SamlMetadataSignatureException extends Pvp2Exception { +public class SamlMetadataSignatureException extends Pvp2MetadataException {    private static final long serialVersionUID = 1L; -  public SamlMetadataSignatureException() { -    super("pvp2.25", null); +  /** +   * In case of a SAML2 metadata-signature verification error. +   *  +   * @param metadataUrl Path metadata that should be loaded +   * @param reason      Details on error +   * +   */ +  public SamlMetadataSignatureException(String metadataUrl, String reason) { +    super("internal.pvp.07", new Object[] { metadataUrl, reason });      this.statusCodeValue = StatusCode.REQUESTER; +    } -  public SamlMetadataSignatureException(final Throwable e) { -    super("pvp2.25", null, e); +  /** +   * In case of a SAML2 metadata-signature verification error. +   * +   * @param metadataUrl Path metadata that should be loaded +   * @param reason      Details on error +   * @param e           Error +   */ +  public SamlMetadataSignatureException(String metadataUrl, String reason, final Throwable e) { +    super("internal.pvp.07", new Object[] { metadataUrl, reason }, e);      this.statusCodeValue = StatusCode.REQUESTER; +    }  } 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 index ae108c35..3543d85a 100644 --- 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 @@ -1,15 +1,29 @@  package at.gv.egiz.eaaf.modules.pvp2.impl.binding; +import javax.xml.namespace.QName; +  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.message.InboundMessageInterface;  import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2InternalErrorException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlBindingException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlMessageValidationException;  import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; +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.utils.Saml2Utils;  import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.PvpSamlMessageHandlerChain;  import org.opensaml.core.config.ConfigurationService;  import org.opensaml.messaging.context.BaseContext;  import org.opensaml.messaging.context.MessageContext; +import org.opensaml.messaging.decoder.MessageDecodingException; +import org.opensaml.messaging.decoder.servlet.HttpServletRequestMessageDecoder; +import org.opensaml.messaging.handler.MessageHandlerException;  import org.opensaml.saml.common.SAMLObject;  import org.opensaml.saml.common.SignableSAMLObject;  import org.opensaml.saml.common.binding.SAMLBindingSupport; @@ -19,6 +33,8 @@ 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.core.RequestAbstractType; +import org.opensaml.saml.saml2.core.StatusResponseType;  import org.opensaml.saml.saml2.metadata.SingleSignOnService;  import org.opensaml.saml.saml2.metadata.impl.SingleSignOnServiceBuilder;  import org.opensaml.xmlsec.SignatureSigningParameters; @@ -28,21 +44,62 @@ import org.opensaml.xmlsec.context.SecurityParametersContext;  import org.opensaml.xmlsec.signature.support.SignatureConstants;  import org.springframework.beans.factory.annotation.Autowired; +import com.google.common.base.Optional; +import com.google.common.base.Predicates; +import com.google.common.base.Throwables; +import com.google.common.collect.FluentIterable; +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; +  /**   * Abstract Binding implements common code for SAML2 binding implementations.   *   * @author tlenz   *   */ +@Slf4j  public abstract class AbstractBinding { -  @Autowired protected IConfiguration basicConfig; +  @Autowired +  protected IConfiguration basicConfig;    public abstract String getSaml2BindingName(); +  protected MessageContext<SAMLObject> internalMessageDecode( +      HttpServletRequestMessageDecoder<SAMLObject> decoder, +      String binding) throws Pvp2Exception { +    try { +      decoder.initialize(); +      decoder.decode(); + +    } catch (final ComponentInitializationException e) { +      log.warn("Internal initialization error. Reason: {}", e.getMessage()); +      throw new Pvp2InternalErrorException(e); + +    } catch (final MessageDecodingException e) { +      final Optional<Throwable> pvpException = FluentIterable.from( +          Throwables.getCausalChain(e)).filter( +              Predicates.instanceOf(Pvp2Exception.class)).first(); + +      if (pvpException.isPresent()) { +        throw (Pvp2Exception) pvpException.get(); + +      } else { +        throw new SamlBindingException("internal.pvp.95", +            new Object[] { binding, "decoding", e.getMessage() }, +            e); + +      } + +    } + +    return decoder.getMessageContext(); + +  } +    protected MessageContext<SAMLObject> buildBasicMessageContext(        SAMLMessageEncoder encoder, SignableSAMLObject response) { -    final MessageContext<SAMLObject> messageContext =  new MessageContext<SAMLObject>(); +    final MessageContext<SAMLObject> messageContext = new MessageContext<>();      messageContext.setMessage(response);      encoder.setMessageContext(messageContext);      return messageContext; @@ -63,7 +120,7 @@ public abstract class AbstractBinding {      signingParams.setSignatureReferenceDigestMethod(          Saml2Utils.getDigestAlgorithm(signingParams.getSignatureAlgorithm())); -    signingParams.setKeyInfoGenerator(Saml2Utils.getKeyInfoGenerator(credentials, false)); +    signingParams.setKeyInfoGenerator(Saml2Utils.getKeyInfoGenerator(credentials, true));      return securityParamContext; @@ -83,16 +140,16 @@ public abstract class AbstractBinding {    }    protected void injectInboundMessageContexts(MessageContext<SAMLObject> messageContext, -      IPvp2MetadataProvider metadataProvider) { -    messageContext.addSubcontext(new SAMLPeerEntityContext()); +      IPvp2MetadataProvider metadataProvider, QName peerEntityRole) throws Pvp2InternalErrorException { +    final SAMLPeerEntityContext peerEntityContext = new SAMLPeerEntityContext(); +    peerEntityContext.setRole(peerEntityRole); +    messageContext.addSubcontext(peerEntityContext);      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); @@ -100,9 +157,63 @@ public abstract class AbstractBinding {      sigValParameters.setBlacklistedAlgorithms(          ConfigurationService.get(SignatureValidationConfiguration.class) -          .getBlacklistedAlgorithms()); +            .getBlacklistedAlgorithms());      sigValParameters.setSignatureTrustEngine(          TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider));    } + +  protected void performMessageValidation(PvpSamlMessageHandlerChain messageValidatorChain, +      MessageContext<SAMLObject> messageContext) throws Pvp2Exception { +    try { +      messageValidatorChain.initialize(); +      messageValidatorChain.invoke(messageContext); + +    } catch (final ComponentInitializationException e) { +      log.warn("Internal initialization error. Reason: {}", e.getMessage()); +      throw new Pvp2InternalErrorException(e); + +    } catch (final MessageHandlerException e) { +      log.info("SAML message validation error. Reason: {}", e.getMessage()); +      final Optional<Throwable> pvpException = FluentIterable.from( +          Throwables.getCausalChain(e)).filter( +              Predicates.instanceOf(Pvp2Exception.class)).first(); + +      if (pvpException.isPresent()) { +        throw (Pvp2Exception) pvpException.get(); + +      } else { +        throw new SamlMessageValidationException("internal.pvp.11", +            new Object[] { e.getMessage() }, e); + +      } +    } +  } + +  protected InboundMessageInterface performMessageDecodePostProcessing( +      MessageContext<SAMLObject> messageContext, boolean isVerified) { +    InboundMessage msg = null; +    if (messageContext.getMessage() instanceof RequestAbstractType) { +      final RequestAbstractType inboundMessage = +          (RequestAbstractType) messageContext.getMessage(); +      msg = new PvpSProfileRequest(inboundMessage, getSaml2BindingName()); +      msg.setEntityID(inboundMessage.getIssuer().getValue()); + +    } else if (messageContext.getMessage() instanceof StatusResponseType) { +      final StatusResponseType inboundMessage = +          (StatusResponseType) messageContext.getMessage(); +      msg = new PvpSProfileResponse(inboundMessage); +      msg.setEntityID(inboundMessage.getIssuer().getValue()); + +    } else { +      // create empty container if request type is unknown +      msg = new InboundMessage(); + +    } + +    msg.setVerified(isVerified); +    msg.setRelayState(SAMLBindingSupport.getRelayState(messageContext)); + +    return msg; +  }  } 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 6f39392d..c679de20 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 @@ -21,6 +21,7 @@ package at.gv.egiz.eaaf.modules.pvp2.impl.binding;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; +import javax.xml.namespace.QName;  import at.gv.egiz.eaaf.core.api.IRequest;  import at.gv.egiz.eaaf.core.api.gui.IGuiBuilderConfigurationFactory; @@ -36,16 +37,17 @@ 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.verification.EaafSamlProtocolMessageXmlSignatureSecurityHandler; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.PvpSamlMessageHandlerChain;  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.binding.impl.CheckMessageVersionHandler; +import org.opensaml.saml.common.binding.security.impl.MessageLifetimeSecurityHandler; +import org.opensaml.saml.common.binding.security.impl.ReceivedEndpointSecurityHandler;  import org.opensaml.saml.common.messaging.SAMLMessageSecuritySupport;  import org.opensaml.saml.common.xml.SAMLConstants;  import org.opensaml.saml.saml2.core.RequestAbstractType; @@ -53,7 +55,6 @@ import org.opensaml.saml.saml2.core.StatusResponseType;  import org.springframework.beans.factory.annotation.Autowired;  import lombok.extern.slf4j.Slf4j; -import net.shibboleth.utilities.java.support.component.ComponentInitializationException;  import net.shibboleth.utilities.java.support.net.URIComparator;  @Slf4j @@ -78,35 +79,34 @@ public class PostBinding extends AbstractBinding implements IDecoder, IEncoder {            guiConfigFactory.getSpSpecificSaml2PostConfiguration(pendingReq,                "pvp_postbinding_template.html", authConfig.getConfigurationRootDirectory()); -      final HttpPostEncoderWithOwnTemplate encoder -          = new HttpPostEncoderWithOwnTemplate(guiConfig, guiBuilder); +      final HttpPostEncoderWithOwnTemplate encoder = new HttpPostEncoderWithOwnTemplate(guiConfig, +          guiBuilder);        encoder.setHttpServletResponse(httpResp); -      //inject message context +      // inject message context        final MessageContext<SAMLObject> messageContext = buildBasicMessageContext(encoder, request); -      //inject signing context +      // inject signing context        messageContext.addSubcontext(injectSigningInfos(credentials)); -      //set endpoint url +      // set endpoint url        messageContext.addSubcontext(injectEndpointInfos(request, targetLocation)); - -      //set relayState of exists +      // set relayState of exists        SAMLBindingSupport.setRelayState(messageContext, relayState); -      //sign SAML2 message +      // sign SAML2 message        SAMLMessageSecuritySupport.signMessage(messageContext); -      //encode message +      // encode message        encoder.initialize();        encoder.encode();      } catch (final Exception e) {        log.warn("Can not encode SAML2 Post-Binding request", e);        throw new SamlBindingException("internal.pvp.95", -          new Object[] {PvpConstants.POST, "encoding", e.getMessage()}, +          new Object[] { PvpConstants.POST, "encoding", e.getMessage() },            e);      } @@ -116,7 +116,7 @@ public class PostBinding extends AbstractBinding implements IDecoder, IEncoder {    public void encodeResponse(final HttpServletRequest httpReq, final HttpServletResponse httpResp,        final StatusResponseType response, final String targetLocation, final String relayState,        final EaafX509Credential credentials, final IRequest pendingReq) -          throws Pvp2Exception { +      throws Pvp2Exception {      try {        log.debug("create SAML POSTBinding response"); @@ -130,99 +130,62 @@ public class PostBinding extends AbstractBinding implements IDecoder, IEncoder {        encoder.setHttpServletResponse(httpResp); -      //inject message context +      // inject message context        final MessageContext<SAMLObject> messageContext = buildBasicMessageContext(encoder, response); -      //inject signing context +      // inject signing context        messageContext.addSubcontext(injectSigningInfos(credentials)); -      //set endpoint url +      // set endpoint url        messageContext.addSubcontext(injectEndpointInfos(response, targetLocation)); -      //set relayState of exists +      // set relayState of exists        SAMLBindingSupport.setRelayState(messageContext, relayState); -      //sign SAML2 message +      // sign SAML2 message        SAMLMessageSecuritySupport.signMessage(messageContext); -      //encode message +      // encode message        encoder.initialize();        encoder.encode();      } catch (final Exception e) {        log.warn("Can not encode SAML2 Post-Binding response", e);        throw new SamlBindingException("internal.pvp.95", -          new Object[] {PvpConstants.POST, "encoding", e.getMessage()}, +          new Object[] { PvpConstants.POST, "encoding", e.getMessage() },            e);      }    } - - - -    @Override    public InboundMessageInterface decode(final HttpServletRequest req,        final HttpServletResponse resp, final IPvp2MetadataProvider metadataProvider, -      final boolean isSpEndPoint, final URIComparator comparator) +      QName peerEntityRole, final URIComparator comparator)        throws Pvp2Exception { -    //TODO: check, if we should re-implement HTTPPostDecoder to collect the last http parameter!!! -    final EaafHttpPostDecoder decode = new EaafHttpPostDecoder(); -    decode.setHttpServletRequest(req); - -    //decode request -    try { -      decode.initialize(); -      decode.decode(); - -    } catch (MessageDecodingException | ComponentInitializationException e) { -      throw new SamlBindingException("internal.pvp.95", -          new Object[] {PvpConstants.POST, "decoding", e.getMessage()}, -          e); -    } - -    final MessageContext<SAMLObject> messageContext = decode.getMessageContext(); +    final EaafHttpPostDecoder decode = new EaafHttpPostDecoder(req); +    final MessageContext<SAMLObject> messageContext = internalMessageDecode(decode, PvpConstants.POST); -    if (SAMLBindingSupport.isSigningCapableBinding(messageContext)) { +    // check if PVP2 AuthnRequest is signed +    if (!SAMLBindingSupport.isMessageSigned(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); +    // inject informations into message context that are required for further +    // processing +    injectInboundMessageContexts(messageContext, metadataProvider, peerEntityRole); +    final PvpSamlMessageHandlerChain messageValidatorChain = +        buildMessageValidationChain(req, comparator, metadataProvider); +    log.trace("Message validation (Signature, ...) on binding-level starts ... "); +    performMessageValidation(messageValidatorChain, messageContext); -    //TODO: add sig validation!!! +    log.trace("Message validation successful"); +    return performMessageDecodePostProcessing(messageContext, true); - - -    InboundMessage msg = null; - -    if (messageContext.getMessage() instanceof RequestAbstractType) { -      final RequestAbstractType inboundMessage = -          (RequestAbstractType) messageContext.getMessage(); -      msg = new PvpSProfileRequest(inboundMessage, getSaml2BindingName()); -      msg.setEntityID(inboundMessage.getIssuer().getValue()); - -    } else if (messageContext.getMessage() instanceof StatusResponseType) { -      final StatusResponseType inboundMessage = -          (StatusResponseType) messageContext.getMessage(); -      msg = new PvpSProfileResponse(inboundMessage); -      msg.setEntityID(inboundMessage.getIssuer().getValue()); - -    } else { -      // create empty container if request type is unknown -      msg = new InboundMessage(); - -    } - -    msg.setVerified(false); -    msg.setRelayState(SAMLBindingSupport.getRelayState(messageContext)); - -    return msg;    }    @Override @@ -234,5 +197,41 @@ public class PostBinding extends AbstractBinding implements IDecoder, IEncoder {    @Override    public String getSaml2BindingName() {      return SAMLConstants.SAML2_POST_BINDING_URI; + +  } + +  private PvpSamlMessageHandlerChain buildMessageValidationChain(HttpServletRequest req, +      URIComparator comparator, IPvp2MetadataProvider metadataProvider) { +    final PvpSamlMessageHandlerChain messageValidatorChain = new PvpSamlMessageHandlerChain(); + +    final ReceivedEndpointSecurityHandler endpointSecurityHandler = new ReceivedEndpointSecurityHandler(); +    endpointSecurityHandler.setHttpServletRequest(req); +    endpointSecurityHandler.setURIComparator(comparator); + +    messageValidatorChain.addHandler(new CheckMessageVersionHandler()); +    messageValidatorChain.addHandler(endpointSecurityHandler); +    messageValidatorChain.addHandler( +        new EaafSamlProtocolMessageXmlSignatureSecurityHandler(metadataProvider)); +    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); + +    return messageValidatorChain; +    }  } 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 5f74053d..f62f8a11 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 @@ -21,6 +21,7 @@ package at.gv.egiz.eaaf.modules.pvp2.impl.binding;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; +import javax.xml.namespace.QName;  import at.gv.egiz.eaaf.core.api.IRequest;  import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; @@ -32,15 +33,11 @@ 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.EaafHttpRedirectDeflateDecoder; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.EaafSaml2HttpRedirectDeflateSignatureSecurityHandler;  import at.gv.egiz.eaaf.modules.pvp2.impl.verification.PvpSamlMessageHandlerChain;  import org.opensaml.messaging.context.MessageContext; -import org.opensaml.messaging.decoder.MessageDecodingException; -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; @@ -48,13 +45,11 @@ import org.opensaml.saml.common.binding.security.impl.MessageLifetimeSecurityHan  import org.opensaml.saml.common.messaging.context.SAMLBindingContext;  import org.opensaml.saml.common.xml.SAMLConstants;  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.slf4j.Logger;  import org.slf4j.LoggerFactory; -import net.shibboleth.utilities.java.support.component.ComponentInitializationException;  import net.shibboleth.utilities.java.support.net.URIComparator;  public class RedirectBinding extends AbstractBinding implements IDecoder, IEncoder { @@ -137,26 +132,11 @@ public class RedirectBinding extends AbstractBinding implements IDecoder, IEncod    @Override    public InboundMessageInterface decode(final HttpServletRequest req,        final HttpServletResponse resp, final IPvp2MetadataProvider metadataProvider, -      final boolean isSpEndPoint, final URIComparator comparator) +      QName peerEntityRole, final URIComparator comparator)        throws Pvp2Exception { -    // TODO: implement one flat decoder to get SAML2 request/response parametes as -    // same as in SAML2HTTPRedirectDeflateSignatureSecurityHandler -    final EaafHttpRedirectDeflateDecoder decode = new EaafHttpRedirectDeflateDecoder(); -    decode.setHttpServletRequest(req); - -    // decode request -    try { -      decode.initialize(); -      decode.decode(); - -    } catch (MessageDecodingException | ComponentInitializationException e) { -      throw new SamlBindingException("internal.pvp.95", -          new Object[] { PvpConstants.REDIRECT, "decoding", e.getMessage() }, -          e); -    } - -    final MessageContext<SAMLObject> messageContext = decode.getMessageContext(); +    final EaafHttpRedirectDeflateDecoder decode = new EaafHttpRedirectDeflateDecoder(req); +    final MessageContext<SAMLObject> messageContext = internalMessageDecode(decode, PvpConstants.REDIRECT);      final SAMLBindingContext bindingContext = messageContext.getSubcontext(SAMLBindingContext.class, true);      if (!bindingContext.hasBindingSignature()) { @@ -165,171 +145,18 @@ public class RedirectBinding extends AbstractBinding implements IDecoder, IEncod      } -    //inject informations into message context that are required for further processing -    injectInboundMessageContexts(messageContext, metadataProvider); +    // inject informations into message context that are required for further +    // processing +    injectInboundMessageContexts(messageContext, metadataProvider, peerEntityRole); +    final PvpSamlMessageHandlerChain messageValidatorChain = +        buildMessageValidationChain(req, 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); +    log.trace("Message validation (Signature, ...) on binding-level starts ... "); +    performMessageValidation(messageValidatorChain, messageContext); +    log.trace("Message validation successful"); +    return performMessageDecodePostProcessing(messageContext, true); -    try { -      messageValidatorChain.initialize(); -      messageValidatorChain.invoke(messageContext); - -    } 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.getMessage() instanceof RequestAbstractType) { -      final RequestAbstractType inboundMessage = -          (RequestAbstractType) messageContext.getMessage(); -      msg = new PvpSProfileRequest(inboundMessage, getSaml2BindingName()); -      msg.setEntityID(inboundMessage.getIssuer().getValue()); - -    } else if (messageContext.getMessage() instanceof StatusResponseType) { -      final StatusResponseType inboundMessage = -          (StatusResponseType) messageContext.getMessage(); -      msg = new PvpSProfileResponse(inboundMessage); -      msg.setEntityID(inboundMessage.getIssuer().getValue()); - -    } else { -      // create empty container if request type is unknown -      msg = new InboundMessage(); - -    } - -    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 @@ -341,5 +168,38 @@ public class RedirectBinding extends AbstractBinding implements IDecoder, IEncod    @Override    public String getSaml2BindingName() {      return SAMLConstants.SAML2_REDIRECT_BINDING_URI; + +  } + +  private PvpSamlMessageHandlerChain buildMessageValidationChain(HttpServletRequest req, +      IPvp2MetadataProvider metadataProvider) { +    final PvpSamlMessageHandlerChain messageValidatorChain = new PvpSamlMessageHandlerChain(); +    final EaafSaml2HttpRedirectDeflateSignatureSecurityHandler redirectBindingSignaturHandler = +        new EaafSaml2HttpRedirectDeflateSignatureSecurityHandler(metadataProvider); +    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); + +    return messageValidatorChain; +    }  } 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 e0df2d2a..49e93f0a 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 @@ -21,6 +21,7 @@ package at.gv.egiz.eaaf.modules.pvp2.impl.binding;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; +import javax.xml.namespace.QName;  import at.gv.egiz.eaaf.core.api.IRequest;  import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; @@ -29,27 +30,29 @@ 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.InvalidPvpRequestException;  import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2InternalErrorException;  import at.gv.egiz.eaaf.modules.pvp2.exception.SamlBindingException; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;  import at.gv.egiz.eaaf.modules.pvp2.impl.verification.EaafMessageContextInitializationHandler; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.EaafSamlProtocolMessageXmlSignatureSecurityHandler;  import at.gv.egiz.eaaf.modules.pvp2.impl.verification.PvpSamlMessageHandlerChain;  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.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.soap.messaging.context.SOAP11Context;  import lombok.extern.slf4j.Slf4j;  import net.shibboleth.utilities.java.support.component.ComponentInitializationException; @@ -61,72 +64,55 @@ public class SoapBinding extends AbstractBinding implements IDecoder, IEncoder {    @Override    public InboundMessageInterface decode(final HttpServletRequest req,        final HttpServletResponse resp, final IPvp2MetadataProvider metadataProvider, -      final boolean isSpEndPoint, final URIComparator comparator) +      QName peerEntityRole, final URIComparator comparator)        throws Pvp2Exception { -    try { -      final HTTPSOAP11Decoder soapDecoder = new HTTPSOAP11Decoder(); +    final HTTPSOAP11Decoder soapDecoder = new HTTPSOAP11Decoder(); +    soapDecoder.setHttpServletRequest(req); + +    injectMessageHandlerChain(soapDecoder, metadataProvider, peerEntityRole); + +    final MessageContext<SAMLObject> messageContext = +        internalMessageDecode(soapDecoder, PvpConstants.SOAP); + +    // check if PVP2 AuthnRequest is signed +    if (!SAMLBindingSupport.isMessageSigned(messageContext)) { +      log.info("SAML Post-Binding message contains no signature. Message will be rejected"); +      throw new InvalidPvpRequestException("internal.pvp.02", null); + +    } + +    return performMessageDecodePostProcessing(messageContext, true); +  } +  private void injectMessageHandlerChain(HTTPSOAP11Decoder soapDecoder, +      IPvp2MetadataProvider metadataProvider, QName peerEntityRole) throws Pvp2InternalErrorException { +    try {        final PvpSamlMessageHandlerChain messageValidatorChain = new PvpSamlMessageHandlerChain(); -      soapDecoder.setBodyHandler(messageValidatorChain); +      messageValidatorChain.addHandler(new EaafMessageContextInitializationHandler(metadataProvider)); +      messageValidatorChain.addHandler(new SAMLSOAPDecoderBodyHandler()); -      final SAMLProtocolMessageXMLSignatureSecurityHandler msgSignatureValidationHandler = -          new SAMLProtocolMessageXMLSignatureSecurityHandler(); +      final SAMLProtocolAndRoleHandler samlProtocolHandler = new SAMLProtocolAndRoleHandler(); +      samlProtocolHandler.setProtocol(SAMLConstants.SAML20P_NS); +      samlProtocolHandler.setRole(peerEntityRole); +      messageValidatorChain.addHandler(samlProtocolHandler); -      messageValidatorChain.addHandler(new EaafMessageContextInitializationHandler());        messageValidatorChain.addHandler(new CheckMessageVersionHandler()); -      messageValidatorChain.addHandler(new SAMLProtocolAndRoleHandler()); -      messageValidatorChain.addHandler(msgSignatureValidationHandler); +      messageValidatorChain.addHandler( +          new EaafSamlProtocolMessageXmlSignatureSecurityHandler(metadataProvider));        messageValidatorChain.addHandler(new MessageLifetimeSecurityHandler()); -      messageValidatorChain.addHandler(new SAMLSOAPDecoderBodyHandler()); -      // decode message -      soapDecoder.initialize(); -      soapDecoder.decode(); +      messageValidatorChain.initialize(); -      final MessageContext<SAMLObject> messageContext = soapDecoder.getMessageContext(); -      messageContext.getMessage(); +      soapDecoder.setBodyHandler(messageValidatorChain); + +    } catch (final ComponentInitializationException e) { +      log.warn("Internal initialization error. Reason: {}", e.getMessage()); +      throw new Pvp2InternalErrorException(e); -    } 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); +    }    @Override @@ -157,6 +143,11 @@ public class SoapBinding extends AbstractBinding implements IDecoder, IEncoder {        // inject message context        final MessageContext<SAMLObject> messageContext = buildBasicMessageContext(encoder, response); +      //inject SOAP enveloped +      final SOAP11Context soap11Context = new SOAP11Context(); +      soap11Context.setEnvelope(Saml2Utils.buildSoap11Envelope(response)); +      messageContext.addSubcontext(soap11Context); +        // inject signing context        messageContext.addSubcontext(injectSigningInfos(credentials)); @@ -172,6 +163,7 @@ public class SoapBinding extends AbstractBinding implements IDecoder, IEncoder {        // 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", 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 1667a07d..bf201803 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 @@ -61,7 +61,8 @@ public class CitizenTokenBuilder {     */    public static XMLObject buildAttributeIntegerValue(final int value) {      final XSIntegerBuilder integerBuilder = -        (XSIntegerBuilder) XMLObjectProviderRegistrySupport.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 d5893d4a..92922e09 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 @@ -20,6 +20,7 @@  package at.gv.egiz.eaaf.modules.pvp2.impl.builder;  import java.io.IOException; +import java.text.MessageFormat;  import java.util.Collection;  import java.util.List; @@ -28,6 +29,13 @@ import javax.xml.parsers.ParserConfigurationException;  import javax.xml.transform.TransformerException;  import javax.xml.transform.TransformerFactoryConfigurationError; +import at.gv.egiz.eaaf.core.exceptions.EaafBuilderException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +  import org.apache.commons.lang3.StringUtils;  import org.joda.time.DateTime;  import org.opensaml.core.xml.io.MarshallingException; @@ -57,14 +65,8 @@ import org.opensaml.xmlsec.keyinfo.impl.X509KeyInfoGeneratorFactory;  import org.opensaml.xmlsec.signature.support.SignatureException;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service;  import org.w3c.dom.Element; -import at.gv.egiz.eaaf.core.exceptions.EaafException; -import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration; -import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;  import net.shibboleth.utilities.java.support.xml.SerializeSupport;  /** @@ -74,9 +76,10 @@ import net.shibboleth.utilities.java.support.xml.SerializeSupport;   *   */ -@Service("PVPMetadataBuilder")  public class PvpMetadataBuilder { +  private static final String ERROR_ROLE_DESCR = "Can not build {0}"; +    private static final Logger log = LoggerFactory.getLogger(PvpMetadataBuilder.class);    X509KeyInfoGeneratorFactory keyInfoFactory = null; @@ -133,6 +136,12 @@ public class PvpMetadataBuilder {        final RoleDescriptor idpSsoDesc = generateIdpMetadata(config);        if (idpSsoDesc != null) {          entityDescriptor.getRoleDescriptors().add(idpSsoDesc); + +      } else { +        final String msg = MessageFormat.format(ERROR_ROLE_DESCR, +            IDPSSODescriptor.DEFAULT_ELEMENT_LOCAL_NAME); +        throw new EaafBuilderException("internal.pvp.13", new Object[] { msg }, msg); +        }      } @@ -142,12 +151,17 @@ public class PvpMetadataBuilder {        final RoleDescriptor spSsoDesc = generateSpMetadata(config);        if (spSsoDesc != null) {          entityDescriptor.getRoleDescriptors().add(spSsoDesc); + +      } else { +        final String msg = MessageFormat.format(ERROR_ROLE_DESCR, SPSSODescriptor.DEFAULT_ELEMENT_LOCAL_NAME); +        throw new EaafBuilderException("internal.pvp.13", new Object[] { msg }, msg); +        }      } -    +      SignableSAMLObject metadataToSign; -     +      // build entities descriptor      if (config.buildEntitiesDescriptorAsRootElement()) {        final EntitiesDescriptor entitiesDescriptor = @@ -157,24 +171,24 @@ public class PvpMetadataBuilder {        entitiesDescriptor.setValidUntil(date.plusHours(config.getMetadataValidUntil()));        entitiesDescriptor.getEntityDescriptors().add(entityDescriptor);        metadataToSign = entitiesDescriptor; -      +      } else {        entityDescriptor.setValidUntil(date.plusHours(config.getMetadataValidUntil()));        entityDescriptor.setID(Saml2Utils.getSecureIdentifier());        metadataToSign = entityDescriptor; -       +      }      // sign metadata      final EaafX509Credential metadataSignCred = config.getMetadataSigningCredentials(); -    SignableSAMLObject signedMetadata = Saml2Utils.signSamlObject(metadataToSign, metadataSignCred, true); -     -    +    final SignableSAMLObject signedMetadata = Saml2Utils.signSamlObject(metadataToSign, metadataSignCred, +        true); +      // Serialize metadata -    final Element document =XMLObjectSupport.marshall(signedMetadata); -    String serializedMetadata = SerializeSupport.nodeToString(document); +    final Element document = XMLObjectSupport.marshall(signedMetadata); +    final String serializedMetadata = SerializeSupport.nodeToString(document);      return serializedMetadata; -     +    }    private RoleDescriptor generateSpMetadata(final IPvpMetadataBuilderConfiguration config) @@ -402,7 +416,10 @@ public class PvpMetadataBuilder {      idpSsoDescriptor.getKeyDescriptors().add(signKeyDescriptor);      // set IDP attribute set -    idpSsoDescriptor.getAttributes().addAll(config.getIdpPossibleAttributes()); +    if (config.getIdpPossibleAttributes() != null) { +      idpSsoDescriptor.getAttributes().addAll(config.getIdpPossibleAttributes()); + +    }      // set providable nameID formats      for (final String format : config.getIdpPossibleNameIdTypes()) { 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 d37d6724..5c44af24 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 @@ -44,7 +44,8 @@ public class SamlAttributeGenerator implements IAttributeGenerator<Attribute> {    private XMLObject buildAttributeIntegerValue(final int value) {      final XSIntegerBuilder integerBuilder = -        (XSIntegerBuilder) XMLObjectProviderRegistrySupport.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/logging/PvpModuleMessageSource.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/logging/PvpModuleMessageSource.java index 961f29cb..227ff30e 100644 --- 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 @@ -5,7 +5,6 @@ import java.util.List;  import at.gv.egiz.eaaf.core.api.logging.IMessageSourceLocation; -  public class PvpModuleMessageSource implements IMessageSourceLocation {    @Override 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 da958d5b..0ffa3789 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,16 +25,17 @@ import java.io.Serializable;  import javax.xml.parsers.ParserConfigurationException;  import javax.xml.transform.TransformerException; +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 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.IPvp2MetadataProvider; -import at.gv.egiz.eaaf.modules.pvp2.exception.NoMetadataInformationException;  import net.shibboleth.utilities.java.support.resolver.ResolverException;  public class InboundMessage implements InboundMessageInterface, Serializable { @@ -68,7 +69,7 @@ public class InboundMessage implements InboundMessageInterface, Serializable {      } catch (final ResolverException 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/metadata/AbstractChainingMetadataProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/AbstractChainingMetadataProvider.java index 3fc675e9..8a20b932 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 @@ -27,12 +27,17 @@ import java.util.HashMap;  import java.util.Iterator;  import java.util.List;  import java.util.Map; -import java.util.UUID;  import javax.annotation.Nonnull;  import javax.annotation.Nullable;  import javax.naming.ConfigurationException; +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.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider; +  import org.apache.commons.lang3.StringUtils;  import org.joda.time.DateTime;  import org.opensaml.core.criterion.EntityIdCriterion; @@ -43,11 +48,6 @@ import org.opensaml.saml.metadata.resolver.filter.MetadataFilter;  import org.opensaml.saml.metadata.resolver.impl.AbstractMetadataResolver;  import org.opensaml.saml.saml2.metadata.EntityDescriptor; -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.IPvp2MetadataProvider; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider;  import lombok.extern.slf4j.Slf4j;  import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;  import net.shibboleth.utilities.java.support.component.IdentifiedComponent; @@ -55,10 +55,13 @@ import net.shibboleth.utilities.java.support.resolver.CriteriaSet;  import net.shibboleth.utilities.java.support.resolver.ResolverException;  @Slf4j -public abstract class AbstractChainingMetadataProvider implements IGarbageCollectorProcessing, IRefreshableMetadataProvider,  +public abstract class AbstractChainingMetadataProvider implements IGarbageCollectorProcessing, +    IRefreshableMetadataProvider,      IDestroyableObject, IPvp2MetadataProvider, ClearableMetadataResolver { -   -  @Nonnull @NonnullElements private final List<MetadataResolver> internalResolvers; + +  @Nonnull +  @NonnullElements +  private final List<MetadataResolver> internalResolvers;    private DateTime lastRefeshTimestamp;    private boolean lastRefeshSuccessful;    private static Object mutex = new Object(); @@ -72,7 +75,6 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec    } -    /*     * (non-Javadoc)     * @@ -104,8 +106,6 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec    } - -    @Override    public synchronized boolean refreshMetadataProvider(final String entityId) {      try { @@ -130,7 +130,7 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec          // check if MetadataProvider is actually loaded          final MetadataResolver loadedResover = actuallyLoadedResolver.get(metadataUrl);          if (loadedResover instanceof RefreshableMetadataResolver) { -          ((RefreshableMetadataResolver)loadedResover).refresh(); +          ((RefreshableMetadataResolver) loadedResover).refresh();            log.info("SAML2 metadata for service provider: " + entityId + " is refreshed.");            return true; @@ -162,30 +162,29 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec     *     */    public void internalDestroy() { -      log.info("Destroying chained metadata resolvers ..."); +    log.info("Destroying chained metadata resolvers ..."); -      for (final MetadataResolver resolver : internalResolvers) { -        destroyMetadataResolver(resolver); -      } +    for (final MetadataResolver resolver : internalResolvers) { +      destroyMetadataResolver(resolver); +    } -      internalResolvers.clear(); +    internalResolvers.clear();    } -  /** {@inheritDoc} */ -  @Override  +  @Override    public final MetadataFilter getMetadataFilter() { -      log.warn("{} does NOT support {}", AbstractChainingMetadataProvider.class.getName(), -          MetadataFilter.class.getName()); -      return null; +    log.warn("{} does NOT support {}", AbstractChainingMetadataProvider.class.getName(), +        MetadataFilter.class.getName()); +    return null;    } -  /** {@inheritDoc} */ -  @Override  +  @Override    public final void setMetadataFilter(final MetadataFilter newFilter) {      log.warn("{} does NOT support {}", AbstractChainingMetadataProvider.class.getName(),          MetadataFilter.class.getName()); -      throw new UnsupportedOperationException("Metadata filters are not supported on AbstractChainingMetadataProvider"); +    throw new UnsupportedOperationException( +        "Metadata filters are not supported on AbstractChainingMetadataProvider");    }    /* @@ -221,17 +220,17 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec    }    @Override -  @Nullable  +  @Nullable    public final EntityDescriptor resolveSingle(@Nullable final CriteriaSet criteria) throws ResolverException {      for (final MetadataResolver resolver : internalResolvers) {        try { -          final EntityDescriptor descriptors = resolver.resolveSingle(criteria); -          if (descriptors != null) { -              return descriptors; -          } +        final EntityDescriptor descriptors = resolver.resolveSingle(criteria); +        if (descriptors != null) { +          return descriptors; +        }        } catch (final ResolverException e) { -          continue; +        continue;        } @@ -242,87 +241,90 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec    }    @Override -  @Nonnull  -  public final Iterable<EntityDescriptor> resolve(@Nullable final CriteriaSet criteria) throws ResolverException { -      for (final MetadataResolver resolver : internalResolvers) { -          try { -              final Iterable<EntityDescriptor> descriptors = resolver.resolve(criteria); -              if (descriptors != null && descriptors.iterator().hasNext()) { -                  return descriptors; -                   -              } -               -          } catch (final ResolverException e) { -              continue; -               -          } +  @Nonnull +  public final Iterable<EntityDescriptor> resolve(@Nullable final CriteriaSet criteria) +      throws ResolverException { +    for (final MetadataResolver resolver : internalResolvers) { +      try { +        final Iterable<EntityDescriptor> descriptors = resolver.resolve(criteria); +        if (descriptors != null && descriptors.iterator().hasNext()) { +          return descriptors; + +        } + +      } catch (final ResolverException e) { +        continue; +        } +    } -      return Collections.emptyList(); +    return Collections.emptyList();    } -   +    @Override    public final void clear() throws ResolverException { -      for (final MetadataResolver resolver : internalResolvers) { -          if (resolver instanceof ClearableMetadataResolver) { -              ((ClearableMetadataResolver) resolver).clear(); -          } +    for (final MetadataResolver resolver : internalResolvers) { +      if (resolver instanceof ClearableMetadataResolver) { +        ((ClearableMetadataResolver) resolver).clear();        } +    }    }    @Override    public final void clear(String entityID) throws ResolverException { -      for (final MetadataResolver resolver : internalResolvers) { -          if (resolver instanceof ClearableMetadataResolver) { -              ((ClearableMetadataResolver) resolver).clear(entityID); -          } +    for (final MetadataResolver resolver : internalResolvers) { +      if (resolver instanceof ClearableMetadataResolver) { +        ((ClearableMetadataResolver) resolver).clear(entityID);        } +    }    } -  @Override final public void refresh() throws ResolverException { -      this.lastRefeshSuccessful = false; -      for (final MetadataResolver resolver : internalResolvers) { -          if (resolver instanceof RefreshableMetadataResolver) { -              ((RefreshableMetadataResolver) resolver).refresh(); -               -          } +  @Override +  public final void refresh() throws ResolverException { +    this.lastRefeshSuccessful = false; +    for (final MetadataResolver resolver : internalResolvers) { +      if (resolver instanceof RefreshableMetadataResolver) { +        ((RefreshableMetadataResolver) resolver).refresh(); +        } -       -      this.lastRefeshTimestamp = DateTime.now(); -      this.lastRefeshSuccessful = true; +    } + +    this.lastRefeshTimestamp = DateTime.now(); +    this.lastRefeshSuccessful = true;    }    @Override -  @Nullable public DateTime getLastUpdate() { -      DateTime ret = null; -      for (final MetadataResolver resolver : internalResolvers) { -          if (resolver instanceof RefreshableMetadataResolver) { -              final DateTime lastUpdate = ((RefreshableMetadataResolver) resolver).getLastUpdate(); -              if (ret == null || ret.isBefore(lastUpdate)) { -                  ret = lastUpdate; -              } -          } +  @Nullable +  public DateTime getLastUpdate() { +    DateTime ret = null; +    for (final MetadataResolver resolver : internalResolvers) { +      if (resolver instanceof RefreshableMetadataResolver) { +        final DateTime lastUpdate = ((RefreshableMetadataResolver) resolver).getLastUpdate(); +        if (ret == null || ret.isBefore(lastUpdate)) { +          ret = lastUpdate; +        }        } -       -      return ret; +    } + +    return ret;    }    @Override -  @Nullable final public DateTime getLastRefresh() { -      DateTime ret = null; -      for (final MetadataResolver resolver : internalResolvers) { -          if (resolver instanceof RefreshableMetadataResolver) { -              final DateTime lastRefresh = ((RefreshableMetadataResolver) resolver).getLastRefresh(); -              if (ret == null || ret.isBefore(lastRefresh)) { -                  ret = lastRefresh; -              } -          } +  @Nullable +  public final DateTime getLastRefresh() { +    DateTime ret = null; +    for (final MetadataResolver resolver : internalResolvers) { +      if (resolver instanceof RefreshableMetadataResolver) { +        final DateTime lastRefresh = ((RefreshableMetadataResolver) resolver).getLastRefresh(); +        if (ret == null || ret.isBefore(lastRefresh)) { +          ret = lastRefresh; +        }        } -       -      return ret; +    } + +    return ret;    } -   -   +    /**     * Get the URL to metadata for a specific entityID.     * @@ -354,103 +356,92 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec    protected abstract List<String> getAllMetadataUrlsFromConfiguration()        throws EaafConfigurationException; -    /**     * Get a Id for this metadata provider. -   *  +   *     * @return     */    @Nonnull    protected abstract String getMetadataProviderId(); -   +    protected final MetadataResolver getMetadataResolver() {      log.warn("{} does NOT support 'getMetadataResolver'", AbstractChainingMetadataProvider.class.getName());      return null; -     +    } -   +    private Map<String, MetadataResolver> getAllActuallyLoadedResolvers() {      final Map<String, MetadataResolver> loadedproviders =          new HashMap<>();      // make a Map of all actually loaded HTTPMetadataProvider      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); +      loadedproviders.put(((IdentifiedComponent) resolver).getId(), resolver); -      }      }      return loadedproviders;    }    private void addAndRemoveMetadataProvider() throws EaafConfigurationException { -      log.info("EAAF chaining metadata resolver starting internal managment task .... "); +    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, MetadataResolver> providersinuse = new HashMap<>(); + +    // get all actually loaded metadata providers +    final Map<String, MetadataResolver> loadedproviders = getAllActuallyLoadedResolvers(); + +    /* +     * TODO: maybe add metadata provider destroy after timeout. But could be a +     * problem if one Metadataprovider load an EntitiesDescriptor with more the +     * multiple EntityDescriptors. If one of this EntityDesciptors are expired the +     * full EntitiesDescriptor is removed. +     * +     * Timeout requires a better solution in this case! +     */ + +    // load all SAML2 SPs form configuration and +    // compare actually loaded Providers with configured SAML2 SPs +    final List<String> allMetadataUrls = getAllMetadataUrlsFromConfiguration(); + +    final Iterator<String> metadataUrlInterator = allMetadataUrls.iterator(); +    while (metadataUrlInterator.hasNext()) { +      final String metadataurl = metadataUrlInterator.next(); +      try { +        if (StringUtils.isNotEmpty(metadataurl) +            && loadedproviders.containsKey(metadataurl)) { +          // SAML2 SP is actually loaded, to nothing +          providersinuse.put(metadataurl, loadedproviders.get(metadataurl)); +          loadedproviders.remove(metadataurl); + +        } +      } catch (final Throwable e) { +        log.error("Failed to add Metadata (unhandled reason: " + e.getMessage(), e); + +      } +    } + +    // remove all actually loaded MetadataProviders with are not in ConfigurationDB +    // any more +    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         * (UnsupportedOperationException) The ChainingMetadataProvider use internal a         * unmodifiableList to hold all registrated MetadataProviders.         */ -      final Map<String, MetadataResolver> providersinuse = new HashMap<>(); +      // chainProvider.removeMetadataProvider(provider); -      // get all actually loaded metadata providers -      final Map<String, MetadataResolver> loadedproviders = getAllActuallyLoadedResolvers(); - -      /* -       * TODO: maybe add metadata provider destroy after timeout. But could be a -       * problem if one Metadataprovider load an EntitiesDescriptor with more the -       * multiple EntityDescriptors. If one of this EntityDesciptors are expired the -       * full EntitiesDescriptor is removed. -       * -       * Timeout requires a better solution in this case! -       */ - -      // load all SAML2 SPs form configuration and -      // compare actually loaded Providers with configured SAML2 SPs -      final List<String> allMetadataUrls = getAllMetadataUrlsFromConfiguration(); - -        final Iterator<String> metadataUrlInterator = allMetadataUrls.iterator(); -        while (metadataUrlInterator.hasNext()) { -          final String metadataurl = metadataUrlInterator.next(); -          try { -            if (StringUtils.isNotEmpty(metadataurl) -                && loadedproviders.containsKey(metadataurl)) { -              // SAML2 SP is actually loaded, to nothing -              providersinuse.put(metadataurl, loadedproviders.get(metadataurl)); -              loadedproviders.remove(metadataurl); - -            } -          } catch (final Throwable e) { -            log.error("Failed to add Metadata (unhandled reason: " + e.getMessage(), e); - -          } -        } - - -      // remove all actually loaded MetadataProviders with are not in ConfigurationDB -      // any more -      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 -           * (UnsupportedOperationException) The ChainingMetadataProvider use internal a -           * unmodifiableList to hold all registrated MetadataProviders. -           */ -          // chainProvider.removeMetadataProvider(provider); - - -      } +    }    } @@ -474,39 +465,34 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec      }    } -   -      @Override    public DateTime getLastSuccessfulRefresh() {      return this.lastRefeshTimestamp; -     -  } +  }    @Override    public Boolean wasLastRefreshSuccess() {      return this.lastRefeshSuccessful; -     -  } - - -  /** {@inheritDoc} */ -  @Override public boolean isRequireValidMetadata() { -      log.warn("Attempt to access unsupported requireValidMetadata property on ChainingMetadataResolver"); -      return false;    } -  /** {@inheritDoc} */ -  @Override public void setRequireValidMetadata(final boolean requireValidMetadata) { -      throw new UnsupportedOperationException("Setting requireValidMetadata is not supported on chaining resolver"); +  @Override +  public boolean isRequireValidMetadata() { +    log.warn("Attempt to access unsupported requireValidMetadata property on ChainingMetadataResolver"); +    return false;    } +  @Override +  public void setRequireValidMetadata(final boolean requireValidMetadata) { +    throw new UnsupportedOperationException( +        "Setting requireValidMetadata is not supported on chaining resolver"); +  }    @Override    public String getId() {      return getMetadataProviderId(); -     +    } -   +  } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverAdapter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverAdapter.java index bd2b79cb..d2b861dc 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverAdapter.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverAdapter.java @@ -1,18 +1,22 @@  package at.gv.egiz.eaaf.modules.pvp2.impl.metadata; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider; +  import org.joda.time.DateTime;  import org.opensaml.core.criterion.EntityIdCriterion;  import org.opensaml.saml.metadata.resolver.ExtendedRefreshableMetadataResolver;  import org.opensaml.saml.metadata.resolver.filter.MetadataFilter;  import org.opensaml.saml.saml2.metadata.EntityDescriptor; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import lombok.extern.slf4j.Slf4j;  import net.shibboleth.utilities.java.support.resolver.CriteriaSet;  import net.shibboleth.utilities.java.support.resolver.ResolverException; -public class PvpMetadataResolverAdapter implements IPvp2MetadataProvider { -   -  private ExtendedRefreshableMetadataResolver internalProvider; +@Slf4j +public class PvpMetadataResolverAdapter implements IPvp2MetadataProvider, IRefreshableMetadataProvider { + +  private final ExtendedRefreshableMetadataResolver internalProvider;    public PvpMetadataResolverAdapter(ExtendedRefreshableMetadataResolver provider) {      this.internalProvider = provider; @@ -27,7 +31,7 @@ public class PvpMetadataResolverAdapter implements IPvp2MetadataProvider {    @Override    public DateTime getLastRefresh() {      return internalProvider.getLastRefresh(); -     +    }    @Override @@ -38,7 +42,7 @@ public class PvpMetadataResolverAdapter implements IPvp2MetadataProvider {    @Override    public boolean isRequireValidMetadata() {      return internalProvider.isRequireValidMetadata(); -     +    }    @Override @@ -50,12 +54,12 @@ public class PvpMetadataResolverAdapter implements IPvp2MetadataProvider {    @Override    public MetadataFilter getMetadataFilter() {      return internalProvider.getMetadataFilter(); -     +    }    @Override    public void setMetadataFilter(MetadataFilter newFilter) { -   internalProvider.setMetadataFilter(newFilter); +    internalProvider.setMetadataFilter(newFilter);    } @@ -67,7 +71,7 @@ public class PvpMetadataResolverAdapter implements IPvp2MetadataProvider {    @Override    public EntityDescriptor resolveSingle(CriteriaSet criteria) throws ResolverException {      return internalProvider.resolveSingle(criteria); -     +    }    @Override @@ -80,7 +84,7 @@ public class PvpMetadataResolverAdapter implements IPvp2MetadataProvider {      final CriteriaSet criteria = new CriteriaSet();      criteria.add(new EntityIdCriterion(entityId));      return internalProvider.resolveSingle(criteria); -     +    }    @Override @@ -93,4 +97,19 @@ public class PvpMetadataResolverAdapter implements IPvp2MetadataProvider {      return internalProvider.wasLastRefreshSuccess();    } +  @Override +  public boolean refreshMetadataProvider(String entityID) { +    try { +      log.trace("Refeshing metadata-provider: {} ... ", getId()); +      internalProvider.refresh(); +      return true; + +    } catch (final ResolverException e) { +      log.warn("Refreshing of metadata-provider: {} failed. Reason: {}", +          getId(), e.getMessage()); +      return false; + +    } +  } +  } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverFactory.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverFactory.java index f548bc7b..0b505e56 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverFactory.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverFactory.java @@ -8,23 +8,31 @@ import javax.annotation.Nullable;  import javax.annotation.PostConstruct;  import javax.net.ssl.SSLHandshakeException; +import at.gv.egiz.components.spring.api.IDestroyableObject; +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.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SignatureValidationException; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.OpenSaml3ResourceAdapter; +  import org.apache.http.client.HttpClient;  import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;  import org.opensaml.saml.metadata.resolver.ExtendedRefreshableMetadataResolver;  import org.opensaml.saml.metadata.resolver.filter.MetadataFilter; +import org.opensaml.saml.metadata.resolver.impl.AbstractReloadingMetadataResolver;  import org.opensaml.saml.metadata.resolver.impl.HTTPMetadataResolver;  import org.opensaml.saml.metadata.resolver.impl.ResourceBackedMetadataResolver;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.core.io.ResourceLoader; -import at.gv.egiz.components.spring.api.IDestroyableObject; -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.api.metadata.IPvp2MetadataProvider; -import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException; -import at.gv.egiz.eaaf.modules.pvp2.exception.SignatureValidationException; -import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.OpenSaml3ResourceAdapter; +import com.google.common.base.Predicates; +import com.google.common.base.Throwables; +import com.google.common.collect.FluentIterable;  import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; +import net.shibboleth.utilities.java.support.resolver.ResolverException;  import net.shibboleth.utilities.java.support.resource.Resource;  import net.shibboleth.utilities.java.support.xml.ParserPool; @@ -34,13 +42,18 @@ public class PvpMetadataResolverFactory implements IDestroyableObject {    private static final String URI_PREFIX_HTTP = "http:";    private static final String URI_PREFIX_HTTPS = "https:"; +  private static final String NOT_SUCCESS = "Maybe metadata was expired"; +    private Timer timer = null; -   -  @Autowired private IConfiguration authConfig; -  @Autowired private ResourceLoader resourceLoader; -   + +  @Autowired +  private IConfiguration authConfig; +  @Autowired +  private ResourceLoader resourceLoader; +    /** -   * Create a single SAML2 metadata provider by using the default OpenSAML3 parser-pool. +   * Create a single SAML2 metadata provider by using the default OpenSAML3 +   * parser-pool.     *     * @param metadataLocation where the metadata should be loaded, but never null.     *                         If the location starts with http(s):, than a http @@ -54,17 +67,18 @@ public class PvpMetadataResolverFactory implements IDestroyableObject {     *     * @return SAML2 Metadata Provider, or null if the metadata provider can not     *         initialized +   * @throws Pvp2MetadataException In case of an initialization error     */ -  @Nullable  +  @Nullable    public IPvp2MetadataProvider createMetadataProvider(@Nonnull final String metadataLocation,        @Nullable final MetadataFilter filter, @Nonnull final String idForLogging, -      @Nullable final HttpClient httpClient) { -    return createMetadataProvider(metadataLocation, filter, idForLogging,  -        XMLObjectProviderRegistrySupport.getParserPool(),  -        httpClient);   -     +      @Nullable final HttpClient httpClient) throws Pvp2MetadataException { +    return createMetadataProvider(metadataLocation, filter, idForLogging, +        XMLObjectProviderRegistrySupport.getParserPool(), +        httpClient); +    } -   +    /**     * Create a single SAML2 metadata provider.     * @@ -80,57 +94,74 @@ public class PvpMetadataResolverFactory implements IDestroyableObject {     *     * @return SAML2 Metadata Provider, or null if the metadata provider can not     *         initialized +   * @throws Pvp2MetadataException In case of an initialization error     */ -  @Nullable  +  @Nullable    public IPvp2MetadataProvider createMetadataProvider(@Nonnull final String metadataLocation,        @Nullable final MetadataFilter filter, @Nonnull final String idForLogging, -      @Nullable final ParserPool pool, @Nullable final HttpClient httpClient) { -     +      @Nullable final ParserPool pool, @Nullable final HttpClient httpClient) throws Pvp2MetadataException { +      ExtendedRefreshableMetadataResolver internalProvider = null; -     -    if (metadataLocation.startsWith(URI_PREFIX_HTTP) -        || metadataLocation.startsWith(URI_PREFIX_HTTPS)) { -      if (httpClient != null) { -        internalProvider = createNewHttpMetaDataProvider(metadataLocation, filter, idForLogging, timer, pool, -            httpClient); + +    try { +      if (metadataLocation.startsWith(URI_PREFIX_HTTP) +          || metadataLocation.startsWith(URI_PREFIX_HTTPS)) { +        internalProvider = createNewHttpMetaDataProvider(metadataLocation, filter, +            idForLogging, timer, pool, httpClient); +        } else { -        log.warn("Can not load http(s) based SAML2 metadata without a HTTP client"); -         +        final String absoluteMetadataLocation = +            FileUtils.makeAbsoluteUrl(metadataLocation, authConfig.getConfigurationRootDirectory()); +        final org.springframework.core.io.Resource resource = +            resourceLoader.getResource(absoluteMetadataLocation); + +        if (resource.exists()) { +          internalProvider = createNewFileSystemMetaDataProvider( +              new OpenSaml3ResourceAdapter(resource), +              filter, idForLogging, timer, +              pool); + +        } else { +          log.warn( +              "SAML2 metadata file: {} not found or not exist", absoluteMetadataLocation); +          throw new Pvp2MetadataException("internal.pvp.05", +              new Object[] { absoluteMetadataLocation, "File NOT found or exist." }); + +        }        } -    } else { -      String absoluteMetadataLocation; -      try { -        absoluteMetadataLocation = -            FileUtils.makeAbsoluteUrl(metadataLocation, authConfig.getConfigurationRootDirectory()); +    } catch (final ComponentInitializationException e) { +      log.warn("Failed to load Metadata file for {} [ {} ]", +          idForLogging, e.getMessage()); +      checkResolverInitializationError(e, metadataLocation); -          org.springframework.core.io.Resource resource = resourceLoader.getResource(absoluteMetadataLocation); -          if (resource.exists()) { -             internalProvider = createNewFileSystemMetaDataProvider( -                new OpenSaml3ResourceAdapter(resource),  -                filter, idForLogging, timer, -                pool); -          } else { -            log.warn( -                "SAML2 metadata file: " + absoluteMetadataLocation + " not found or not exist"); -             -          } +    } catch (final Exception e) { +      throw new Pvp2MetadataException("internal.pvp.09", new Object[] { metadataLocation, e.getMessage() }); +    } -      } catch (final IOException e) { -        log.warn("SAML2 metadata URL is invalid: " + metadataLocation, e); +    if (!internalProvider.wasLastRefreshSuccess()) { +      log.info("Metadata loading from source: {} failed. {}", metadataLocation, NOT_SUCCESS); +      throw new Pvp2MetadataException("internal.pvp.09", new Object[] { metadataLocation, NOT_SUCCESS }); -      }      } -    if (internalProvider != null) { -      return new PvpMetadataResolverAdapter(internalProvider); -       -    } else { -      log.warn("SAML2 metadata has an unsupported metadata location prefix: " + metadataLocation); -      return null; -       +    return new PvpMetadataResolverAdapter(internalProvider); + +  } + +  @Override +  public void fullyDestroy() { +    if (timer != null) { +      log.info("Stopping timer-thread for PVP metadata resolver ...  "); +      timer.cancel();      } +  } + +  @PostConstruct +  private void initialize() { +    log.info("Initializing timer-thread for PVP metadata resolver ... "); +    timer = new Timer("PVP metadata-resolver refresh");    } @@ -142,55 +173,26 @@ public class PvpMetadataResolverFactory implements IDestroyableObject {     * @param idForLogging Id, which is used for Logging     * @param timer        {@link Timer} which is used to schedule metadata refresh     *                     operations -   * @param pool +   * @param pool         SAML2 parser pool that should be used     *     * @return SAML2 Metadata Provider -   * @throws IOException  +   * @throws IOException                      In case of a metadata resource error +   * @throws ComponentInitializationException In case of a metadata resolver +   *                                          initialization error     */    private ExtendedRefreshableMetadataResolver createNewFileSystemMetaDataProvider(final Resource metadataFile,        final MetadataFilter filter, final String idForLogging, final Timer timer, -      final ParserPool pool) throws IOException { +      final ParserPool pool) throws IOException, ComponentInitializationException {      ResourceBackedMetadataResolver fileSystemResolver = null; -    try { -      //fileSystemResolver = new FilesystemMetadataResolver(timer, metadataFile); -       -      fileSystemResolver = new ResourceBackedMetadataResolver(timer, metadataFile); -       -      if (pool != null) { -        fileSystemResolver.setParserPool(pool); -         -      } else { -        fileSystemResolver.setParserPool( -            XMLObjectProviderRegistrySupport.getParserPool()); -         -      } -      fileSystemResolver.setRequireValidMetadata(true); -      fileSystemResolver.setMinRefreshDelay(1000 * 60 * 15); // 15 minutes -      fileSystemResolver.setMaxRefreshDelay(1000 * 60 * 60 * 24); // 24 hours - -      fileSystemResolver.setMetadataFilter(filter); -      fileSystemResolver.initialize(); -      fileSystemResolver.setId(metadataFile.getURI().toASCIIString()); - -      fileSystemResolver.setRequireValidMetadata(true); - -      return fileSystemResolver; - -    } catch (final Exception e) { -      log.warn("Failed to load Metadata file for " + idForLogging + "[ " + "File: " -          + metadataFile.getURI().toASCIIString() + " Msg: " + e.getMessage() + " ]", e); - -      log.warn("Can not initialize SAML2 metadata provider from filesystem: " -          + metadataFile.getURI().toASCIIString() + " Reason: " + e.getMessage(), e); +    fileSystemResolver = new ResourceBackedMetadataResolver(timer, metadataFile); +    injectMetadataResolverConfiguration(fileSystemResolver, filter, pool); +    fileSystemResolver.setId(metadataFile.getURI().toASCIIString()); +    fileSystemResolver.initialize(); -      if (fileSystemResolver != null) { -        fileSystemResolver.destroy(); +    log.trace("Set-up metadata-resolver with ID: {} as: {}", +        idForLogging, fileSystemResolver.getClass().getSimpleName()); -      } - -    } - -    return null; +    return fileSystemResolver;    } @@ -202,70 +204,75 @@ public class PvpMetadataResolverFactory implements IDestroyableObject {     * @param idForLogging Id, which is used for Logging     * @param timer        {@link Timer} which is used to schedule metadata refresh     *                     operations -   * @param pool -   * +   * @param pool         SAML2 parser pool that should be used     * @return SAML2 Metadata Provider +   * @throws ComponentInitializationException In case of a metadata resolver +   *                                          initialization error +   * @throws ResolverException                In case of an internal OpenSAML +   *                                          resolver error     */    private ExtendedRefreshableMetadataResolver createNewHttpMetaDataProvider(final String metadataUrl,        final MetadataFilter filter, final String idForLogging, final Timer timer, -      final ParserPool pool, final HttpClient httpClient) { +      final ParserPool pool, final HttpClient httpClient) throws ComponentInitializationException, +      ResolverException {      HTTPMetadataResolver httpMetadataResolver = null; -    try { -      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); +    httpMetadataResolver = new HTTPMetadataResolver(timer, httpClient, metadataUrl); +    injectMetadataResolverConfiguration(httpMetadataResolver, filter, pool); +    httpMetadataResolver.setId(metadataUrl); +    httpMetadataResolver.initialize(); -      httpMetadataResolver.setMetadataFilter(filter); -      httpMetadataResolver.setId(metadataUrl); -      httpMetadataResolver.initialize(); +    log.trace("Set-up metadata-resolver with ID: {} as: {}", +        idForLogging, httpMetadataResolver.getClass().getSimpleName()); -      httpMetadataResolver.setRequireValidMetadata(true); +    return httpMetadataResolver; -      return httpMetadataResolver; +  } -    } catch (final Throwable e) { -      if (e.getCause() != null && e.getCause().getCause() instanceof SSLHandshakeException) { -        log.warn("SSL-Server certificate for metadata " + metadataUrl + " not trusted.", e); +  private void injectMetadataResolverConfiguration(AbstractReloadingMetadataResolver resolver, +      final MetadataFilter filter, final ParserPool pool) { +    if (pool != null) { +      resolver.setParserPool(pool); -      } -      if (e.getCause() != null && e.getCause().getCause() instanceof SignatureValidationException) { -        log.warn("Signature verification for metadata" + metadataUrl + " FAILED.", e); +    } else { +      resolver.setParserPool( +          XMLObjectProviderRegistrySupport.getParserPool()); -      } -      if (e.getCause() != null && e.getCause().getCause() instanceof SchemaValidationException) { -        log.warn("Schema validation for metadata " + metadataUrl + " FAILED.", e); -      } +    } + +    resolver.setRequireValidMetadata(true); +    resolver.setMinRefreshDelay(1000 * 60 * 15); // 15 minutes +    resolver.setMaxRefreshDelay(1000 * 60 * 60 * 24); // 24 hours +    resolver.setMetadataFilter(filter); + +  } -      log.warn("Failed to load Metadata file for " + idForLogging + "[ " + e.getMessage() + " ]", +  private void checkResolverInitializationError(ComponentInitializationException e, String metadataLocation) +      throws Pvp2MetadataException { +    if (FluentIterable.from(Throwables.getCausalChain(e)).filter( +        Predicates.instanceOf(SSLHandshakeException.class)).first().isPresent()) { +      log.info("SSL-Server certificate for metadata: {} not trusted.", metadataLocation, null, e); +      throw new Pvp2MetadataException("internal.pvp.06", new Object[] { metadataLocation, e.getMessage() },            e); -      if (httpMetadataResolver != null) { -        log.debug("Destroy failed Metadata provider"); -        httpMetadataResolver.destroy(); +    } else if (FluentIterable.from(Throwables.getCausalChain(e)).filter( +        Predicates.instanceOf(SignatureValidationException.class)).first().isPresent()) { +      log.info("Signature verification for metadata: {} FAILED.", metadataLocation, null, e); +      throw new Pvp2MetadataException("internal.pvp.07", new Object[] { metadataLocation, e.getMessage() }, +          e); -      } +    } else if (FluentIterable.from(Throwables.getCausalChain(e)).filter( +        Predicates.instanceOf(SchemaValidationException.class)).first().isPresent()) { +      log.info("Schema validation for metadata: {} FAILED.", metadataLocation, null, e); +      throw new Pvp2MetadataException("internal.pvp.08", new Object[] { metadataLocation, e.getMessage() }, +          e); + +    } else { +      log.info("Generic initialization error for metadata: {}", metadataLocation, null, e); +      throw new Pvp2MetadataException("internal.pvp.09", new Object[] { metadataLocation, e.getMessage() }, +          e);      } -    return null;    } -  @Override -  public void fullyDestroy() { -    if (timer != null) { -      log.info("Stopping timer-thread for PVP metadata resolver ...  "); -      timer.cancel(); -    }     -  } -   -  @PostConstruct -  private void initialize() { -    log.info("Initializing timer-thread for PVP metadata resolver ... "); -    timer = new Timer("PVP metadata-resolver refresh"); -     -  } -    } 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 index d23affba..fdd44b9a 100644 --- 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 @@ -2,18 +2,18 @@ package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml;  import java.io.ByteArrayInputStream;  import java.io.InputStream; +import java.io.UnsupportedEncodingException; -import javax.annotation.Nonnull; -import javax.annotation.Nullable;  import javax.servlet.http.HttpServletRequest; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SamlHttpUtils; +  import org.opensaml.core.xml.XMLObject;  import org.opensaml.messaging.decoder.MessageDecodingException;  import org.opensaml.saml.saml2.binding.decoding.impl.HTTPPostDecoder;  import com.google.common.base.Strings; - -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;  import lombok.extern.slf4j.Slf4j;  import net.shibboleth.utilities.java.support.codec.Base64Support; @@ -27,14 +27,22 @@ import net.shibboleth.utilities.java.support.codec.Base64Support;  @Slf4j  public class EaafHttpPostDecoder extends HTTPPostDecoder { +  private static final String SAML_REQ_PARAM_NAME = "SAMLRequest"; +  private static final String SAML_RESP_PARAM_NAME = "SAMLResponse"; + +  public EaafHttpPostDecoder(HttpServletRequest req) { +    setHttpServletRequest(req); +  } +    @Override    protected InputStream getBase64DecodedMessage(final HttpServletRequest request)        throws MessageDecodingException {      log.debug("Getting Base64 encoded message from request"); -    String encodedMessage = getLastParameterFromRequest(request, "SAMLRequest"); +    String encodedMessage = SamlHttpUtils.getLastParameterFromRequest(request, SAML_REQ_PARAM_NAME);      if (Strings.isNullOrEmpty(encodedMessage)) { -      encodedMessage = getLastParameterFromRequest(request, "SAMLResponse"); +      encodedMessage = SamlHttpUtils.getLastParameterFromRequest(request, SAML_RESP_PARAM_NAME); +      }      if (Strings.isNullOrEmpty(encodedMessage)) { @@ -43,14 +51,17 @@ public class EaafHttpPostDecoder extends HTTPPostDecoder {        throw new MessageDecodingException("No SAML message present in request");      } -    log.trace("Base64 decoding SAML message:\n{}", encodedMessage); +    log.trace("Base64 decoding SAML message: {}", 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"); + +    try { +      log.trace("Decoded SAML message: {}", new String(decodedBytes, "UTF-8")); + +    } catch (final UnsupportedEncodingException e) { +      log.warn("Logging of incomming message failed", e); +      } -    log.trace("Decoded SAML message:\n{}", new String(decodedBytes));      return new ByteArrayInputStream(decodedBytes);    } @@ -61,31 +72,8 @@ public class EaafHttpPostDecoder extends HTTPPostDecoder {     */    @Override    protected XMLObject unmarshallMessage(final InputStream messageStream) throws MessageDecodingException { -      return Saml2Utils.unmarshallMessage(messageStream); -       -  } - -  /** -   * 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; +    return Saml2Utils.unmarshallMessage(messageStream);    } +  } 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 index 16d73296..c5174f02 100644 --- 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 @@ -4,6 +4,9 @@ import java.io.InputStream;  import javax.servlet.http.HttpServletRequest; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SamlHttpUtils; +  import org.opensaml.core.xml.XMLObject;  import org.opensaml.messaging.context.MessageContext;  import org.opensaml.messaging.decoder.MessageDecodingException; @@ -13,10 +16,7 @@ import org.opensaml.saml.common.xml.SAMLConstants;  import org.opensaml.saml.saml2.binding.decoding.impl.HTTPRedirectDeflateDecoder;  import com.google.common.base.Strings; - -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;  import lombok.extern.slf4j.Slf4j; -import net.shibboleth.utilities.java.support.net.URISupport;  import net.shibboleth.utilities.java.support.primitive.StringSupport;  /** @@ -29,6 +29,14 @@ import net.shibboleth.utilities.java.support.primitive.StringSupport;  @Slf4j  public class EaafHttpRedirectDeflateDecoder extends HTTPRedirectDeflateDecoder { +  private static final String SAML_REQ_PARAM_NAME = "SAMLRequest"; +  private static final String SAML_RESP_PARAM_NAME = "SAMLResponse"; + +  public EaafHttpRedirectDeflateDecoder(HttpServletRequest req) { +    setHttpServletRequest(req); + +  } +    @Override    protected void doDecode() throws MessageDecodingException {      final MessageContext<SAMLObject> messageContext = new MessageContext<>(); @@ -52,16 +60,19 @@ public class EaafHttpRedirectDeflateDecoder extends HTTPRedirectDeflateDecoder {      // 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")); +    final String samlReq = SamlHttpUtils.getLastParameterFromRequest(request, SAML_REQ_PARAM_NAME); +    final String samlResp = SamlHttpUtils.getLastParameterFromRequest(request, SAML_RESP_PARAM_NAME); +    if (!Strings.isNullOrEmpty(samlReq)) { +      samlMessageIns = decodeMessage(samlReq); + +    } else if (!Strings.isNullOrEmpty(samlResp)) { +      samlMessageIns = decodeMessage(samlResp); +      } 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"); @@ -69,9 +80,9 @@ public class EaafHttpRedirectDeflateDecoder extends HTTPRedirectDeflateDecoder {      populateBindingContext(messageContext);      setMessageContext(messageContext); -     +    } -   +    /**     * EAAF specific unmarshaller perform XML schema validation before unmarshalling     * the SAML message. @@ -79,8 +90,8 @@ public class EaafHttpRedirectDeflateDecoder extends HTTPRedirectDeflateDecoder {     */    @Override    protected XMLObject unmarshallMessage(final InputStream messageStream) throws MessageDecodingException { -      return Saml2Utils.unmarshallMessage(messageStream); -       +    return Saml2Utils.unmarshallMessage(messageStream); +    }  } 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 7c433c1c..6d81700a 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 @@ -50,21 +50,24 @@ public class EaafKeyStoreX509CredentialAdapter extends KeyStoreX509CredentialAda    /**     * Get an OpenSAML2 keystore.     * -   * @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 +   * @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(@Nonnull final KeyStore store, @Nonnull final String alias, -      @Nullable final char[] password, @Nonnull String keyStoreFriendlyName) throws CredentialsNotAvailableException { +      @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}); +          new Object[] { keyStoreFriendlyName, alias });      } @@ -74,7 +77,8 @@ public class EaafKeyStoreX509CredentialAdapter extends KeyStoreX509CredentialAda            PvpConstants.DEFAULT_SIGNING_METHODE_EC));      } catch (final SamlSigningException e) { -      throw new CredentialsNotAvailableException("internal.pvp.01", new Object[] {keyStoreFriendlyName, alias}, e); +      throw new CredentialsNotAvailableException("internal.pvp.01", new Object[] { keyStoreFriendlyName, +          alias }, e);      } 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 3650e617..fa77b73c 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,7 +19,6 @@  package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml; -  import java.io.BufferedReader;  import java.io.IOException;  import java.io.InputStream; diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/OpenSaml3ResourceAdapter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/OpenSaml3ResourceAdapter.java index 2e45aea2..f474267f 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/OpenSaml3ResourceAdapter.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/OpenSaml3ResourceAdapter.java @@ -9,22 +9,23 @@ import java.net.URL;  import net.shibboleth.utilities.java.support.resource.Resource;  /** - * Adapter that connects a Spring {@link org.springframework.core.io.Resource} to a {@link Resource}. - *  + * Adapter that connects a Spring {@link org.springframework.core.io.Resource} + * to a {@link Resource}. + *   * @author tlenz   *   */  public class OpenSaml3ResourceAdapter implements Resource { -  private org.springframework.core.io.Resource internalResource; +  private final org.springframework.core.io.Resource internalResource;    public OpenSaml3ResourceAdapter(org.springframework.core.io.Resource resource) {      this.internalResource = resource;    } -   +    @Override    public boolean exists() { -    return  internalResource.exists(); +    return internalResource.exists();    }    @Override 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 bd450518..38735fb8 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 @@ -23,8 +23,8 @@ 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 lombok.extern.slf4j.Slf4j;  /**   * Create deflate encoded SAML2 redirect-binding informations. @@ -32,9 +32,9 @@ import org.slf4j.LoggerFactory;   * @author tlenz   *   */ -public class StringRedirectDeflateEncoder extends HTTPRedirectDeflateEncoder { -  private static final Logger log = LoggerFactory.getLogger(StringRedirectDeflateEncoder.class); +@Slf4j +public class StringRedirectDeflateEncoder extends HTTPRedirectDeflateEncoder {    private String redirectUrl = null;    @Override @@ -50,6 +50,8 @@ public class StringRedirectDeflateEncoder extends HTTPRedirectDeflateEncoder {      redirectUrl = buildRedirectURL(messageContext, endpointUrl, encodedMessage); +    log.trace("SAML2 redirect-binding URL was generated as: {}", redirectUrl); +    }    /** 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 index 42d4d736..5c6d861d 100644 --- 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 @@ -60,10 +60,12 @@ public class EaafOpenSaml3xInitializer extends InitializationService {    /**     * EAAF specific OpenSAML3.x initialization.     * -   * @throws InitializationException In case of an error -   * @throws ComponentInitializationException +   * @throws InitializationException          In case of an error +   * @throws ComponentInitializationException In case of an OpenSAML3 +   *                                          initialization error     */ -  public static synchronized void eaafInitialize() throws InitializationException, ComponentInitializationException { +  public static synchronized void eaafInitialize() throws InitializationException, +      ComponentInitializationException {      log.debug("Initializing OpenSAML 3.x ... ");      initialize(); diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/QaaLevelVerifier.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/QaaLevelVerifier.java index 31ffd5a7..ca6f29e4 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/QaaLevelVerifier.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/QaaLevelVerifier.java @@ -21,13 +21,13 @@ package at.gv.egiz.eaaf.modules.pvp2.impl.utils;  import java.util.List; +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.modules.pvp2.exception.QaaNotAllowedException; +  import org.apache.commons.lang3.StringUtils;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory; -import at.gv.egiz.eaaf.core.api.data.EaafConstants; -import at.gv.egiz.eaaf.modules.pvp2.exception.QaaNotAllowedException; -  /**   * EAAF LoA Level verifier checks if requested LoA matchs to LoA of   * authentication. 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 763c07f6..dc7e9338 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 @@ -37,6 +37,14 @@ import javax.xml.transform.dom.DOMSource;  import javax.xml.validation.Schema;  import javax.xml.validation.Validator; +import at.gv.egiz.eaaf.core.impl.utils.DomUtils; +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 at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException; +  import org.apache.commons.collections4.CollectionUtils;  import org.apache.commons.lang3.StringUtils;  import org.opensaml.core.xml.XMLObject; @@ -82,13 +90,6 @@ import org.w3c.dom.Document;  import org.w3c.dom.Element;  import org.xml.sax.SAXException; -import at.gv.egiz.eaaf.core.impl.utils.DomUtils; -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 at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException;  import net.shibboleth.utilities.java.support.xml.QNameSupport;  import net.shibboleth.utilities.java.support.xml.SerializeSupport; @@ -114,13 +115,14 @@ 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> +   * 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 <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 @@ -157,18 +159,20 @@ public class Saml2Utils {      } catch (final SignatureException | MarshallingException | SecurityException e) {        throw new SamlSigningException("internal.pvp.96", -          new Object[] {signingCredential.getEntityId(), e.getMessage()}, e); +          new Object[] { signingCredential.getEntityId(), e.getMessage() }, e);      }    }    /** -   * SAML2 message unmarshaller that performs schema validation before unmarshall the message. -   *  +   * SAML2 message unmarshaller that performs schema validation before unmarshall +   * the message. +   *     * @param messageStream SAML2 message that shoulld be unmarshalled     * @return OpenSAML XML object -   * @throws MessageDecodingException In case of a schema-validation or unmarshalling error +   * @throws MessageDecodingException In case of a schema-validation or +   *                                  unmarshalling error     */    public static XMLObject unmarshallMessage(final InputStream messageStream) throws MessageDecodingException {      try { @@ -201,22 +205,24 @@ public class Saml2Utils {      } catch (ParserConfigurationException | SAXException e) {        log.warn("Message schema-validation failed."); -      throw new MessageDecodingException("Message schema-validation failed.",  +      throw new MessageDecodingException("Message schema-validation failed.",            new SchemaValidationException("internal.pvp.03", new Object[] { e.getMessage() }, e));      } catch (final IOException e) {        log.error("Error read message from input stream", e);        throw new MessageDecodingException("Error read message from input stream", 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 +   * @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     */ @@ -233,7 +239,7 @@ public class Saml2Utils {        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()}); +          new Object[] { credentials.getEntityId(), privatekey.getClass().getName() });      }    } @@ -263,14 +269,16 @@ public class Saml2Utils {    }    /** -   * Get a {@link KeyInfoGenerator} that injects key information into XML signature. +   * 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 +   * @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 +    // OpenSAML3 only support RSA and DSA for direct key injection      KeyInfoGeneratorFactory keyInfoGenFac = null;      if (injectCertificate || credential.getPublicKey() instanceof ECPublicKey) {        final SignatureSigningConfiguration secConfiguration = SecurityConfigurationSupport @@ -280,7 +288,7 @@ public class Saml2Utils {        keyInfoGenFac = keyInfoGenManager.getFactory(credential);      } else { -      keyInfoGenFac = createKeyInfoWithoutCertificate(credential); +      keyInfoGenFac = createKeyInfoWithoutCertificate();      } @@ -288,7 +296,6 @@ public class Saml2Utils {    } -    /**     * Create a SAML2 object.     * @@ -462,19 +469,20 @@ public class Saml2Utils {          .buildObject(Signature.DEFAULT_ELEMENT_NAME);      signature.setSigningCredential(signingCredential);      signature.setSignatureAlgorithm(usedSigAlg); -    final KeyInfo keyInfo = getKeyInfoGenerator(signingCredential, injectCertificate).generate(signingCredential); +    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) { +  private static KeyInfoGeneratorFactory createKeyInfoWithoutCertificate() {      final KeyInfoGeneratorFactory keyInfoGenFac = new BasicKeyInfoGeneratorFactory(); -    ((BasicKeyInfoGeneratorFactory)keyInfoGenFac).setEmitPublicKeyValue(true); -    ((BasicKeyInfoGeneratorFactory)keyInfoGenFac).setEmitEntityIDAsKeyName(true); -    ((BasicKeyInfoGeneratorFactory)keyInfoGenFac).setEmitKeyNames(true); -    ((BasicKeyInfoGeneratorFactory)keyInfoGenFac).setEmitPublicDEREncodedKeyValue(true); +    ((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/utils/SamlHttpUtils.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/SamlHttpUtils.java new file mode 100644 index 00000000..2e02bf22 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/SamlHttpUtils.java @@ -0,0 +1,33 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.utils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.servlet.http.HttpServletRequest; + +public class SamlHttpUtils { + +  /** +   * 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 +  public static 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/validation/TrustEngineFactory.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/TrustEngineFactory.java index 1591198c..f0758706 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 @@ -23,9 +23,11 @@ import java.util.ArrayList;  import java.util.List;  import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2InternalErrorException;  import org.opensaml.saml.metadata.resolver.impl.PredicateRoleDescriptorResolver;  import org.opensaml.saml.security.impl.MetadataCredentialResolver; +import org.opensaml.xmlsec.keyinfo.KeyInfoCredentialResolver;  import org.opensaml.xmlsec.keyinfo.impl.BasicProviderKeyInfoCredentialResolver;  import org.opensaml.xmlsec.keyinfo.impl.KeyInfoProvider;  import org.opensaml.xmlsec.keyinfo.impl.provider.DSAKeyValueProvider; @@ -34,29 +36,50 @@ import org.opensaml.xmlsec.keyinfo.impl.provider.RSAKeyValueProvider;  import org.opensaml.xmlsec.signature.support.SignatureTrustEngine;  import org.opensaml.xmlsec.signature.support.impl.ExplicitKeySignatureTrustEngine; +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; + +@Slf4j  public class TrustEngineFactory {    /**     * Get OpenSAML2 TrustEngine.     *     * @param mdResolver Metadata provider -   * @return +   * @return TrustEngine for SAML2 message validation +   * @throws Pvp2InternalErrorException In case of a TrustEngine initialization +   *                                    error     */    public static SignatureTrustEngine getSignatureKnownKeysTrustEngine( -      final IPvp2MetadataProvider mdResolver) { -    final MetadataCredentialResolver resolver = new MetadataCredentialResolver(); -    resolver.setRoleDescriptorResolver(new PredicateRoleDescriptorResolver(mdResolver)); +      final IPvp2MetadataProvider mdResolver) throws Pvp2InternalErrorException { +    try { +      final List<KeyInfoProvider> keyInfoProvider = new ArrayList<>(); +      keyInfoProvider.add(new DSAKeyValueProvider()); +      keyInfoProvider.add(new RSAKeyValueProvider()); +      keyInfoProvider.add(new InlineX509DataProvider()); +      final KeyInfoCredentialResolver keyInfoCredentialResolver = new BasicProviderKeyInfoCredentialResolver( +          keyInfoProvider); + +      final PredicateRoleDescriptorResolver roleDescriptorResolver = new PredicateRoleDescriptorResolver( +          mdResolver); +      roleDescriptorResolver.setRequireValidMetadata(true); +      roleDescriptorResolver.initialize(); + +      final MetadataCredentialResolver resolver = new MetadataCredentialResolver(); +      resolver.setRoleDescriptorResolver(roleDescriptorResolver); +      resolver.setKeyInfoCredentialResolver(keyInfoCredentialResolver); +      resolver.initialize(); + +      final ExplicitKeySignatureTrustEngine engine = +          new ExplicitKeySignatureTrustEngine(resolver, keyInfoCredentialResolver); -    final List<KeyInfoProvider> keyInfoProvider = new ArrayList<>(); -    keyInfoProvider.add(new DSAKeyValueProvider()); -    keyInfoProvider.add(new RSAKeyValueProvider()); -    keyInfoProvider.add(new InlineX509DataProvider()); +      return engine; -    final ExplicitKeySignatureTrustEngine engine = -        new ExplicitKeySignatureTrustEngine(resolver, -            new BasicProviderKeyInfoCredentialResolver(keyInfoProvider)); +    } catch (final ComponentInitializationException e) { +      log.warn("Initialization of SignatureTrustEngine FAILED.", e); +      throw new Pvp2InternalErrorException(e); -    return engine; +    }    } 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 73a11c49..1994eba0 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 @@ -32,7 +32,6 @@ 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;  public class SchemaValidationFilter implements MetadataFilter {    private static final Logger log = LoggerFactory.getLogger(SchemaValidationFilter.class); @@ -58,8 +57,6 @@ public class SchemaValidationFilter implements MetadataFilter {    @Override    public XMLObject filter(final XMLObject arg0) throws FilterException { -    String errString = null; -      if (isActive) {        try {          final Schema test = schemaBuilder.getSAMLSchema(); @@ -68,15 +65,6 @@ public class SchemaValidationFilter implements MetadataFilter {          val.validate(source);          log.info("Metadata Schema validation check done OK"); -      } catch (final SAXException e) { -        if (log.isDebugEnabled() || log.isTraceEnabled()) { -          log.warn("Metadata Schema validation FAILED with exception:", e); -        } else { -          log.warn("Metadata Schema validation FAILED with message: " + e.getMessage()); -        } - -        errString = e.getMessage(); -        } catch (final Exception e) {          if (log.isDebugEnabled() || log.isTraceEnabled()) {            log.warn("Metadata Schema validation FAILED with exception:", e); @@ -84,13 +72,10 @@ public class SchemaValidationFilter implements MetadataFilter {            log.warn("Metadata Schema validation FAILED with message: " + e.getMessage());          } -        errString = e.getMessage(); - +        throw new FilterException(new SchemaValidationException("internal.pvp.03", +            new Object[] { e.getMessage() }, e));        } -      throw new FilterException(new SchemaValidationException("pvp2.26", -          new Object[] { "Metadata Schema validation FAILED with message: " + errString })); -      } else {        log.info("Metadata Schema validation check is DEACTIVATED!"); diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SimpleMetadataSignatureVerificationFilter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SimpleMetadataSignatureVerificationFilter.java new file mode 100644 index 00000000..ef09e5c4 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SimpleMetadataSignatureVerificationFilter.java @@ -0,0 +1,146 @@ +/* + * Copyright 2018 A-SIT Plus GmbH + * AT-specific eIDAS Connector has been developed in a cooperation between EGIZ, + * A-SIT Plus GmbH, 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 "License"); + * You may not use this work except in compliance with the License. + * You may obtain a copy of the License at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * 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.validation.metadata; + +import java.util.ArrayList; +import java.util.List; + +import javax.annotation.Nonnull; + +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.SamlMetadataSignatureException; + +import org.opensaml.saml.common.SignableSAMLObject; +import org.opensaml.saml.saml2.metadata.EntitiesDescriptor; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml.security.impl.SAMLSignatureProfileValidator; +import org.opensaml.security.x509.BasicX509Credential; +import org.opensaml.xmlsec.signature.support.SignatureException; +import org.opensaml.xmlsec.signature.support.SignatureValidator; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class SimpleMetadataSignatureVerificationFilter extends AbstractMetadataSignatureFilter { + +  private final String metadataUrl; +  private final List<BasicX509Credential> trustedCredential = new ArrayList<>(); + +  private static final String ERROR_07 = "internal.pvp.07"; +  private static final String ERROR_12 = "internal.pvp.12"; +  private static final String ERROR_MSG_ENTITIESDESC = "EntitiesDescritors are NOT supported"; +  private static final String ERROR_MSG_SIGNOTVALID = "Signature not valid or no trusted certificate found"; + +  /** +   * SAML2 metadata-signature verification-filter that uses a simple {@link List} +   * of trusted {@link BasicX509Credential} as truststore. <br> +   * <p> +   * This filter only validates {@link EntityDescriptor} elements.<br> +   * SAML2 metadata with {@link EntitiesDescriptor} <b>are not supported.</b> +   * </p> +   * +   * @param credentials Trust X509 certificates +   * @param metadataUrl Metadata URL for logging purposes +   */ +  public SimpleMetadataSignatureVerificationFilter(@Nonnull List<BasicX509Credential> credentials, +      @Nonnull String metadataUrl) { +    this.metadataUrl = metadataUrl; +    this.trustedCredential.addAll(credentials); + +  } + +  @Override +  protected void verify(EntityDescriptor desc) throws Pvp2MetadataException { +    try { +      internalVerify(desc); + +    } catch (final EaafException e) { +      log.info("Metadata verification FAILED for: {} Reason: {}", metadataUrl, e.getMessage()); +      throw new Pvp2MetadataException(ERROR_07, +          new Object[] { metadataUrl, e.getMessage() }, e); + +    } +  } + +  @Override +  protected void verify(EntitiesDescriptor desc) throws Pvp2MetadataException { +    throw new Pvp2MetadataException(ERROR_07, +        new Object[] { metadataUrl, ERROR_MSG_ENTITIESDESC }); + +  } + +  @Override +  protected void verify(EntityDescriptor entity, EntitiesDescriptor desc) throws Pvp2MetadataException { +    throw new Pvp2MetadataException(ERROR_07, +        new Object[] { metadataUrl, ERROR_MSG_ENTITIESDESC }); + +  } + +  private void internalVerify(SignableSAMLObject signedElement) +      throws EaafException { +    // check if signature exists +    if (signedElement.getSignature() == null) { +      throw new Pvp2MetadataException(ERROR_12, +          new Object[] { metadataUrl }); + +    } + +    // perform general signature validation +    try { +      final SAMLSignatureProfileValidator sigValidator = new SAMLSignatureProfileValidator(); +      sigValidator.validate(signedElement.getSignature()); + +    } catch (final SignatureException e) { +      log.error("Failed to validate Signature", e); +      throw new Pvp2MetadataException(ERROR_07, +          new Object[] { metadataUrl, e.getMessage() }, e); + +    } + +    // perform cryptographic signature verification +    boolean isTrusted = false; +    for (final BasicX509Credential cred : trustedCredential) { +      log.trace("Validating signature with credential: {} ... ", +          cred.getEntityCertificate().getSubjectDN()); +      try { +        SignatureValidator.validate(signedElement.getSignature(), cred); +        isTrusted = true; + +      } catch (final SignatureException e) { +        log.debug("Failed to verfiy Signature with cert: {} Reason: {}", +            cred.getEntityCertificate().getSubjectDN(), e.getMessage()); + +      } +    } + +    if (!isTrusted) { +      log.info("PVP2 metadata: " + metadataUrl + " are NOT trusted!"); +      throw new SamlMetadataSignatureException(metadataUrl, ERROR_MSG_SIGNOTVALID); + +    } + +  } + +} 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 index 2672bef2..aba0a68b 100644 --- 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 @@ -1,23 +1,64 @@  package at.gv.egiz.eaaf.modules.pvp2.impl.verification; +import javax.annotation.Nonnull; + +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2InternalErrorException; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory; + +import org.opensaml.core.config.ConfigurationService;  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 org.opensaml.xmlsec.SignatureValidationConfiguration; +import org.opensaml.xmlsec.SignatureValidationParameters; +import org.opensaml.xmlsec.context.SecurityParametersContext; +import org.opensaml.xmlsec.signature.support.SignatureTrustEngine;  import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException;  @Slf4j  public class EaafMessageContextInitializationHandler extends AbstractMessageHandler<SAMLObject> { +  private final IPvp2MetadataProvider internalMetadataProvider; +  private SignatureTrustEngine trustEngine; + +  public EaafMessageContextInitializationHandler(@Nonnull IPvp2MetadataProvider metadataProvider) { +    internalMetadataProvider = metadataProvider; +  } + +  @Override +  protected void doInitialize() throws ComponentInitializationException { +    try { +      trustEngine = TrustEngineFactory.getSignatureKnownKeysTrustEngine(internalMetadataProvider); + +    } catch (final Pvp2InternalErrorException e) { +      throw new ComponentInitializationException("TrustEngine injection FAILED", e); + +    } +  } + +    @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()); + +    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(trustEngine);    }  } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSaml2HttpRedirectDeflateSignatureSecurityHandler.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSaml2HttpRedirectDeflateSignatureSecurityHandler.java new file mode 100644 index 00000000..204229ee --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSaml2HttpRedirectDeflateSignatureSecurityHandler.java @@ -0,0 +1,107 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.verification; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +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.SamlSigningException; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SamlHttpUtils; + +import org.opensaml.messaging.context.MessageContext; +import org.opensaml.messaging.handler.MessageHandlerException; +import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext; +import org.opensaml.saml.saml2.binding.security.impl.SAML2HTTPRedirectDeflateSignatureSecurityHandler; + +import com.google.common.base.Strings; +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.codec.Base64Support; + +/** + * Always extracts the last http parameter with a specific name from request, if + * more than one with the same name exists. + * + * @author tlenz + * + */ +@Slf4j +public class EaafSaml2HttpRedirectDeflateSignatureSecurityHandler extends +    SAML2HTTPRedirectDeflateSignatureSecurityHandler { + +  public static final String HTTP_REDIRECT_SIGALG = "SigAlg"; +  public static final String HTTP_REDIRECT_SIGNATURE = "Signature"; + +  private IRefreshableMetadataProvider refreshableMetadataProvider = null; + +  /** +   * Signature verification handler that reloads SAML2 metadata if signature +   * verification fails. +   * +   * @param metadataProvider Metadata provider implementation. Refreshing is only +   *                         possible, if that provider implements +   *                         {@link IRefreshableMetadataProvider} +   */ +  public EaafSaml2HttpRedirectDeflateSignatureSecurityHandler( +      @Nullable IPvp2MetadataProvider metadataProvider) { +    if (metadataProvider != null) { +      if (metadataProvider instanceof IRefreshableMetadataProvider) { +        refreshableMetadataProvider = (IRefreshableMetadataProvider) metadataProvider; + +      } else { +        log.trace("Refreshing is not supported by {} metadata-provider", +            metadataProvider.getClass().getSimpleName()); + +      } +    } +  } + +  @Override +  protected void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException { +    try { +      super.doInvoke(messageContext); + +    } catch (final MessageHandlerException e) { +      if (refreshableMetadataProvider != null) { + +        log.debug("Starting metadata refresh process ... "); +        if (refreshableMetadataProvider.refreshMetadataProvider( +            messageContext.getSubcontext(SAMLPeerEntityContext.class).getEntityId())) { +          log.trace("Refreshing successful. Restarting message evaluation ... "); + +          try { +            super.doInvoke(messageContext); +            return; + +          } catch (final MessageHandlerException e1) { +            log.debug("Signature validation fails twice with second error: {}", e.getMessage()); + +          } +        } +      } + +      log.info("Signature validation of SAML message failed. Reason: {}", e.getMessage()); +      throw new MessageHandlerException( +          new SamlSigningException("internal.pvp.10", new Object[] { e.getMessage() }, e)); +    } +  } + +  @Override +  @Nullable +  protected byte[] getSignature() throws MessageHandlerException { +    final String signature = SamlHttpUtils.getLastParameterFromRequest( +        getHttpServletRequest(), HTTP_REDIRECT_SIGNATURE); + +    if (Strings.isNullOrEmpty(signature)) { +      return null; + +    } +    return Base64Support.decode(signature); +  } + +  @Override +  @Nullable +  protected String getSignatureAlgorithm() throws MessageHandlerException { +    return SamlHttpUtils.getLastParameterFromRequest(getHttpServletRequest(), HTTP_REDIRECT_SIGALG); + +  } +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSamlProtocolMessageXmlSignatureSecurityHandler.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSamlProtocolMessageXmlSignatureSecurityHandler.java new file mode 100644 index 00000000..9f6bc864 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSamlProtocolMessageXmlSignatureSecurityHandler.java @@ -0,0 +1,75 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.verification; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +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.SamlSigningException; + +import org.opensaml.messaging.context.MessageContext; +import org.opensaml.messaging.handler.MessageHandlerException; +import org.opensaml.saml.common.binding.security.impl.SAMLProtocolMessageXMLSignatureSecurityHandler; +import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class EaafSamlProtocolMessageXmlSignatureSecurityHandler extends +    SAMLProtocolMessageXMLSignatureSecurityHandler { + +  private IRefreshableMetadataProvider refreshableMetadataProvider = null; + +  /** +   * Signature verification handler that reloads SAML2 metadata if signature +   * verification fails. +   * +   * @param metadataProvider Metadata provider implementation. Refreshing is only +   *                         possible, if that provider implements +   *                         {@link IRefreshableMetadataProvider} +   */ +  public EaafSamlProtocolMessageXmlSignatureSecurityHandler( +      @Nullable IPvp2MetadataProvider metadataProvider) { +    if (metadataProvider != null) { +      if (metadataProvider instanceof IRefreshableMetadataProvider) { +        refreshableMetadataProvider = (IRefreshableMetadataProvider) metadataProvider; + +      } else { +        log.trace("Refreshing is not supported by {} metadata-provider", +            metadataProvider.getClass().getSimpleName()); + +      } +    } +  } + +  @Override +  public void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException { +    try { +      super.doInvoke(messageContext); + +    } catch (final MessageHandlerException e) { +      if (refreshableMetadataProvider != null) { + +        log.debug("Starting metadata refresh process ... "); +        if (refreshableMetadataProvider.refreshMetadataProvider( +            messageContext.getSubcontext(SAMLPeerEntityContext.class).getEntityId())) { +          log.trace("Refreshing successful. Restarting message evaluation ... "); + +          try { +            super.doInvoke(messageContext); +            return; + +          } catch (final MessageHandlerException e1) { +            log.debug("Signature validation fails twice with second error: {}", e.getMessage()); + +          } +        } +      } + +      log.info("Signature validation of SAML message failed. Reason: {}", e.getMessage()); +      throw new MessageHandlerException( +          new SamlSigningException("internal.pvp.10", new Object[] { e.getMessage() }, e)); +    } + +  } +} 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 index e43d0423..a1365023 100644 --- 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 @@ -24,12 +24,12 @@ public class PvpSamlMessageHandlerChain implements MessageHandlerChain<SAMLObjec            + PvpSamlMessageHandlerChain.class.getName() + " not initialized");      } +      for (final MessageHandler<SAMLObject> handler : getHandlers()) {        log.trace("Initializing SAML message handler: {}", handler.getClass().getName());        handler.invoke(messageContext);      } -    }    @Override 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 658dfe16..2e26de7f 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 @@ -68,9 +68,10 @@ public class SamlVerificationEngine {     *     * @param msg            SAML2 message     * @param sigTrustEngine TrustEngine -   * @throws           org.opensaml.xml.security.SecurityException In case of -   *                   invalid signature -   * @throws Exception In case of a general error +   * @throws org.opensaml.xml.security.SecurityException In case of invalid +   *                                                     signature +   * @throws Exception                                   In case of a general +   *                                                     error     */    public void verify(final InboundMessage msg, final SignatureTrustEngine sigTrustEngine)        throws SecurityException, Exception { 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 index cee622c2..8a91c68c 100644 --- 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 @@ -4,6 +4,18 @@ internal.pvp.02=PVP message contains no signature.  internal.pvp.03=Schema-validation of SAML2 message failed with error: {0}  internal.pvp.04=Can not initialize metadata provider for metadata: {0}  internal.pvp.05=Can not initialize metadata provider for metadata: {0}. Reason: {1} +internal.pvp.06=SSL-Server certificate for metadata: {0} not trusted. Details: {1} +internal.pvp.07=Signature verification for metadata: {0} FAILED. Details: {1} +internal.pvp.08=Schema validation for metadata: {0} FAILED. Details: {1} +internal.pvp.09=Can not initialize metadata provider for metadata: {0}. Details: {1} +internal.pvp.10=Signature verification of SAML2 message FAILED. Reason: {0} +internal.pvp.11=General SAML2 message validation error. Reason: {0} +internal.pvp.12=SAML2 metadata: {0} is NOT signed +internal.pvp.13=SAML2 metadata generation failed. Reason: {0} + +pvp2.21=Signature validation of SAML2 Authn. request failed. Reason: {0} +pvp2.22=Validation of SAML2 Authn. request failed. Reason: {0} +pvp2.24=General error during SAML2 Auth. request pre-processing. Reason: {0}  internal.pvp.95=OpenSAML {0}-binding message {1} failed. Reason: {2}  internal.pvp.96=OpenSAML signing FAILED with key: {0}. Reason: {1} 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 index 6adce26e..87073e81 100644 --- 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 @@ -3,6 +3,7 @@ package at.gv.egiz.eaaf.modules.pvp2.test.binding;  import java.io.ByteArrayInputStream;  import java.io.IOException;  import java.io.InputStream; +import java.io.UnsupportedEncodingException;  import java.util.Base64;  import java.util.Map; @@ -13,23 +14,30 @@ 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.core.impl.utils.IHttpClientFactory; +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.CredentialsNotAvailableException;  import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlMessageValidationException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException;  import at.gv.egiz.eaaf.modules.pvp2.impl.binding.PostBinding; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory;  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 at.gv.egiz.eaaf.modules.pvp2.test.metadata.MetadataResolverTest;  import org.apache.commons.io.IOUtils;  import org.apache.commons.lang3.RandomStringUtils; +import org.joda.time.DateTime;  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; @@ -40,6 +48,7 @@ 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.opensaml.saml.saml2.metadata.SPSSODescriptor;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.mock.web.MockHttpServletRequest;  import org.springframework.mock.web.MockHttpServletResponse; @@ -49,9 +58,11 @@ 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; +import okhttp3.HttpUrl; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer;  @RunWith(SpringJUnit4ClassRunner.class)  @ContextConfiguration({"/spring/test_eaaf_pvp.beans.xml"}) @@ -65,15 +76,27 @@ public class PostBindingTest {    @Autowired private PostBinding bindingImpl;    @Autowired private DummyCredentialProvider credentialProvider;    @Autowired private DummyGuiBuilderConfigurationFactory guiBuilderFactory; +  @Autowired private PvpMetadataResolverFactory metadataResolverFactory; +  @Autowired private IHttpClientFactory httpClientFactory; + +  private static MockWebServer mockWebServer; +  private static HttpUrl mockServerUrl;    protected MockHttpServletRequest httpReq;    protected MockHttpServletResponse httpResp;    protected IRequest pendingReq; +  /** +   * JUnit class initializer. +   * +   * @throws Exception In case of an OpenSAML3 initialization error +   */    @BeforeClass -  public static void classInitializer() throws InitializationException, ComponentInitializationException { +  public static void classInitializer() throws Exception {      EaafOpenSaml3xInitializer.eaafInitialize(); +    mockWebServer = new MockWebServer(); +    mockServerUrl = mockWebServer.url("/sp/metadata");    }    /** @@ -101,12 +124,14 @@ public class PostBindingTest {    }    @Test -  public void decodeRequestSuccess() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception { -    final String serviceUrl = "http://testservice.org"; +  public void decodeRequestWrongEndpoint() throws MessageDecodingException, SecurityException, +      IOException, Pvp2MetadataException { +    final String serviceUrl = "https://wrongEndpoint/pvp2/post"; -    final IPvp2MetadataProvider metadataProvider = null; +    final IPvp2MetadataProvider metadataProvider = +        metadataResolverFactory.createMetadataProvider( +            "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null); -    final boolean isSpEndPoint = false;      final URIComparator comparator = new EaafUriCompare(serviceUrl);      final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray( @@ -114,39 +139,169 @@ public class PostBindingTest {      httpReq.setMethod("POST");      httpReq.addParameter("SAMLRequest", b64AuthnReq); +    try { +      bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); +      Assert.fail("Wrong http end-point not detected"); + +    } catch (final Pvp2Exception e) { +      Assert.assertEquals("Wrong errorCode", "internal.pvp.11", e.getErrorId()); +      Assert.assertNotNull("Parameters null", e.getParams()); +      Assert.assertEquals("Wrong numer of parameters", 1, e.getParams().length); + + +    } + +  } + +  @Test +  public void decodeRequestMissingSignature() throws MessageDecodingException, SecurityException, +      IOException, Pvp2MetadataException { +    final String serviceUrl = "https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/post"; + +    final IPvp2MetadataProvider metadataProvider = +        metadataResolverFactory.createMetadataProvider( +            "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null); + +    final URIComparator comparator = new EaafUriCompare(serviceUrl); + +    final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray( +        PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml"))); +    httpReq.setMethod("POST"); +    httpReq.addParameter("SAMLRequest", b64AuthnReq); + +    try { +      bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); +      Assert.fail("Missing signature not detected"); + +    } catch (final Pvp2Exception e) { +      Assert.assertEquals("Wrong errorCode", "internal.pvp.02", e.getErrorId()); + +    } + +  } + +  @Test +  public void decodeRequestWrongSignature() throws MessageDecodingException, SecurityException, +      IOException, Pvp2Exception { +    final String serviceUrl = "https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/post"; + +    final IPvp2MetadataProvider metadataProvider = +        metadataResolverFactory.createMetadataProvider( +            "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null); + +    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); + +    try { +      bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); +      Assert.fail("Invalid signature not detected"); + +    } catch (final Pvp2Exception e) { +      org.springframework.util.Assert.isInstanceOf(SamlSigningException.class, e, "Wrong Exception type"); +      Assert.assertEquals("Wrong errorCode", "internal.pvp.10", e.getErrorId()); +      Assert.assertNotNull("No error params", e.getParams()); +      Assert.assertEquals("Wrong param size", 1, e.getParams().length); + +    } + +  } + +  @Test +  public void decodeRequestMsgExpired() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception { +    final String serviceUrl = "https://eidas-test.bmi.gv.at/ms_connector/pvp/post"; + +    final IPvp2MetadataProvider metadataProvider = +        metadataResolverFactory.createMetadataProvider( +            "classpath:/data/pvp_metadata_moaid_test.xml", null, "jUnit metadata resolver", null); + +    final URIComparator comparator = new EaafUriCompare(serviceUrl); + +    final String b64AuthnReq = new String(IOUtils.toByteArray( +        PostBindingTest.class.getResourceAsStream("/data/AuthRequest_withsig_expired.b64")), "UTF-8"); +    httpReq.setMethod("POST"); +    httpReq.addParameter("SAMLRequest", b64AuthnReq); + + +    try { +      bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); +      Assert.fail("Expired msg not detected"); + +    } catch (final Pvp2Exception e) { +      org.springframework.util.Assert.isInstanceOf(SamlMessageValidationException.class, e, "Wrong Exception type"); +      Assert.assertEquals("Wrong errorCode", "internal.pvp.11", e.getErrorId()); +      Assert.assertNotNull("No error params", e.getParams()); +      Assert.assertEquals("Wrong param size", 1, e.getParams().length); + +    } + +  } + +  @Test +  public void decodeRequestSuccessMetadataReloadRequired() throws MessageDecodingException, SecurityException, +      IOException, Pvp2Exception, CredentialsNotAvailableException, XMLParserException, UnmarshallingException { +    final String serviceUrl = "http://testservice.org"; + +    final String b64AuthnReq = generateSaml2AuthnRequest( +        credentialProvider.getIdpMetaDataSigningCredential()); +    httpReq.setMethod("POST"); +    httpReq.addParameter("SAMLRequest", b64AuthnReq); + +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(new String(IOUtils.toByteArray( +            MetadataResolverTest.class.getResourceAsStream( +                "/data/pvp_metadata_wrong_sig.xml")), "UTF-8")) +        .setHeader("Content-Type", "text/xml")); + +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(new String(IOUtils.toByteArray( +            MetadataResolverTest.class.getResourceAsStream( +                "/data/pvp_metadata_junit_keystore.xml")), "UTF-8")) +        .setHeader("Content-Type", "text/xml")); + +    final IPvp2MetadataProvider metadataProvider = +        metadataResolverFactory.createMetadataProvider( +            mockServerUrl.url().toString(), +            null, "jUnit test", httpClientFactory.getHttpClient()); + +    final URIComparator comparator = new EaafUriCompare(serviceUrl); +      final InboundMessageInterface msg = -        bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, comparator); +        bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator);      Assert.assertNotNull("PVP msg is null", msg); -    Assert.assertNull("RelayState is not null", msg.getRelayState()); +    Assert.assertNull("RelayState 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()); +    Assert.assertTrue("Wrong isVerified flag", msg.isVerified());    }    @Test -  public void decodeRequestSuccessWithRelayState() throws MessageDecodingException, SecurityException, -      IOException, Pvp2Exception { +  public void decodeRequestSuccessWithRelayStateRsaSig() throws MessageDecodingException, SecurityException, +      IOException, Pvp2Exception, CredentialsNotAvailableException, XMLParserException, UnmarshallingException {      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"))); +    final String b64AuthnReq = generateSaml2AuthnRequest( +        credentialProvider.getIdpMetaDataSigningCredential());      httpReq.setMethod("POST");      httpReq.addParameter("SAMLRequest", b64AuthnReq);      httpReq.addParameter("RelayState", relayState); -    final IPvp2MetadataProvider metadataProvider = null; +    final IPvp2MetadataProvider metadataProvider = +        metadataResolverFactory.createMetadataProvider( +            "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); -    final boolean isSpEndPoint = false;      final URIComparator comparator = new EaafUriCompare(serviceUrl); -      final InboundMessageInterface msg = -        bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, comparator); +        bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator);      Assert.assertNotNull("PVP msg is null", msg);      Assert.assertNotNull("RelayState is not null", msg.getRelayState()); @@ -154,64 +309,63 @@ public class PostBindingTest {      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()); +    Assert.assertTrue("Wrong isVerified flag", msg.isVerified());    }    @Test -  public void decodeResponseSuccess() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception { +  public void decodeRequestSuccessWithoutRelayStateEcdsaSig() throws MessageDecodingException, SecurityException, +      IOException, Pvp2Exception, CredentialsNotAvailableException, XMLParserException, UnmarshallingException {      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"))); +    final String b64AuthnReq = generateSaml2AuthnRequest( +        credentialProvider.getIdpAssertionSigningCredential());      httpReq.setMethod("POST");      httpReq.addParameter("SAMLRequest", b64AuthnReq); +    final IPvp2MetadataProvider metadataProvider = +        metadataResolverFactory.createMetadataProvider( +            "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); + +    final URIComparator comparator = new EaafUriCompare(serviceUrl); +      final InboundMessageInterface msg = -        bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, comparator); +        bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, 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("AuthnReq 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()); +    Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg.getEntityID()); +    Assert.assertTrue("Wrong isVerified flag", msg.isVerified());    }    @Test -  public void decodeResponseSuccessWithRelayState() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception { +  public void decodeResponseSuccess() throws MessageDecodingException, SecurityException, +      IOException, Pvp2Exception, CredentialsNotAvailableException, XMLParserException, UnmarshallingException {      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 = +        metadataResolverFactory.createMetadataProvider( +            "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); -    final IPvp2MetadataProvider metadataProvider = null; - -    final boolean isSpEndPoint = false;      final URIComparator comparator = new EaafUriCompare(serviceUrl); +    final String b64AuthnReq = generateSaml2Response(credentialProvider.getIdpMetaDataSigningCredential()); +    httpReq.setMethod("POST"); +    httpReq.addParameter("SAMLRequest", b64AuthnReq);      final InboundMessageInterface msg = -        bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, comparator); +        bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, 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.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()); +    Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg.getEntityID()); +    Assert.assertTrue("Wrong isVerified flag", msg.isVerified());    } @@ -445,4 +599,48 @@ public class PostBindingTest {    } +  private String generateSaml2AuthnRequest(EaafX509Credential credentials) +      throws XMLParserException, UnmarshallingException, Pvp2Exception, CredentialsNotAvailableException, +      UnsupportedEncodingException { +    final MockHttpServletRequest intHttpReq = new MockHttpServletRequest(); +    final MockHttpServletResponse intHttpResp = new MockHttpServletResponse(); +    guiBuilderFactory.setVelocityBuilderConfig(createDummyGuiConfig()); +    final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( +        XMLObjectProviderRegistrySupport.getParserPool(), +        PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml")); +    authnReq.setIssueInstant(DateTime.now()); + +    bindingImpl.encodeRequest(intHttpReq, intHttpResp, authnReq, "http://testservice.org", null, +        credentials, pendingReq); + +    Assert.assertEquals("http StatusCode", 200, intHttpResp.getStatus()); +    final String http = intHttpResp.getContentAsString(); +    Assert.assertNotNull("http body is null", http); +    Assert.assertTrue("SAMLRequest parameter", http.contains(HTTP_FORM_SAMLREQ)); +    return extractParamFromHttpForm(http, HTTP_FORM_SAMLREQ); + +  } + +  private String generateSaml2Response(EaafX509Credential credentials) +      throws XMLParserException, UnmarshallingException, Pvp2Exception, CredentialsNotAvailableException, +      UnsupportedEncodingException { +    final MockHttpServletRequest intHttpReq = new MockHttpServletRequest(); +    final MockHttpServletResponse intHttpResp = new MockHttpServletResponse(); +    guiBuilderFactory.setVelocityBuilderConfig(createDummyGuiConfig()); +    final StatusResponseType response = (StatusResponseType)  XMLObjectSupport.unmarshallFromInputStream( +        XMLObjectProviderRegistrySupport.getParserPool(), +        PostBindingTest.class.getResourceAsStream("/data/Response_without_sig_1.xml")); +    response.setIssueInstant(DateTime.now()); + +    bindingImpl.encodeResponse(intHttpReq, intHttpResp, response, "http://testservice.org", null, +        credentials, pendingReq); + +    Assert.assertEquals("http StatusCode", 200, intHttpResp.getStatus()); +    final String http = intHttpResp.getContentAsString(); +    Assert.assertNotNull("http body is null", http); +    Assert.assertTrue("SAMLRequest parameter", http.contains(HTTP_FORM_SAMLRESP)); +    return extractParamFromHttpForm(http, HTTP_FORM_SAMLRESP); + +  } +  } 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 index a99c8461..23cc98a6 100644 --- 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 @@ -6,15 +6,34 @@ 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.core.impl.utils.IHttpClientFactory; +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.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.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlMessageValidationException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; +import at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; +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 at.gv.egiz.eaaf.modules.pvp2.test.metadata.MetadataResolverTest; +  import org.apache.commons.io.IOUtils;  import org.apache.commons.lang3.RandomStringUtils; +import org.joda.time.DateTime;  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; @@ -22,6 +41,7 @@ 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.opensaml.saml.saml2.metadata.SPSSODescriptor;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.mock.web.MockHttpServletRequest;  import org.springframework.mock.web.MockHttpServletResponse; @@ -30,46 +50,57 @@ import org.springframework.test.context.TestPropertySource;  import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  import org.xml.sax.SAXException; -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.metadata.PvpMetadataResolverFactory; -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 net.shibboleth.utilities.java.support.component.ComponentInitializationException;  import net.shibboleth.utilities.java.support.net.URIComparator; +import net.shibboleth.utilities.java.support.net.URISupport;  import net.shibboleth.utilities.java.support.xml.XMLParserException; +import okhttp3.HttpUrl; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer;  @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration({"/spring/test_eaaf_pvp.beans.xml"}) -@TestPropertySource(locations = {"/config/config_1.props"}) +@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_FORM_RELAYSTATE = "RelayState"; +  public static final String HTTP_FORM_RELAYSTATE_PARAM = HTTP_FORM_RELAYSTATE + "="; + +  public static final String HTTP_FORM_SAMLREQ = "SAMLRequest"; +  public static final String HTTP_FORM_SAMLREQ_PARAM = HTTP_FORM_SAMLREQ + "="; +  public static final String HTTP_FORM_SAMLRESP = "SAMLResponse"; +  public static final String HTTP_FORM_SAMLRESP_PARM = HTTP_FORM_SAMLRESP + "="; + +  public static final String HTTP_REDIRECT_SIGALG = "SigAlg"; +  public static final String HTTP_REDIRECT_SIGALG_PARAM = HTTP_REDIRECT_SIGALG + "="; +  public static final String HTTP_REDIRECT_SIGNATURE = "Signature"; +  public static final String HTTP_REDIRECT_SIGNATURE_PARAM = HTTP_REDIRECT_SIGNATURE + "="; -  public static final String HTTP_REDIRECT_SIGALG = "SigAlg="; -  public static final String HTTP_REDIRECT_SIGNATURE = "Signature="; +  @Autowired +  private RedirectBinding bindingImpl; +  @Autowired +  private DummyCredentialProvider credentialProvider; +  @Autowired +  private PvpMetadataResolverFactory metadataResolverFactory; +  @Autowired private IHttpClientFactory httpClientFactory; -  @Autowired private RedirectBinding bindingImpl; -  @Autowired private DummyCredentialProvider credentialProvider; -  @Autowired private PvpMetadataResolverFactory metadataResolverFactory; +  private static MockWebServer mockWebServer; +  private static HttpUrl mockServerUrl;    protected MockHttpServletRequest httpReq;    protected MockHttpServletResponse httpResp;    protected IRequest pendingReq; +  /** +   * JUnit class initializer. +   * +   * @throws Exception In case of an OpenSAML3 initialization error +   */    @BeforeClass -  public static void classInitializer() throws InitializationException, ComponentInitializationException { +  public static void classInitializer() throws Exception {      EaafOpenSaml3xInitializer.eaafInitialize(); +    mockWebServer = new MockWebServer(); +    mockServerUrl = mockWebServer.url("/sp/metadata");    }    /** @@ -97,34 +128,236 @@ public class RedirectBindingTest {    }    @Test -  public void decodeRequestSuccess() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception { +  public void decodeRequestNoSignature() throws MessageDecodingException, +      SecurityException, IOException, Pvp2MetadataException { +    final String serviceUrl = "http://testservice.org"; + +    final IPvp2MetadataProvider metadataProvider = +        metadataResolverFactory.createMetadataProvider( +            "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null); + +    final URIComparator comparator = new EaafUriCompare(serviceUrl); + +    httpReq.setMethod("GET"); +    httpReq.setRequestURI("http://testservice.org"); +    httpReq.setQueryString("SAMLRequest=nVRNb9swDD13wP6DoXvkr%2FRjQuzCSFAgQDd0TbfDLoVi0642Wcok2kn766c4duABWw%" +        + "2B%2BSdQj%2BfhIanF7qKXXgrFCq4SENCAeqFwXQlUJ%2BfZ0N7sht%2BnC8lpGO5Y1%2BKIe4XcDFj3nqCw7vSSkMYppboVli" +        + "tdgGeZsk32%2BZxEN2M5o1LmWxMusBYMu1VIr29RgNmBakcNaFXBw6R0C0Yhtg3BCOBp%2FQxy%2FlcsuFMeO8Qvijvk%2BOps" +        + "9Aak2FfHWq4Q8c4BtySHO4eomLCEuipyXURjzeVQGYRE7mLWNC22RK0xIFITzWRDPgsun4IrFn1gQ0evryx%2FE%2Bz4o5Oohv" +        + "R6sczZjId7XgQ%2FVE%2B9Om5rj%2B%2FCjRRSzsoMyUCjwlaTHgq2ruIBaU6jEG61ayrG777RBLp%2BPR6krofyFP2Y68N402" +        + "5%2BQ4xTi6ccPFxd9mC8Ot15NI9T7umiDpSd1nrUT4kFLkb96mZR6vzTAERKCpoEpCu6OPbTohCRThtc%2FU%2Bs3AIpuH9ygI" +        + "hwm7cNYzXGspXSKP0I5qUP9Ruz3e2pRm1%2B00i2Fxne77ecCxRuor1l2Dy1Ifz6o%2F6%2Fso%2B78p%2Bb0%2FDz%2BGdI%2" +        + "F&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=DOVMqh17xn4wl%2" +        + "Byvifm4McMsBjKDVf1eqph9ss362ZEbp2nkAIXUzkNWv72I96iNK3r%2BYbAxY9dwZ8Z7jKzCGiJ9Qm34YSfPvzXWl3EVrdI86" +        + "9U%2BH6HGIMqVew3cVdr4q3Qv9ZBIhdRxbrDu%2F%2BnMjdf8mzbgcQnfjSQiQIYWxOIXZFyxKsyrxJtIam4hoNwUT7mMN6Rjg" +        + "zvyeS3mARsTJdcI0Vn4ItiprhLgIkD18V9WIdeSZR0gfRaFj8PKdmXCD%2FIa0cKgjhVKoiIZisV4vcthBOeDIqBORL2Ad3Xhc" +        + "NRQ3%2BcpAf65zHGMBAv1aRy7Bmv0%2B%2BOvCavufykqI2EHtg%3D%3D"); + +    httpReq.setParameter(HTTP_FORM_SAMLREQ, URLDecoder.decode(URISupport.getRawQueryStringParameter( +        httpReq.getQueryString(), HTTP_FORM_SAMLREQ).substring(HTTP_FORM_SAMLREQ_PARAM.length()), "UTF-8")); +    httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter( +        httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()), +        "UTF-8")); + +    try { +      bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, +          comparator); +      Assert.fail("Missing signature not detected"); + +    } catch (final Pvp2Exception e) { +      Assert.assertEquals("Wrong errorCode", "internal.pvp.02", e.getErrorId()); + +    } + +  } + +  @Test +  public void decodeRequestWrongEndpoint() throws MessageDecodingException, +      SecurityException, IOException, Pvp2Exception { +    final String serviceUrl = "http://wrongEndPoint.org"; + +    final IPvp2MetadataProvider metadataProvider = +        metadataResolverFactory.createMetadataProvider( +            "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null); + +    final URIComparator comparator = new EaafUriCompare(serviceUrl); + +    httpReq.setMethod("GET"); +    httpReq.setRequestURI("http://testservice.org"); +    httpReq.setQueryString("SAMLRequest=nVRNb9swDD13wP6DoXvkr%2FRjQuzCSFAgQDd0TbfDLoVi0642Wcok2kn766c4duABWw%" +        + "2B%2BSdQj%2BfhIanF7qKXXgrFCq4SENCAeqFwXQlUJ%2BfZ0N7sht%2BnC8lpGO5Y1%2BKIe4XcDFj3nqCw7vSSkMYppboVli" +        + "tdgGeZsk32%2BZxEN2M5o1LmWxMusBYMu1VIr29RgNmBakcNaFXBw6R0C0Yhtg3BCOBp%2FQxy%2FlcsuFMeO8Qvijvk%2BOps" +        + "9Aak2FfHWq4Q8c4BtySHO4eomLCEuipyXURjzeVQGYRE7mLWNC22RK0xIFITzWRDPgsun4IrFn1gQ0evryx%2FE%2Bz4o5Oohv" +        + "R6sczZjId7XgQ%2FVE%2B9Om5rj%2B%2FCjRRSzsoMyUCjwlaTHgq2ruIBaU6jEG61ayrG777RBLp%2BPR6krofyFP2Y68N402" +        + "5%2BQ4xTi6ccPFxd9mC8Ot15NI9T7umiDpSd1nrUT4kFLkb96mZR6vzTAERKCpoEpCu6OPbTohCRThtc%2FU%2Bs3AIpuH9ygI" +        + "hwm7cNYzXGspXSKP0I5qUP9Ruz3e2pRm1%2B00i2Fxne77ecCxRuor1l2Dy1Ifz6o%2F6%2Fso%2B78p%2Bb0%2FDz%2BGdI%2" +        + "F&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=DOVMqh17xn4wl%2" +        + "Byvifm4McMsBjKDVf1eqph9ss362ZEbp2nkAIXUzkNWv72I96iNK3r%2BYbAxY9dwZ8Z7jKzCGiJ9Qm34YSfPvzXWl3EVrdI86" +        + "9U%2BH6HGIMqVew3cVdr4q3Qv9ZBIhdRxbrDu%2F%2BnMjdf8mzbgcQnfjSQiQIYWxOIXZFyxKsyrxJtIam4hoNwUT7mMN6Rjg" +        + "zvyeS3mARsTJdcI0Vn4ItiprhLgIkD18V9WIdeSZR0gfRaFj8PKdmXCD%2FIa0cKgjhVKoiIZisV4vcthBOeDIqBORL2Ad3Xhc" +        + "NRQ3%2BcpAf65zHGMBAv1aRy7Bmv0%2B%2BOvCavufykqI2EHtg%3D%3D"); + +    httpReq.setParameter(HTTP_FORM_SAMLREQ, URLDecoder.decode(URISupport.getRawQueryStringParameter( +        httpReq.getQueryString(), HTTP_FORM_SAMLREQ).substring(HTTP_FORM_SAMLREQ_PARAM.length()), "UTF-8")); +    httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter( +        httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()), +        "UTF-8")); +    httpReq.setParameter(HTTP_REDIRECT_SIGNATURE, URLDecoder.decode(URISupport.getRawQueryStringParameter( +        httpReq.getQueryString(), HTTP_REDIRECT_SIGNATURE).substring(HTTP_REDIRECT_SIGNATURE_PARAM.length()), +        "UTF-8")); + +    try { +      bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, +          comparator); +      Assert.fail("Wrong signature not detected"); + +    } catch (final Pvp2Exception e) { +      Assert.assertEquals("Wrong errorCode", "internal.pvp.10", e.getErrorId()); +      Assert.assertNotNull("Parameters null", e.getParams()); +      Assert.assertEquals("Wrong numer of parameters", 1, e.getParams().length); + +    } + +  } + +  @Test +  public void decodeRequestWrongSignature() throws MessageDecodingException, +      SecurityException, IOException, Pvp2Exception { +    final String serviceUrl = "http://testservice.org"; + +    final IPvp2MetadataProvider metadataProvider = +        metadataResolverFactory.createMetadataProvider( +            "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null); + +    final URIComparator comparator = new EaafUriCompare(serviceUrl); + +    httpReq.setMethod("GET"); +    httpReq.setRequestURI("http://testservice.org"); +    httpReq.setQueryString("SAMLRequest=nVRNb9swDD13wP6DoXvkr%2FRjQuzCSFAgQDd0TbfDLoVi0642Wcok2kn766c4duABWw%" +        + "2B%2BSdQj%2BfhIanF7qKXXgrFCq4SENCAeqFwXQlUJ%2BfZ0N7sht%2BnC8lpGO5Y1%2BKIe4XcDFj3nqCw7vSSkMYppboVli" +        + "tdgGeZsk32%2BZxEN2M5o1LmWxMusBYMu1VIr29RgNmBakcNaFXBw6R0C0Yhtg3BCOBp%2FQxy%2FlcsuFMeO8Qvijvk%2BOps" +        + "9Aak2FfHWq4Q8c4BtySHO4eomLCEuipyXURjzeVQGYRE7mLWNC22RK0xIFITzWRDPgsun4IrFn1gQ0evryx%2FE%2Bz4o5Oohv" +        + "R6sczZjId7XgQ%2FVE%2B9Om5rj%2B%2FCjRRSzsoMyUCjwlaTHgq2ruIBaU6jEG61ayrG777RBLp%2BPR6krofyFP2Y68N402" +        + "5%2BQ4xTi6ccPFxd9mC8Ot15NI9T7umiDpSd1nrUT4kFLkb96mZR6vzTAERKCpoEpCu6OPbTohCRThtc%2FU%2Bs3AIpuH9ygI" +        + "hwm7cNYzXGspXSKP0I5qUP9Ruz3e2pRm1%2B00i2Fxne77ecCxRuor1l2Dy1Ifz6o%2F6%2Fso%2B78p%2Bb0%2FDz%2BGdI%2" +        + "F&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=DOVMqh17xn4wl%2" +        + "Byvifm4McMsBjKDVf1eqph9ss362ZEbp2nkAIXUzkNWv72I96iNK3r%2BYbAxY9dwZ8Z7jKzCGiJ9Qm34YSfPvzXWl3EVrdI86" +        + "9U%2BH6HGIMqVew3cVdr4q3Qv9ZBIhdRxbrDu%2F%2BnMjdf8mzbgcQnfjSQiQIYWxOIXZFyxKsyrxJtIam4hoNwUT7mMN6Rjg" +        + "zvyeS3mARsTJdcI0Vn4ItiprhLgIkD18V9WIdeSZR0gfRaFj8PKdmXCD%2FIa0cKgjhVKoiIZisV4vcthBOeDIqBORL2Ad3Xhc" +        + "NRQ3%2BcpAf65zHGMBAv1aRy7Bmv0%2B%2BOvCavufykqI2EHtg%3D%3D"); + +    httpReq.setParameter(HTTP_FORM_SAMLREQ, URLDecoder.decode(URISupport.getRawQueryStringParameter( +        httpReq.getQueryString(), HTTP_FORM_SAMLREQ).substring(HTTP_FORM_SAMLREQ_PARAM.length()), "UTF-8")); +    httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter( +        httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()), +        "UTF-8")); +    httpReq.setParameter(HTTP_REDIRECT_SIGNATURE, URLDecoder.decode(URISupport.getRawQueryStringParameter( +        httpReq.getQueryString(), HTTP_REDIRECT_SIGNATURE).substring(HTTP_REDIRECT_SIGNATURE_PARAM.length()), +        "UTF-8")); + +    try { +      bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, +          comparator); +      Assert.fail("Wrong signature not detected"); + +    } catch (final Pvp2Exception e) { +      org.springframework.util.Assert.isInstanceOf(SamlSigningException.class, e, "Wrong Exception type"); +      Assert.assertEquals("Wrong errorCode", "internal.pvp.10", e.getErrorId()); +      Assert.assertNotNull("No error params", e.getParams()); +      Assert.assertEquals("Wrong param size", 1, e.getParams().length); + +    } + +  } + +  @Test +  public void decodeRequestExpired() throws MessageDecodingException, +      SecurityException, IOException, Pvp2Exception, CredentialsNotAvailableException, +      XMLParserException, UnmarshallingException {      final String serviceUrl = "http://testservice.org"; -     -    final IPvp2MetadataProvider metadataProvider =  + +    final IPvp2MetadataProvider metadataProvider =          metadataResolverFactory.createMetadataProvider( -            "classpath:/data/metadata_1.xml", null, "jUnit metadata resolver", null); +            "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", 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=="); +    httpReq.setQueryString("SAMLRequest=nVRNb9swDD13wP6DoXvkj2RFJsQujAQFAnTD1nQ97FIoNu1qkyVPop20v36KYwcusPVgQ" +        + "AeLeiQfH0mvbo6V9FowVmgVk5AGxAOV6VyoMiY%2FHm5nS3KTrCyvZFSztMFndQ9%2FGrDoOUdl2fklJo1RTHMrLFO8AsswY7v" +        + "0yx2LaMBqo1FnWhIvtRYMulRrrWxTgdmBaUUGW5XD0aV3CEQj9g3CGeFovIU4fhuXXSiOHeNnxJr5PjqbPQOpNiXxtpuYPHGAf" +        + "cFhnsH1MixgnucZL6JwzhdREYT53MGsbVxoi1xhTKIgCmZBNAsWD8Fn5s6na7qMwp%2FEexwUcvWQXg%2FWOZuxEO%2FrwIfqi" +        + "XerTcXxffjJIvJZ0UEZKBT4QpJTwdZVnEOlKZTilZYt5djda22Qy6fTp9SlUP7KHzMdeO%2Ba%2FS%2FIcArx5OOHq6s%2BzFe" +        + "H226mEep9XbTB0pO6zNoZ8U1Lkb14qZT6sDbAEWKCpoEpCtanHlp0QpIpw%2BtfqPUbAHm3D25QEY6T9mGs5jjWWjrF76GY1KF" +        + "%2BIw6HA7WozW9a6pZC47vd9jOB4hXU9zS9gxakvxjU%2F1f2UXf%2BU3NyeR7%2FGZK%2F&SigAlg=http%3A%2F%2Fwww.w3" +        + ".org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=JogFpk2oimCnBCgE7eZx%2B6yoJu2ZCgus5vM1opkTk" +        + "OLM9qgNMUJJJbIeA3j2TR%2BWx3pUApnV7ed9CuTBF94b3ELkFdaZAetfLzY8gnPLCBmcYIYkwg3bK7ZQWEBJpjNoU%2BaBHXV" +        + "OgptLUt0qRWavm%2BiPOUXRWpb0PtgvApTieRk32gBfZbuPOltWjrRCKaa2ulKBjB34LqYdAaIWaVix2sGvg128p6lC7bQ%2Fz" +        + "wmz6j8S5Vn8snvlg48MlBldTWKSZrUERx3MwTyaB17A617XmX2QKo8fGCQ6O7FF4umFyWGAlujI%2FwqafTfPlaNX2usHynHS6" +        + "XkH5HWCDSAe3%2BVR1w%3D%3D "); + +    httpReq.setParameter(HTTP_FORM_SAMLREQ, URLDecoder.decode(URISupport.getRawQueryStringParameter( +        httpReq.getQueryString(), HTTP_FORM_SAMLREQ).substring(HTTP_FORM_SAMLREQ_PARAM.length()), "UTF-8")); +    httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter( +        httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()), +        "UTF-8")); +    httpReq.setParameter(HTTP_REDIRECT_SIGNATURE, URLDecoder.decode(URISupport.getRawQueryStringParameter( +        httpReq.getQueryString(), HTTP_REDIRECT_SIGNATURE).substring(HTTP_REDIRECT_SIGNATURE_PARAM.length()), +        "UTF-8")); + +    try { +      bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, +          comparator); +      Assert.fail("Expired message not detected"); + +    } catch (final Pvp2Exception e) { +      org.springframework.util.Assert.isInstanceOf(SamlMessageValidationException.class, e, +          "Wrong Exception type"); +      Assert.assertEquals("Wrong errorCode", "internal.pvp.11", e.getErrorId()); +      Assert.assertNotNull("No error params", e.getParams()); +      Assert.assertEquals("Wrong param size", 1, e.getParams().length); + +    } + +  } +  @Test +  public void decodeRequestSuccess() throws MessageDecodingException, +      SecurityException, IOException, Pvp2Exception, CredentialsNotAvailableException, +      XMLParserException, UnmarshallingException { +    final String serviceUrl = "http://testservice.org"; +    final IPvp2MetadataProvider metadataProvider = +        metadataResolverFactory.createMetadataProvider( +            "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); +    final URIComparator comparator = new EaafUriCompare(serviceUrl); + +    httpReq.setMethod("GET"); +    httpReq.setRequestURI("http://testservice.org"); +    httpReq.setQueryString(generateAuthnRequest(credentialProvider.getIdpMetaDataSigningCredential())); + +    httpReq.setParameter(HTTP_FORM_SAMLREQ, URLDecoder.decode(URISupport.getRawQueryStringParameter( +        httpReq.getQueryString(), HTTP_FORM_SAMLREQ).substring(HTTP_FORM_SAMLREQ_PARAM.length()), "UTF-8")); +    httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter( +        httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()), +        "UTF-8")); +    httpReq.setParameter(HTTP_REDIRECT_SIGNATURE, URLDecoder.decode(URISupport.getRawQueryStringParameter( +        httpReq.getQueryString(), HTTP_REDIRECT_SIGNATURE).substring(HTTP_REDIRECT_SIGNATURE_PARAM.length()), +        "UTF-8"));      final InboundMessageInterface msg = -        bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, comparator); +        bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, +            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()); +    Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg +        .getEntityID()); +    Assert.assertTrue("Wrong isVerified flag", msg.isVerified());    } @@ -143,88 +376,123 @@ public class RedirectBindingTest {      final IPvp2MetadataProvider metadataProvider = null; -    final boolean isSpEndPoint = false;      final URIComparator comparator = new EaafUriCompare(serviceUrl); -      final InboundMessageInterface msg = -        bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, comparator); +        bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, +            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.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 { +  public void decodeResponseSuccess() throws MessageDecodingException, SecurityException, IOException, +      Pvp2Exception, CredentialsNotAvailableException, XMLParserException, UnmarshallingException {      final String serviceUrl = "http://testservice.org"; -    final IPvp2MetadataProvider metadataProvider = null; +    final IPvp2MetadataProvider metadataProvider = +        metadataResolverFactory.createMetadataProvider( +            "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", 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); +    httpReq.setMethod("GET"); +    httpReq.setRequestURI("http://testservice.org"); +    httpReq.setQueryString(generateResponse(credentialProvider.getIdpMetaDataSigningCredential())); +    httpReq.setParameter(HTTP_FORM_SAMLRESP, URLDecoder.decode(URISupport.getRawQueryStringParameter( +        httpReq.getQueryString(), HTTP_FORM_SAMLRESP).substring(HTTP_FORM_SAMLRESP_PARM.length()), "UTF-8")); +    httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter( +        httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()), +        "UTF-8")); +    httpReq.setParameter(HTTP_REDIRECT_SIGNATURE, URLDecoder.decode(URISupport.getRawQueryStringParameter( +        httpReq.getQueryString(), HTTP_REDIRECT_SIGNATURE).substring(HTTP_REDIRECT_SIGNATURE_PARAM.length()), +        "UTF-8"));      final InboundMessageInterface msg = -        bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, comparator); +        bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, +            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()); +    Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg +        .getEntityID()); +    Assert.assertTrue("Wrong isVerified flag", msg.isVerified());    } -  @Ignore    @Test -  public void decodeResponseSuccessWithRelayState() throws MessageDecodingException, SecurityException, -      IOException, Pvp2Exception { +  public void decodeResponseSuccessWithRelayStateAndMetadataReload() throws MessageDecodingException, +      SecurityException, IOException, Pvp2Exception, CredentialsNotAvailableException, +      XMLParserException, UnmarshallingException {      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); +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(new String(IOUtils.toByteArray( +            MetadataResolverTest.class.getResourceAsStream( +                "/data/pvp_metadata_wrong_sig.xml")), "UTF-8")) +        .setHeader("Content-Type", "text/xml")); -    final IPvp2MetadataProvider metadataProvider = null; +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(new String(IOUtils.toByteArray( +            MetadataResolverTest.class.getResourceAsStream( +                "/data/pvp_metadata_junit_keystore.xml")), "UTF-8")) +        .setHeader("Content-Type", "text/xml")); -    final boolean isSpEndPoint = false; -    final URIComparator comparator = new EaafUriCompare(serviceUrl); +    final IPvp2MetadataProvider metadataProvider = +        metadataResolverFactory.createMetadataProvider( +            mockServerUrl.url().toString(), +            null, "jUnit test", httpClientFactory.getHttpClient()); +    httpReq.setMethod("GET"); +    httpReq.setRequestURI("http://testservice.org"); +    httpReq.setParameter(HTTP_FORM_RELAYSTATE, relayState); +    httpReq.setQueryString(generateResponse(credentialProvider.getIdpMetaDataSigningCredential())); + +    httpReq.setParameter(HTTP_FORM_SAMLRESP, URLDecoder.decode(URISupport.getRawQueryStringParameter( +        httpReq.getQueryString(), HTTP_FORM_SAMLRESP).substring(HTTP_FORM_SAMLRESP_PARM.length()), "UTF-8")); +    httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter( +        httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()), +        "UTF-8")); +    httpReq.setParameter(HTTP_REDIRECT_SIGNATURE, URLDecoder.decode(URISupport.getRawQueryStringParameter( +        httpReq.getQueryString(), HTTP_REDIRECT_SIGNATURE).substring(HTTP_REDIRECT_SIGNATURE_PARAM.length()), +        "UTF-8")); + +    final URIComparator comparator = new EaafUriCompare(serviceUrl); +      final InboundMessageInterface msg = -        bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, comparator); +        bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, +            comparator);      Assert.assertNotNull("PVP msg is null", msg); -    Assert.assertNotNull("RelayState is not null", msg.getRelayState()); +    Assert.assertNotNull("RelayState is 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()); +    Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg +        .getEntityID()); +    Assert.assertTrue("Wrong isVerified flag", msg.isVerified());    }    @Test    public void encodeRequestSuccess() throws MessageDecodingException, SecurityException,        MessageEncodingException, XMLParserException, UnmarshallingException, -      CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception { -    //build test data +      CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, +      Pvp2Exception { +    // build test data      final String serviceUrl = "http://testservice.org";      final String relayState = null;      final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( @@ -234,7 +502,7 @@ public class RedirectBindingTest {      bindingImpl.encodeRequest(httpReq, httpResp, authnReq, serviceUrl, relayState,          credentialProvider.getIdpMetaDataSigningCredential(), pendingReq); -    //validate +    // validate      Assert.assertEquals("http StatusCode", 302, httpResp.getStatus());      Assert.assertEquals("PVP msg is null", 0, httpResp.getContentLength()); @@ -246,33 +514,33 @@ public class RedirectBindingTest {      Assert.assertFalse("Location header is empty", locationHeader.isEmpty());      Assert.assertTrue("Wrong redirect URL", -        locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLREQ)); +        locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLREQ_PARAM)); -    final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLREQ, true); +    final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLREQ_PARAM, 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); +    final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG_PARAM, 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); +    final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE_PARAM, true);      Assert.assertNotNull("Saml signature null", samlSig);      Assert.assertFalse("Saml signature is empty", samlSig.isEmpty()); -    final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE, false); +    final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE_PARAM, false);      Assert.assertNull("RelayState parameter", respRelayState);    } -    @Test    public void encodeRequestSuccessEcdsa() throws MessageDecodingException, SecurityException,        MessageEncodingException, XMLParserException, UnmarshallingException, -      CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception { -    //build test data +      CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, +      Pvp2Exception { +    // build test data      final String serviceUrl = "http://testservice.org";      final String relayState = null;      final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( @@ -282,8 +550,8 @@ public class RedirectBindingTest {      bindingImpl.encodeRequest(httpReq, httpResp, authnReq, serviceUrl, relayState,          credentialProvider.getIdpAssertionSigningCredential(), pendingReq); -    //validate -    //validate +    // validate +    // validate      Assert.assertEquals("http StatusCode", 302, httpResp.getStatus());      Assert.assertEquals("PVP msg is null", 0, httpResp.getContentLength()); @@ -295,34 +563,34 @@ public class RedirectBindingTest {      Assert.assertFalse("Location header is empty", locationHeader.isEmpty());      Assert.assertTrue("Wrong redirect URL", -        locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLREQ)); +        locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLREQ_PARAM)); -    final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLREQ, true); +    final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLREQ_PARAM, 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); +    final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG_PARAM, 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); +    final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE_PARAM, true);      Assert.assertNotNull("Saml signature null", samlSig);      Assert.assertFalse("Saml signature is empty", samlSig.isEmpty()); -    final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE, false); +    final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE_PARAM, false);      Assert.assertNull("RelayState parameter", respRelayState); -    }    @Test    public void encodeRequestSuccessWithRelayState() throws MessageDecodingException, SecurityException,        MessageEncodingException, XMLParserException, UnmarshallingException, -      CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception { +      CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, +      Pvp2Exception { -    //build test data +    // build test data      final String serviceUrl = "http://testservice.org";      final String relayState = RandomStringUtils.randomAlphabetic(10);      final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( @@ -332,8 +600,7 @@ public class RedirectBindingTest {      bindingImpl.encodeRequest(httpReq, httpResp, authnReq, serviceUrl, relayState,          credentialProvider.getIdpMetaDataSigningCredential(), pendingReq); - -    //validate +    // validate      Assert.assertEquals("http StatusCode", 302, httpResp.getStatus());      Assert.assertEquals("PVP msg is null", 0, httpResp.getContentLength()); @@ -345,36 +612,36 @@ public class RedirectBindingTest {      Assert.assertFalse("Location header is empty", locationHeader.isEmpty());      Assert.assertTrue("Wrong redirect URL", -        locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLREQ)); +        locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLREQ_PARAM)); -    final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLREQ, true); +    final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLREQ_PARAM, 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); +    final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG_PARAM, 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); +    final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE_PARAM, true);      Assert.assertNotNull("Saml signature null", samlSig);      Assert.assertFalse("Saml signature is empty", samlSig.isEmpty()); -    final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE, false); +    final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE_PARAM, 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 { +      CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, +      Pvp2Exception { -    //build test data +    // build test data      final String serviceUrl = "http://testservice.org";      final String relayState = RandomStringUtils.randomAlphabetic(10);      final StatusResponseType authnReq = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream( @@ -384,8 +651,7 @@ public class RedirectBindingTest {      bindingImpl.encodeResponse(httpReq, httpResp, authnReq, serviceUrl, relayState,          credentialProvider.getIdpMetaDataSigningCredential(), pendingReq); - -    //validate +    // validate      Assert.assertEquals("http StatusCode", 302, httpResp.getStatus());      Assert.assertEquals("PVP msg is null", 0, httpResp.getContentLength()); @@ -397,23 +663,23 @@ public class RedirectBindingTest {      Assert.assertFalse("Location header is empty", locationHeader.isEmpty());      Assert.assertTrue("Wrong redirect URL", -        locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLRESP)); +        locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLRESP_PARM)); -    final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLRESP, true); +    final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLRESP_PARM, 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); +    final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG_PARAM, 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); +    final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE_PARAM, true);      Assert.assertNotNull("Saml signature null", samlSig);      Assert.assertFalse("Saml signature is empty", samlSig.isEmpty()); -    final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE, false); +    final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE_PARAM, false);      Assert.assertNotNull("RelayState parameter", respRelayState);      Assert.assertEquals("RelayState not match", relayState,          URLDecoder.decode(respRelayState, "UTF-8")); @@ -423,9 +689,10 @@ public class RedirectBindingTest {    @Test    public void encodeResponseSuccess() throws MessageDecodingException, SecurityException,        MessageEncodingException, XMLParserException, UnmarshallingException, -      CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception { +      CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, +      Pvp2Exception { -    //build test data +    // build test data      final String serviceUrl = "http://testservice.org";      final String relayState = null;      final StatusResponseType authnReq = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream( @@ -435,8 +702,7 @@ public class RedirectBindingTest {      bindingImpl.encodeResponse(httpReq, httpResp, authnReq, serviceUrl, relayState,          credentialProvider.getIdpMetaDataSigningCredential(), pendingReq); - -    //validate +    // validate      Assert.assertEquals("http StatusCode", 302, httpResp.getStatus());      Assert.assertEquals("PVP msg is null", 0, httpResp.getContentLength()); @@ -448,23 +714,23 @@ public class RedirectBindingTest {      Assert.assertFalse("Location header is empty", locationHeader.isEmpty());      Assert.assertTrue("Wrong redirect URL", -        locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLRESP)); +        locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLRESP_PARM)); -    final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLRESP, true); +    final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLRESP_PARM, 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); +    final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG_PARAM, 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); +    final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE_PARAM, true);      Assert.assertNotNull("Saml signature null", samlSig);      Assert.assertFalse("Saml signature is empty", samlSig.isEmpty()); -    final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE, false); +    final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE_PARAM, false);      Assert.assertNull("RelayState parameter", respRelayState);    } @@ -490,4 +756,45 @@ public class RedirectBindingTest {    } +  private String generateAuthnRequest(EaafX509Credential credential) throws Pvp2Exception, +      XMLParserException, UnmarshallingException { +    final MockHttpServletRequest intHttpReq = new MockHttpServletRequest(); +    final MockHttpServletResponse intHttpResp = new MockHttpServletResponse(); + +    final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( +        XMLObjectProviderRegistrySupport.getParserPool(), +        RedirectBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml")); +    authnReq.setIssueInstant(DateTime.now()); + +    bindingImpl.encodeRequest(intHttpReq, intHttpResp, authnReq, "http://testservice.org", null, +        credential, pendingReq); + +    Assert.assertEquals("http StatusCode", 302, intHttpResp.getStatus()); +    final String locationHeader = intHttpResp.getHeader("Location"); +    Assert.assertNotNull("Location header is null", locationHeader); +    return locationHeader.split("\\?")[1]; + +  } + +  private String generateResponse(EaafX509Credential credential) throws Pvp2Exception, +      XMLParserException, UnmarshallingException { +    new MockHttpServletRequest(); +    final MockHttpServletRequest intHttpReq = new MockHttpServletRequest(); +    final MockHttpServletResponse intHttpResp = new MockHttpServletResponse(); + +    final StatusResponseType authnReq = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream( +        XMLObjectProviderRegistrySupport.getParserPool(), +        RedirectBindingTest.class.getResourceAsStream("/data/Response_without_sig_1.xml")); +    authnReq.setIssueInstant(DateTime.now()); + +    bindingImpl.encodeResponse(intHttpReq, intHttpResp, authnReq, "http://testservice.org", null, +        credential, pendingReq); + +    Assert.assertEquals("http StatusCode", 302, intHttpResp.getStatus()); +    final String locationHeader = intHttpResp.getHeader("Location"); +    Assert.assertNotNull("Location header is null", locationHeader); +    return locationHeader.split("\\?")[1]; + +  } +  } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/SoapBindingTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/SoapBindingTest.java new file mode 100644 index 00000000..1125d30e --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/SoapBindingTest.java @@ -0,0 +1,214 @@ +package at.gv.egiz.eaaf.modules.pvp2.test.binding; + +import java.io.ByteArrayOutputStream; +import java.io.UnsupportedEncodingException; + +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.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.SoapBinding; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.EaafUriCompare; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; + +import org.joda.time.DateTime; +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.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.Marshaller; +import org.opensaml.core.xml.io.MarshallingException; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.saml.saml2.core.RequestAbstractType; +import org.opensaml.saml.saml2.core.StatusResponseType; +import org.opensaml.saml.saml2.metadata.SPSSODescriptor; +import org.opensaml.soap.soap11.Envelope; +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 net.shibboleth.utilities.java.support.logic.Constraint; +import net.shibboleth.utilities.java.support.net.URIComparator; +import net.shibboleth.utilities.java.support.xml.SerializeSupport; +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 SoapBindingTest { + +  @Autowired private SoapBinding bindingImpl; +  @Autowired private PvpMetadataResolverFactory metadataResolverFactory; +  @Autowired private DummyCredentialProvider credentialProvider; + +  protected MockHttpServletRequest httpReq; +  protected MockHttpServletResponse httpResp; +  protected IRequest pendingReq; + +  /** +   * JUnit class initializer. +   * +   * @throws Exception In case of an OpenSAML3 initialization error +   */ +  @BeforeClass +  public static void classInitializer() throws Exception { +    EaafOpenSaml3xInitializer.eaafInitialize(); + +  } + +  /** +   * Test initializer. +   * +   */ +  @Before +  public void initialize() { +    httpReq = new MockHttpServletRequest(); +    httpResp = new MockHttpServletResponse(); + +    pendingReq = new TestRequestImpl(); + +  } + +  @Test +  public void withoutSig() throws Pvp2Exception, MarshallingException, XMLParserException, UnmarshallingException { +    final String serviceUrl = "https://localhost/pvp2/post"; +    final IPvp2MetadataProvider metadataProvider = +        metadataResolverFactory.createMetadataProvider( +            "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); +    final URIComparator comparator = new EaafUriCompare(serviceUrl); + +    final RequestAbstractType payload = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( +        XMLObjectProviderRegistrySupport.getParserPool(), +        PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml")); +    payload.setIssueInstant(DateTime.now()); +    final Envelope enveloped = Saml2Utils.buildSoap11Envelope(payload); +    final Marshaller marshaller = Constraint.isNotNull( +        XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(enveloped), +        "SOAP Envelope marshaller not available"); +    final ByteArrayOutputStream arrayOut = new ByteArrayOutputStream(); +    SerializeSupport.writeNode(marshaller.marshall(enveloped), arrayOut); +    httpReq.setMethod("POST"); +    httpReq.setContentType("text/xml"); +    httpReq.setContent(arrayOut.toByteArray()); + + +    try { +      bindingImpl.decode(httpReq, httpResp, metadataProvider, +          SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); +      Assert.fail("Missing signature not detected"); + +    } catch (final Pvp2Exception e) { +      Assert.assertEquals("Wrong errorCode", "internal.pvp.02", e.getErrorId()); + +    } +  } + +  @Test +  public void wrongSignature() throws Pvp2Exception, MarshallingException, XMLParserException, UnmarshallingException { +    final String serviceUrl = "https://localhost/pvp2/post"; +    final IPvp2MetadataProvider metadataProvider = +        metadataResolverFactory.createMetadataProvider( +            "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); +    final URIComparator comparator = new EaafUriCompare(serviceUrl); + +    final RequestAbstractType payload = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( +        XMLObjectProviderRegistrySupport.getParserPool(), +        PostBindingTest.class.getResourceAsStream("/data/AuthRequest_with_sig_1.xml")); +    payload.setIssueInstant(DateTime.now()); +    final Envelope enveloped = Saml2Utils.buildSoap11Envelope(payload); +    final Marshaller marshaller = Constraint.isNotNull( +        XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(enveloped), +        "SOAP Envelope marshaller not available"); +    final ByteArrayOutputStream arrayOut = new ByteArrayOutputStream(); +    SerializeSupport.writeNode(marshaller.marshall(enveloped), arrayOut); +    httpReq.setMethod("POST"); +    httpReq.setContentType("text/xml"); +    httpReq.setContent(arrayOut.toByteArray()); + + +    try { +      bindingImpl.decode(httpReq, httpResp, metadataProvider, +          SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); +      Assert.fail("Missing signature not detected"); + +    } catch (final Pvp2Exception e) { +      Assert.assertEquals("Wrong errorCode", "internal.pvp.10", e.getErrorId()); + +    } +  } + +  @Test +  public void validSignature() throws Pvp2Exception, MarshallingException, XMLParserException, +      UnmarshallingException, CredentialsNotAvailableException { +    final String serviceUrl = "https://localhost/pvp2/post"; +    final IPvp2MetadataProvider metadataProvider = +        metadataResolverFactory.createMetadataProvider( +            "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); +    final URIComparator comparator = new EaafUriCompare(serviceUrl); + +    final RequestAbstractType payload = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( +        XMLObjectProviderRegistrySupport.getParserPool(), +        PostBindingTest.class.getResourceAsStream("/data/AuthRequest_with_sig_1.xml")); +    payload.setIssueInstant(DateTime.now()); +    final RequestAbstractType signedPayload = Saml2Utils.signSamlObject( +        payload, credentialProvider.getIdpMetaDataSigningCredential(), true); + +    final Envelope enveloped = Saml2Utils.buildSoap11Envelope(signedPayload); +    final Marshaller marshaller = Constraint.isNotNull( +        XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(enveloped), +        "SOAP Envelope marshaller not available"); +    final ByteArrayOutputStream arrayOut = new ByteArrayOutputStream(); +    SerializeSupport.writeNode(marshaller.marshall(enveloped), arrayOut); +    httpReq.setMethod("POST"); +    httpReq.setContentType("text/xml"); +    httpReq.setContent(arrayOut.toByteArray()); + + +    final InboundMessageInterface msg = +        bindingImpl.decode(httpReq, httpResp, metadataProvider, +            SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); + +    Assert.assertNotNull("Inbound msg is null", msg); +    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.assertTrue("Wrong isVerified flag", msg.isVerified()); + +  } + +  @Test +  public void encodeResponse() throws XMLParserException, UnmarshallingException, +      Pvp2Exception, CredentialsNotAvailableException, UnsupportedEncodingException { +    final String serviceUrl = "http://testservice.org"; + +    final StatusResponseType response = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream( +        XMLObjectProviderRegistrySupport.getParserPool(), +        PostBindingTest.class.getResourceAsStream("/data/Response_without_sig_1.xml")); + +    bindingImpl.encodeResponse(httpReq, httpResp, response, serviceUrl, null, +        credentialProvider.getIdpMetaDataSigningCredential(), pendingReq); + +    Assert.assertEquals("http StatusCode", 200, httpResp.getStatus()); +    Assert.assertNotNull("PVP msg is null", httpResp.getContentLength()); + +    Assert.assertEquals("ContentType", "text/xml", 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()); + +  } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataBuilderTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataBuilderTest.java new file mode 100644 index 00000000..2d46f102 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataBuilderTest.java @@ -0,0 +1,298 @@ +package at.gv.egiz.eaaf.modules.pvp2.test.metadata; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactoryConfigurationError; + +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpMetadataBuilder; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; + +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.MarshallingException; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.saml2.core.Attribute; +import org.opensaml.saml.saml2.core.NameIDType; +import org.opensaml.saml.saml2.metadata.ContactPerson; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml.saml2.metadata.Organization; +import org.opensaml.saml.saml2.metadata.RequestedAttribute; +import org.opensaml.saml.security.impl.SAMLSignatureProfileValidator; +import org.opensaml.security.SecurityException; +import org.opensaml.security.credential.Credential; +import org.opensaml.security.x509.BasicX509Credential; +import org.opensaml.xmlsec.signature.support.SignatureException; +import org.opensaml.xmlsec.signature.support.SignatureValidator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +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 MetadataBuilderTest { + +  @Autowired private PvpMetadataBuilder metadataBuilder; +  @Autowired private DummyCredentialProvider credentialProvider; + +  private static CertificateFactory fact; + +  /** +   * JUnit class initializer. +   * +   * @throws Exception In case of an OpenSAML3 initialization error +   */ +  @BeforeClass +  public static void classInitializer() throws Exception { +    EaafOpenSaml3xInitializer.eaafInitialize(); + +    fact = CertificateFactory.getInstance("X.509"); +  } + +  @Test +  public void buildIdpMetadata() throws CredentialsNotAvailableException, EaafException, +      SecurityException, TransformerFactoryConfigurationError, MarshallingException, +      TransformerException, ParserConfigurationException, IOException, SignatureException, +      XMLParserException, UnmarshallingException, CertificateException { + +    final IPvpMetadataBuilderConfiguration config = idpMetadataConfig(false, true); + +    //generate metadata +    final String metadata = metadataBuilder.buildPvpMetadata(config); + +    //validate +    final EntityDescriptor entity = validateMetadata(metadata); +    Assert.assertNotNull("IDPSSODescr. is null", entity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS)); +    Assert.assertNull("IDPSSODescr. is null", entity.getSPSSODescriptor(SAMLConstants.SAML20P_NS)); + +  } + +  @Test +  public void buildSpMetadata() throws CredentialsNotAvailableException, EaafException, +      SecurityException, TransformerFactoryConfigurationError, MarshallingException, +      TransformerException, ParserConfigurationException, IOException, SignatureException, +      XMLParserException, UnmarshallingException, CertificateException { + +    final IPvpMetadataBuilderConfiguration config = idpMetadataConfig(true, false); + +    //generate metadata +    final String metadata = metadataBuilder.buildPvpMetadata(config); + +    //validate +    final EntityDescriptor entity = validateMetadata(metadata); +    Assert.assertNull("IDPSSODescr. is null", entity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS)); +    Assert.assertNotNull("IDPSSODescr. is null", entity.getSPSSODescriptor(SAMLConstants.SAML20P_NS)); + +  } + +  @Test +  public void buildSpAndIdpMetadata() throws CredentialsNotAvailableException, EaafException, +      SecurityException, TransformerFactoryConfigurationError, MarshallingException, +      TransformerException, ParserConfigurationException, IOException, SignatureException, +      XMLParserException, UnmarshallingException, CertificateException { + +    final IPvpMetadataBuilderConfiguration config = idpMetadataConfig(true, true); + +    //generate metadata +    final String metadata = metadataBuilder.buildPvpMetadata(config); + +    //validate +    final EntityDescriptor entity = validateMetadata(metadata); +    Assert.assertNotNull("IDPSSODescr. is null", entity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS)); +    Assert.assertNotNull("IDPSSODescr. is null", entity.getSPSSODescriptor(SAMLConstants.SAML20P_NS)); + +  } + +  private EntityDescriptor validateMetadata(String metadata) throws UnsupportedEncodingException, +      XMLParserException, UnmarshallingException, SignatureException, CertificateException { +    Assert.assertNotNull("Metadata is null", metadata); +    Assert.assertFalse("Metadata is empty", metadata.isEmpty()); + +    final EntityDescriptor entity = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream( +        XMLObjectProviderRegistrySupport.getParserPool(), +        new ByteArrayInputStream(metadata.getBytes("UTF-8"))); + +    Assert.assertNotNull("Unmarshalling failed", entity); +    Assert.assertNotNull("EntityId is null", entity.getEntityID()); + +    Assert.assertNotNull("Signature is null", entity.getSignature()); +    final SAMLSignatureProfileValidator sigValidator = new SAMLSignatureProfileValidator(); +    sigValidator.validate(entity.getSignature()); + +    final Credential cred = new BasicX509Credential((X509Certificate) fact.generateCertificate( +        MetadataResolverTest.class.getResourceAsStream("/data/junit_metadata_sig_cert.crt"))); +    SignatureValidator.validate(entity.getSignature(), cred); + +    return entity; +  } + +  private IPvpMetadataBuilderConfiguration idpMetadataConfig(boolean buildSpInfos, boolean buildIdpInfos) { +    return new IPvpMetadataBuilderConfiguration() { + +      @Override +      public boolean wantAuthnRequestSigned() { +        return true; +      } + +      @Override +      public boolean wantAssertionSigned() { +        return true; +      } + +      @Override +      public String getSpSloSoapBindingUrl() { +        return RandomStringUtils.randomAlphabetic(10); + +      } + +      @Override +      public String getSpSloRedirectBindingUrl() { +        return RandomStringUtils.randomAlphabetic(10); + +      } + +      @Override +      public String getSpSloPostBindingUrl() { +        return RandomStringUtils.randomAlphabetic(10); +      } + +      @Override +      public Collection<RequestedAttribute> getSpRequiredAttributes() { +        return null; +      } + +      @Override +      public String getSpNameForLogging() { +        return RandomStringUtils.randomAlphabetic(10); +      } + +      @Override +      public String getSpAssertionConsumerServiceRedirectBindingUrl() { +        return RandomStringUtils.randomAlphabetic(10); +      } + +      @Override +      public String getSpAssertionConsumerServicePostBindingUrl() { +        return RandomStringUtils.randomAlphabetic(10); +      } + +      @Override +      public List<String> getSpAllowedNameIdTypes() { +        return Arrays.asList(NameIDType.PERSISTENT); +      } + +      @Override +      public Credential getRequestorResponseSigningCredentials() throws CredentialsNotAvailableException { +        return credentialProvider.getIdpAssertionSigningCredential(); +      } + +      @Override +      public Organization getOrgansiationInformation() { +        return null; +      } + +      @Override +      public int getMetadataValidUntil() { +        return 10; +      } + +      @Override +      public EaafX509Credential getMetadataSigningCredentials() throws CredentialsNotAvailableException { +        return credentialProvider.getIdpMetaDataSigningCredential(); +      } + +      @Override +      public String getIdpWebSsoRedirectBindingUrl() { +        return RandomStringUtils.randomAlphabetic(10); +      } + +      @Override +      public String getIdpWebSsoPostBindingUrl() { +        return RandomStringUtils.randomAlphabetic(10); +      } + +      @Override +      public String getIdpSloRedirectBindingUrl() { +        return RandomStringUtils.randomAlphabetic(10); +      } + +      @Override +      public String getIdpSloPostBindingUrl() { +        return RandomStringUtils.randomAlphabetic(10); +      } + +      @Override +      public List<String> getIdpPossibleNameIdTypes() { +        return Arrays.asList(NameIDType.PERSISTENT); +      } + +      @Override +      public List<Attribute> getIdpPossibleAttributes() { +        return null; +      } + +      @Override +      public String getEntityID() { +        return RandomStringUtils.randomAlphabetic(10); +      } + +      @Override +      public String getEntityFriendlyName() { +        return RandomStringUtils.randomAlphabetic(10); +      } + +      @Override +      public Credential getEncryptionCredentials() throws CredentialsNotAvailableException { +        return credentialProvider.getIdpAssertionSigningCredential(); +      } + +      @Override +      public List<ContactPerson> getContactPersonInformation() { +        return null; +      } + +      @Override +      public boolean buildSpSsoDescriptor() { +        return buildSpInfos; +      } + +      @Override +      public boolean buildIdpSsoDescriptor() { +        return buildIdpInfos; +      } + +      @Override +      public boolean buildEntitiesDescriptorAsRootElement() { +        return false; +      } +    }; +  } +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataResolverTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataResolverTest.java new file mode 100644 index 00000000..f40fbc74 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataResolverTest.java @@ -0,0 +1,725 @@ +package at.gv.egiz.eaaf.modules.pvp2.test.metadata; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.transform.TransformerException; + +import at.gv.egiz.eaaf.core.impl.utils.IHttpClientFactory; +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.Pvp2InternalErrorException; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.PvpEntityCategoryFilter; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.SchemaValidationFilter; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.SimpleMetadataSignatureVerificationFilter; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; + +import org.apache.commons.io.IOUtils; +import org.joda.time.DateTime; +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.ConfigurationService; +import org.opensaml.core.criterion.EntityIdCriterion; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.MarshallingException; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.criterion.EntityRoleCriterion; +import org.opensaml.saml.metadata.resolver.filter.MetadataFilter; +import org.opensaml.saml.metadata.resolver.filter.MetadataFilterChain; +import org.opensaml.saml.metadata.resolver.filter.impl.RequiredValidUntilFilter; +import org.opensaml.saml.metadata.resolver.impl.PredicateRoleDescriptorResolver; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml.saml2.metadata.RequestedAttribute; +import org.opensaml.saml.saml2.metadata.SPSSODescriptor; +import org.opensaml.saml.security.impl.MetadataCredentialResolver; +import org.opensaml.security.credential.Credential; +import org.opensaml.security.credential.UsageType; +import org.opensaml.security.criteria.UsageCriterion; +import org.opensaml.security.x509.BasicX509Credential; +import org.opensaml.xmlsec.SignatureValidationConfiguration; +import org.opensaml.xmlsec.SignatureValidationParameters; +import org.opensaml.xmlsec.keyinfo.KeyInfoCredentialResolver; +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.SignatureValidationParametersCriterion; +import org.springframework.beans.factory.annotation.Autowired; +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 net.shibboleth.utilities.java.support.component.ComponentInitializationException; +import net.shibboleth.utilities.java.support.resolver.CriteriaSet; +import net.shibboleth.utilities.java.support.resolver.ResolverException; +import net.shibboleth.utilities.java.support.xml.SerializeSupport; +import net.shibboleth.utilities.java.support.xml.XMLParserException; +import okhttp3.HttpUrl; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ "/spring/test_eaaf_pvp.beans.xml" }) +@TestPropertySource(locations = { "/config/config_1.props" }) +public class MetadataResolverTest { + +  private static MockWebServer mockWebServer; +  private static HttpUrl mockServerUrl; + +  @Autowired +  private PvpMetadataResolverFactory metadataResolverFactory; +  @Autowired +  private IHttpClientFactory httpClientFactory; +  @Autowired private DummyCredentialProvider credentialProvider; + +  /** +   * JUnit class initializer. +   * +   * @throws Exception In case of an OpenSAML3 initialization error +   */ +  @BeforeClass +  public static void classInitializer() throws Exception { +    EaafOpenSaml3xInitializer.eaafInitialize(); +    mockWebServer = new MockWebServer(); +    mockServerUrl = mockWebServer.url("/sp/metadata"); + +  } + +  /** +   * Single test initializer. +   * +   */ +  @Before +  public void testInitializer() { + +  } + +  @Test +  public void wrongSchema() { +    final List<MetadataFilter> filterList = new ArrayList<>(); +    filterList.add(new SchemaValidationFilter(true)); + +    final MetadataFilterChain filterChain = new MetadataFilterChain(); +    filterChain.setFilters(filterList); + +    try { +      metadataResolverFactory.createMetadataProvider( +          "classpath:/data/pvp_metadata_wrong_schema.xml", +          filterChain, "jUnit test", null); +      Assert.fail("Wrong XML Schema not detected"); + +    } catch (final Pvp2MetadataException e) { +      Assert.assertEquals("Wrong ErrorCode", "internal.pvp.08", e.getErrorId()); +      Assert.assertNotNull("params null", e.getParams()); +      Assert.assertEquals("Params size", 2, e.getParams().length); +      Assert.assertEquals("Param[0] wrong", +          "classpath:/data/pvp_metadata_wrong_schema.xml", e.getParams()[0]); + +    } + +  } + +  @Test +  public void simpleClasspathMetadataWithoutSigValidation() +      throws Pvp2MetadataException, ComponentInitializationException, ResolverException, +      Pvp2InternalErrorException { +    final List<MetadataFilter> filterList = new ArrayList<>(); +    filterList.add(new SchemaValidationFilter(true)); + +    final MetadataFilterChain filterChain = new MetadataFilterChain(); +    filterChain.setFilters(filterList); + +    final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( +        "classpath:/data/pvp_metadata_wrong_sig.xml", +        filterChain, "jUnit test", null); + +    final EntityDescriptor entityIdNotExists = mdResolver.getEntityDescriptor( +        "https://demo.egiz.gv.at/notExtist/"); +    Assert.assertNull("No EntityDescripter", entityIdNotExists); + +    final EntityDescriptor entityId = mdResolver.getEntityDescriptor( +        "https://demo.egiz.gv.at/demoportal_demologin/"); +    Assert.assertNotNull("No EntityDescripter", entityId); + +    Assert.assertNotNull("Metadata provider is null", mdResolver); +    final MetadataCredentialResolver resolver = createKeyInfoResolver(mdResolver); + +    final CriteriaSet criteriaSet = new CriteriaSet(); +    criteriaSet.add(new EntityIdCriterion("https://demo.egiz.gv.at/demoportal_demologin/")); +    criteriaSet.add(new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME)); +    criteriaSet.add(new UsageCriterion(UsageType.SIGNING)); +    final SignatureValidationParameters sigValCrit = new SignatureValidationParameters(); +    sigValCrit.setBlacklistedAlgorithms( +        ConfigurationService.get(SignatureValidationConfiguration.class) +            .getBlacklistedAlgorithms()); +    sigValCrit.setSignatureTrustEngine( +        TrustEngineFactory.getSignatureKnownKeysTrustEngine(mdResolver)); +    criteriaSet.add(new SignatureValidationParametersCriterion(sigValCrit)); + +    final Iterable<Credential> keyInfos = resolver.resolve(criteriaSet); +    Assert.assertNotNull("KeyInfos null", keyInfos); + +  } + +  @Test +  public void noCredentials() { +    final String metadataUrl = "classpath:/data/pvp_metadata_moaid_test.xml"; + +    final List<BasicX509Credential> credentials = new ArrayList<>(); + +    final List<MetadataFilter> filterList = new ArrayList<>(); +    filterList.add(new SchemaValidationFilter(true)); + +    filterList.add(new SimpleMetadataSignatureVerificationFilter( +        credentials, +        metadataUrl)); + +    final MetadataFilterChain filterChain = new MetadataFilterChain(); +    filterChain.setFilters(filterList); + +    try { +      metadataResolverFactory.createMetadataProvider( +          metadataUrl, +          filterChain, "jUnit test", null); +      Assert.fail("Untrusted signature not detected"); + +    } catch (final Pvp2MetadataException e) { +      Assert.assertEquals("Wrong errorCode", "internal.pvp.07", e.getErrorId()); + +    } + +  } + +  @Test +  public void wrongCredentials() throws CertificateException { +    final String metadataUrl = "classpath:/data/pvp_metadata_moaid_test.xml"; + +    final List<BasicX509Credential> credentials = new ArrayList<>(); +    final CertificateFactory fact = CertificateFactory.getInstance("X.509"); +    final BasicX509Credential credential = new BasicX509Credential((X509Certificate) fact.generateCertificate( +        MetadataResolverTest.class.getResourceAsStream("/data/assertion_sig_cert.crt"))); +    credentials.add(credential); + +    final List<MetadataFilter> filterList = new ArrayList<>(); +    filterList.add(new SchemaValidationFilter(true)); + +    filterList.add(new SimpleMetadataSignatureVerificationFilter( +        credentials, +        metadataUrl)); + +    final MetadataFilterChain filterChain = new MetadataFilterChain(); +    filterChain.setFilters(filterList); + +    try { +      metadataResolverFactory.createMetadataProvider( +          metadataUrl, +          filterChain, "jUnit test", null); +      Assert.fail("Untrusted signature not detected"); + +    } catch (final Pvp2MetadataException e) { +      Assert.assertEquals("Wrong errorCode", "internal.pvp.07", e.getErrorId()); + +    } + +  } + +  @Test +  public void validCredentialsInvalidSig() throws CertificateException, Pvp2MetadataException, +      ResolverException { +    final String metadataUrl = "classpath:/data/pvp_metadata_moaid_test.xml"; + +    final List<BasicX509Credential> credentials = new ArrayList<>(); +    final CertificateFactory fact = CertificateFactory.getInstance("X.509"); +    credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( +        MetadataResolverTest.class.getResourceAsStream("/data/assertion_sig_cert.crt")))); +    credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( +        MetadataResolverTest.class.getResourceAsStream("/data/metadata_sig_cert.crt")))); + +    final List<MetadataFilter> filterList = new ArrayList<>(); +    filterList.add(new SchemaValidationFilter(true)); + +    filterList.add(new SimpleMetadataSignatureVerificationFilter( +        credentials, +        metadataUrl)); + +    final MetadataFilterChain filterChain = new MetadataFilterChain(); +    filterChain.setFilters(filterList); +    try { +      metadataResolverFactory.createMetadataProvider( +          metadataUrl, +          filterChain, "jUnit test", null); +      Assert.fail("Untrusted signature not detected"); + +    } catch (final Pvp2MetadataException e) { +      Assert.assertEquals("Wrong errorCode", "internal.pvp.07", e.getErrorId()); + +    } + +  } + +  @Test +  public void metadataSignatureValidCredentials() throws CertificateException, Pvp2MetadataException, +      ResolverException, XMLParserException, UnmarshallingException, SamlSigningException, +      CredentialsNotAvailableException, MarshallingException, TransformerException, IOException { + +    final String metadataUrl = "classpath:/data/pvp_metadata_valid.xml"; + +    final List<BasicX509Credential> credentials = new ArrayList<>(); +    final CertificateFactory fact = CertificateFactory.getInstance("X.509"); +    credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( +        MetadataResolverTest.class.getResourceAsStream("/data/metadata_sig_cert.crt")))); +    credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( +        MetadataResolverTest.class.getResourceAsStream("/data/assertion_sig_cert.crt")))); +    credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( +        MetadataResolverTest.class.getResourceAsStream("/data/junit_metadata_sig_cert.crt")))); + +    final List<MetadataFilter> filterList = new ArrayList<>(); +    filterList.add(new SchemaValidationFilter(true)); +    filterList.add(new SimpleMetadataSignatureVerificationFilter( +        credentials, +        metadataUrl)); +    filterList.add(new PvpEntityCategoryFilter(true)); + +    final MetadataFilterChain filterChain = new MetadataFilterChain(); +    filterChain.setFilters(filterList); + +    final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( +        metadataUrl, +        filterChain, "jUnit test", httpClientFactory.getHttpClient()); + +    final EntityDescriptor entityIdNotExists = mdResolver.getEntityDescriptor( +        "https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/metadata"); +    Assert.assertNotNull("No EntityDescripter", entityIdNotExists); + +  } + +  @Test +  public void metadataSignatureValidCredentialsSecond() throws CertificateException, Pvp2MetadataException, +      ResolverException, XMLParserException, UnmarshallingException, SamlSigningException, +      CredentialsNotAvailableException, MarshallingException, TransformerException, IOException { + +    final EntityDescriptor metadata = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream( +        XMLObjectProviderRegistrySupport.getParserPool(), +        MetadataResolverTest.class.getResourceAsStream("/data/pvp_metadata_valid_with_entityCategory.xml")); +    metadata.setValidUntil(DateTime.now().plusDays(1)); +    metadata.setSignature(null); +    Saml2Utils.signSamlObject(metadata, credentialProvider.getIdpMetaDataSigningCredential(), true); +    final Element metadataElement = XMLObjectSupport.marshall(metadata); +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(SerializeSupport.nodeToString(metadataElement)) +        .setHeader("Content-Type", "text/html;charset=utf-8")); + +    final List<BasicX509Credential> credentials = new ArrayList<>(); +    final CertificateFactory fact = CertificateFactory.getInstance("X.509"); +    credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( +        MetadataResolverTest.class.getResourceAsStream("/data/metadata_sig_cert.crt")))); +    credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( +        MetadataResolverTest.class.getResourceAsStream("/data/assertion_sig_cert.crt")))); +    credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( +        MetadataResolverTest.class.getResourceAsStream("/data/junit_metadata_sig_cert.crt")))); + +    final List<MetadataFilter> filterList = new ArrayList<>(); +    filterList.add(new SchemaValidationFilter(true)); +    filterList.add(new SimpleMetadataSignatureVerificationFilter( +        credentials, +        mockServerUrl.url().toString())); +    filterList.add(new PvpEntityCategoryFilter(true)); + +    final MetadataFilterChain filterChain = new MetadataFilterChain(); +    filterChain.setFilters(filterList); + +    final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( +        mockServerUrl.url().toString(), +        filterChain, "jUnit test", httpClientFactory.getHttpClient()); + + + +    final EntityDescriptor descr = mdResolver.getEntityDescriptor( +        "https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/metadata"); +    Assert.assertNotNull("No EntityDescripter", descr); + +    final List<RequestedAttribute> reqAttr = descr.getSPSSODescriptor(SAMLConstants.SAML20P_NS) +        .getAttributeConsumingServices().get(0).getRequestAttributes(); +    Assert.assertNotNull("Req. attributes are null", reqAttr); +    Assert.assertEquals("# of req. attributes", 20, reqAttr.size()); + +  } + +  @Test +  public void metadataSignatureValidCredentialsThird() throws CertificateException, Pvp2MetadataException, +      ResolverException, XMLParserException, UnmarshallingException, SamlSigningException, +      CredentialsNotAvailableException, MarshallingException, TransformerException, IOException { + +    final EntityDescriptor metadata = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream( +        XMLObjectProviderRegistrySupport.getParserPool(), +        MetadataResolverTest.class.getResourceAsStream("/data/pvp_metadata_valid_with_entityCategory_egov.xml")); +    metadata.setValidUntil(DateTime.now().plusDays(1)); +    metadata.setSignature(null); +    Saml2Utils.signSamlObject(metadata, credentialProvider.getIdpMetaDataSigningCredential(), true); +    final Element metadataElement = XMLObjectSupport.marshall(metadata); +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(SerializeSupport.nodeToString(metadataElement)) +        .setHeader("Content-Type", "text/html;charset=utf-8")); + +    final List<BasicX509Credential> credentials = new ArrayList<>(); +    final CertificateFactory fact = CertificateFactory.getInstance("X.509"); +    credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( +        MetadataResolverTest.class.getResourceAsStream("/data/metadata_sig_cert.crt")))); +    credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( +        MetadataResolverTest.class.getResourceAsStream("/data/assertion_sig_cert.crt")))); +    credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( +        MetadataResolverTest.class.getResourceAsStream("/data/junit_metadata_sig_cert.crt")))); + +    final List<MetadataFilter> filterList = new ArrayList<>(); +    filterList.add(new SchemaValidationFilter(true)); +    filterList.add(new SimpleMetadataSignatureVerificationFilter( +        credentials, +        mockServerUrl.url().toString())); +    filterList.add(new PvpEntityCategoryFilter(true)); + +    final MetadataFilterChain filterChain = new MetadataFilterChain(); +    filterChain.setFilters(filterList); + +    final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( +        mockServerUrl.url().toString(), +        filterChain, "jUnit test", httpClientFactory.getHttpClient()); + + + +    final EntityDescriptor descr = mdResolver.getEntityDescriptor( +        "https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/metadata"); +    Assert.assertNotNull("No EntityDescripter", descr); + +    final List<RequestedAttribute> reqAttr = descr.getSPSSODescriptor(SAMLConstants.SAML20P_NS) +        .getAttributeConsumingServices().get(0).getRequestAttributes(); +    Assert.assertNotNull("Req. attributes are null", reqAttr); +    Assert.assertEquals("# of req. attributes", 9, reqAttr.size()); + +  } + +  @Test +  public void metadataExpired() throws CertificateException, Pvp2MetadataException, +      ResolverException, XMLParserException, UnmarshallingException, SamlSigningException, +      CredentialsNotAvailableException, MarshallingException, TransformerException, IOException { + +    final EntityDescriptor metadata = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream( +        XMLObjectProviderRegistrySupport.getParserPool(), +        MetadataResolverTest.class.getResourceAsStream("/data/pvp_metadata_valid.xml")); +    metadata.setValidUntil(DateTime.now().minusDays(2)); +    metadata.setSignature(null); +    Saml2Utils.signSamlObject(metadata, credentialProvider.getIdpMetaDataSigningCredential(), true); +    final Element metadataElement = XMLObjectSupport.marshall(metadata); + +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(SerializeSupport.nodeToString(metadataElement)) +        .setHeader("Content-Type", "text/html;charset=utf-8")); + +    final List<BasicX509Credential> credentials = new ArrayList<>(); +    final CertificateFactory fact = CertificateFactory.getInstance("X.509"); +    credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( +        MetadataResolverTest.class.getResourceAsStream("/data/metadata_sig_cert.crt")))); +    credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( +        MetadataResolverTest.class.getResourceAsStream("/data/assertion_sig_cert.crt")))); +    credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( +        MetadataResolverTest.class.getResourceAsStream("/data/junit_metadata_sig_cert.crt")))); + +    final List<MetadataFilter> filterList = new ArrayList<>(); +    filterList.add(new SchemaValidationFilter(true)); +    filterList.add(new SimpleMetadataSignatureVerificationFilter( +        credentials, +        mockServerUrl.url().toString())); +    filterList.add(new RequiredValidUntilFilter()); +    filterList.add(new PvpEntityCategoryFilter(false)); + + +    final MetadataFilterChain filterChain = new MetadataFilterChain(); +    filterChain.setFilters(filterList); + +    try { +      metadataResolverFactory.createMetadataProvider( +          mockServerUrl.url().toString(), +          filterChain, "jUnit test", httpClientFactory.getHttpClient()); +      Assert.fail("Expired metadata not detected"); + +    } catch (final Pvp2MetadataException e) { +      Assert.assertEquals("Wrong errorCode", "internal.pvp.09", e.getErrorId()); + +    } + + +  } + +  @Test +  public void simpleClasspathMetadataWithoutSigValidationMoaidTwoSigKeys() +      throws Pvp2MetadataException, ComponentInitializationException, ResolverException, +      Pvp2InternalErrorException { +    final List<MetadataFilter> filterList = new ArrayList<>(); +    filterList.add(new SchemaValidationFilter(true)); + +    final MetadataFilterChain filterChain = new MetadataFilterChain(); +    filterChain.setFilters(filterList); + +    final String entityIdToResolve = "https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata"; + +    final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( +        "classpath:/data/pvp_metadata_moaid_test.xml", +        filterChain, "jUnit test", null); + +    final EntityDescriptor entityIdNotExists = mdResolver.getEntityDescriptor( +        "https://demo.egiz.gv.at/notExtist/"); +    Assert.assertNull("No EntityDescripter", entityIdNotExists); + +    final EntityDescriptor entityId = mdResolver.getEntityDescriptor(entityIdToResolve); +    Assert.assertNotNull("No EntityDescripter", entityId); + +    Assert.assertNotNull("Metadata provider is null", mdResolver); +    final MetadataCredentialResolver resolver = createKeyInfoResolver(mdResolver); + +    final CriteriaSet sigCriteriaSet = new CriteriaSet(); +    sigCriteriaSet.add(new EntityIdCriterion(entityIdToResolve)); +    sigCriteriaSet.add(new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME)); +    sigCriteriaSet.add(new UsageCriterion(UsageType.SIGNING)); +    final SignatureValidationParameters sigValCrit = new SignatureValidationParameters(); +    sigValCrit.setBlacklistedAlgorithms( +        ConfigurationService.get(SignatureValidationConfiguration.class) +            .getBlacklistedAlgorithms()); +    sigValCrit.setSignatureTrustEngine( +        TrustEngineFactory.getSignatureKnownKeysTrustEngine(mdResolver)); +    sigCriteriaSet.add(new SignatureValidationParametersCriterion(sigValCrit)); + +    final Iterable<Credential> singingKeyInfos = resolver.resolve(sigCriteriaSet); +    Assert.assertNotNull("Signing KeyInfos null", singingKeyInfos); +    Assert.assertTrue("First Credential resolved", singingKeyInfos.iterator().hasNext()); +    Assert.assertTrue("Second Credential resolved", singingKeyInfos.iterator().hasNext()); + +    final CriteriaSet encCriteriaSet = new CriteriaSet(); +    encCriteriaSet.add(new EntityIdCriterion(entityIdToResolve)); +    encCriteriaSet.add(new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME)); +    encCriteriaSet.add(new UsageCriterion(UsageType.ENCRYPTION)); +    final Iterable<Credential> encKeyInfos = resolver.resolve(encCriteriaSet); +    Assert.assertNotNull("Encryption KeyInfos null", encKeyInfos); +    Assert.assertTrue("No Credential resolved", encKeyInfos.iterator().hasNext()); + +  } + +  @Test +  public void httpMetadataLoading() throws UnsupportedEncodingException, +      IOException, ResolverException, Pvp2MetadataException { + +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(new String(IOUtils.toByteArray( +            MetadataResolverTest.class.getResourceAsStream( +                "/data/pvp_metadata_moaid_test.xml")), "UTF-8")) +        .setHeader("Content-Type", "text/xml")); + +    final List<MetadataFilter> filterList = new ArrayList<>(); +    filterList.add(new SchemaValidationFilter(true)); + +    final MetadataFilterChain filterChain = new MetadataFilterChain(); +    filterChain.setFilters(filterList); + +    final String entityIdToResolve = "https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata"; + +    final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( +        mockServerUrl.url().toString(), +        filterChain, "jUnit test", httpClientFactory.getHttpClient()); + +    final EntityDescriptor entityIdNotExists = mdResolver.getEntityDescriptor( +        "https://demo.egiz.gv.at/notExtist/"); +    Assert.assertNull("No EntityDescripter", entityIdNotExists); + +    final EntityDescriptor entityId = mdResolver.getEntityDescriptor(entityIdToResolve); +    Assert.assertNotNull("No EntityDescripter", entityId); + +  } + +  @Test +  public void httpMetadataLoadingRefeshFailed() throws UnsupportedEncodingException, +      IOException, ResolverException, Pvp2MetadataException { + +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(new String(IOUtils.toByteArray( +            MetadataResolverTest.class.getResourceAsStream( +                "/data/pvp_metadata_moaid_test.xml")), "UTF-8")) +        .setHeader("Content-Type", "text/xml")); + +    final List<MetadataFilter> filterList = new ArrayList<>(); +    filterList.add(new SchemaValidationFilter(true)); + +    final MetadataFilterChain filterChain = new MetadataFilterChain(); +    filterChain.setFilters(filterList); + +    final String entityIdToResolve = "https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata"; + +    final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( +        mockServerUrl.url().toString(), +        filterChain, "jUnit test", httpClientFactory.getHttpClient()); + +    final EntityDescriptor entityIdNotExists = mdResolver.getEntityDescriptor( +        "https://demo.egiz.gv.at/notExtist/"); +    Assert.assertNull("No EntityDescripter", entityIdNotExists); + +    final EntityDescriptor entityId = mdResolver.getEntityDescriptor(entityIdToResolve); +    Assert.assertNotNull("No EntityDescripter", entityId); + +    final DateTime lastRefreshSucess = mdResolver.getLastSuccessfulRefresh(); + +    try { +      mdResolver.refresh(); +      Assert.fail("Refesh possible without available metadata"); + +    } catch (final ResolverException e) { +      Assert.assertFalse("Wrong Refesh success flag", mdResolver.wasLastRefreshSuccess()); +      Assert.assertEquals("Wrong refresh success date", lastRefreshSucess, mdResolver +          .getLastSuccessfulRefresh()); + +    } + +  } + +  @Test +  public void httpMetadataLoadingWithRefeshSuccess() throws UnsupportedEncodingException, +      IOException, ResolverException, Pvp2MetadataException { + +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(new String(IOUtils.toByteArray( +            MetadataResolverTest.class.getResourceAsStream( +                "/data/pvp_metadata_moaid_test.xml")), "UTF-8")) +        .setHeader("Content-Type", "text/xml")); + +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(new String(IOUtils.toByteArray( +            MetadataResolverTest.class.getResourceAsStream( +                "/data/pvp_metadata_moaid_test.xml")), "UTF-8")) +        .setHeader("Content-Type", "text/xml")); + +    final List<MetadataFilter> filterList = new ArrayList<>(); +    filterList.add(new SchemaValidationFilter(true)); + +    final MetadataFilterChain filterChain = new MetadataFilterChain(); +    filterChain.setFilters(filterList); + +    final String entityIdToResolve = "https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata"; + +    final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( +        mockServerUrl.url().toString(), +        filterChain, "jUnit test", httpClientFactory.getHttpClient()); + +    final EntityDescriptor entityIdNotExists = mdResolver.getEntityDescriptor( +        "https://demo.egiz.gv.at/notExtist/"); +    Assert.assertNull("No EntityDescripter", entityIdNotExists); + +    final EntityDescriptor entityId = mdResolver.getEntityDescriptor(entityIdToResolve); +    Assert.assertNotNull("No EntityDescripter", entityId); + +    final DateTime lastRefresh = mdResolver.getLastRefresh(); + +    // refresh metadata +    mdResolver.refresh(); + +    Assert.assertTrue("Refresh not sucessful", mdResolver.wasLastRefreshSuccess()); +    Assert.assertTrue("Wrong last refresh date", lastRefresh.isBefore(mdResolver.getLastRefresh())); + +  } + +  @Test +  public void httpMetadataLoadingWithoutHttpClient() throws UnsupportedEncodingException, +      IOException, ResolverException, Pvp2MetadataException { + +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(new String(IOUtils.toByteArray( +            MetadataResolverTest.class.getResourceAsStream( +                "/data/pvp_metadata_moaid_test.xml")), "UTF-8")) +        .setHeader("Content-Type", "text/xml")); + +    final List<MetadataFilter> filterList = new ArrayList<>(); +    filterList.add(new SchemaValidationFilter(true)); + +    final MetadataFilterChain filterChain = new MetadataFilterChain(); +    filterChain.setFilters(filterList); + +    try { +      metadataResolverFactory.createMetadataProvider( +          mockServerUrl.url().toString(), +          filterChain, "jUnit test", null); +      Assert.fail("No httpclient not detected"); + +    } catch (final Pvp2MetadataException e) { +      Assert.assertEquals("Wrong errorCode", "internal.pvp.09", e.getErrorId()); +      Assert.assertNotNull("No error params", e.getParams()); +      Assert.assertEquals("Wrong params size", 2, e.getParams().length); + +    } +  } + +  @Test +  public void httpMetadataLoadingWrongUrl() throws UnsupportedEncodingException, +      IOException, ResolverException, Pvp2MetadataException { + +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(new String(IOUtils.toByteArray( +            MetadataResolverTest.class.getResourceAsStream( +                "/data/pvp_metadata_moaid_test.xml")), "UTF-8")) +        .setHeader("Content-Type", "text/xml")); + +    final List<MetadataFilter> filterList = new ArrayList<>(); +    filterList.add(new SchemaValidationFilter(true)); + +    final MetadataFilterChain filterChain = new MetadataFilterChain(); +    filterChain.setFilters(filterList); + +    try { +      metadataResolverFactory.createMetadataProvider( +          "http://127.0.0.1/notexist", +          filterChain, "jUnit test", httpClientFactory.getHttpClient()); +      Assert.fail("No httpclient not detected"); + +    } catch (final Pvp2MetadataException e) { +      Assert.assertEquals("Wrong errorCode", "internal.pvp.09", e.getErrorId()); +      Assert.assertNotNull("No error params", e.getParams()); +      Assert.assertEquals("Wrong params size", 2, e.getParams().length); + +    } + +  } + +  private MetadataCredentialResolver createKeyInfoResolver(IPvp2MetadataProvider mdResolver) +      throws ComponentInitializationException { +    final List<KeyInfoProvider> keyInfoProvider = new ArrayList<>(); +    keyInfoProvider.add(new DSAKeyValueProvider()); +    keyInfoProvider.add(new RSAKeyValueProvider()); +    keyInfoProvider.add(new InlineX509DataProvider()); +    final KeyInfoCredentialResolver keyInfoCredentialResolver = new BasicProviderKeyInfoCredentialResolver( +        keyInfoProvider); + +    final PredicateRoleDescriptorResolver roleDescriptorResolver = new PredicateRoleDescriptorResolver( +        mdResolver); +    roleDescriptorResolver.setRequireValidMetadata(true); +    roleDescriptorResolver.initialize(); + +    final MetadataCredentialResolver resolver = new MetadataCredentialResolver(); +    resolver.setRoleDescriptorResolver(roleDescriptorResolver); +    resolver.setKeyInfoCredentialResolver(keyInfoCredentialResolver); +    resolver.initialize(); + +    return resolver; +  } +} 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 index 74b805ba..164b8807 100644 --- 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 @@ -5,4 +5,8 @@ key.metadata.pass=password  key.sig.alias=sig  key.sig.pass=password  key.enc.alias= -key.enc.pass=
\ No newline at end of file +key.enc.pass= + +client.http.connection.timeout.socket=2 +client.http.connection.timeout.connection=2 +client.http.connection.timeout.request=2
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_withsig_expired.b64 b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_withsig_expired.b64 new file mode 100644 index 00000000..f02ce2ea --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_withsig_expired.b64 @@ -0,0 +1 @@ +PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDJwOkF1dGhuUmVxdWVzdCB4bWxuczpzYW1sMnA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgQXNzZXJ0aW9uQ29uc3VtZXJTZXJ2aWNlSW5kZXg9IjAiIERlc3RpbmF0aW9uPSJodHRwczovL2VpZGFzLXRlc3QuYm1pLmd2LmF0L21zX2Nvbm5lY3Rvci9wdnAvcG9zdCIgSUQ9Il9lZDJjZDQ0NjNiODJkYzYwOTI0MzM5YjEwZWIyNzQ4OCIgSXNQYXNzaXZlPSJmYWxzZSIgSXNzdWVJbnN0YW50PSIyMDIwLTAyLTA0VDA2OjQ4OjU4LjA3NFoiIFByb3ZpZGVyTmFtZT0iT3BlbklEIENvbm5lY3QgRGVtbyIgVmVyc2lvbj0iMi4wIiB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiPjxzYW1sMjpJc3N1ZXIgeG1sbnM6c2FtbDI9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iIEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOm5hbWVpZC1mb3JtYXQ6ZW50aXR5Ij5odHRwczovL2RlbW8uZWdpei5ndi5hdC9kZW1vcG9ydGFsX21vYWlkLTIuMC9zcC9laWRhcy9tZXRhZGF0YTwvc2FtbDI6SXNzdWVyPjxkczpTaWduYXR1cmUgeG1sbnM6ZHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPjxkczpTaWduZWRJbmZvPjxkczpDYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+PGRzOlNpZ25hdHVyZU1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZHNpZy1tb3JlI3JzYS1zaGEyNTYiLz48ZHM6UmVmZXJlbmNlIFVSST0iI19lZDJjZDQ0NjNiODJkYzYwOTI0MzM5YjEwZWIyNzQ4OCI+PGRzOlRyYW5zZm9ybXM+PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNlbnZlbG9wZWQtc2lnbmF0dXJlIi8+PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyI+PGVjOkluY2x1c2l2ZU5hbWVzcGFjZXMgeG1sbnM6ZWM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIgUHJlZml4TGlzdD0ieHMiLz48L2RzOlRyYW5zZm9ybT48L2RzOlRyYW5zZm9ybXM+PGRzOkRpZ2VzdE1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jI3NoYTI1NiIvPjxkczpEaWdlc3RWYWx1ZT5aSEZ0UVpYeXBTbFhrK3ZYdGZlSDVMWEdNcTE2MUpmUHdFUHBPVFhUSzlRPTwvZHM6RGlnZXN0VmFsdWU+PC9kczpSZWZlcmVuY2U+PC9kczpTaWduZWRJbmZvPjxkczpTaWduYXR1cmVWYWx1ZT5CSFFHeXpMZE5rb2dGZmt5T0FxVnBTRXh1NXhRaWxvVUs5L01GejBTM01LZnRkaDVtTXVaT0tBSUU1SUMrKzlPS25UbUlncUVNdWJVKzAvTEVobTUwUk1oZGtxYUFFWG02Y2xKYmlaOHBvT0pPd09sWlhQVWtub0J4NkZxRi9MNThqTFV6ZlluNEh0OUtCOGVQV2djU2FVR3lpMHB4OEdzMzNJUDd3eGF2bnhGYUMvSERpZkN0UytaZzJ5QVpJR2lnQksxcXIrUTMweWIrNWZEQmprU3pWMWJGb2NKdHY2cDJhSXlUMTNnb2x6N0FuK3JSWVloVnd5WENBY25CdHJjQTREbmNpWVVnTVNLQTRTR1hLNExyZ1RTdjFXUHJEdlJmWkVLMk9xL2JEMHE0MWF1T1d4VVkzK2x2T2pJYUI3YnRobURiSVJPbmhaWW1rMDlPSFZJMVE9PTwvZHM6U2lnbmF0dXJlVmFsdWU+PGRzOktleUluZm8+PGRzOlg1MDlEYXRhPjxkczpYNTA5Q2VydGlmaWNhdGU+TUlJREt6Q0NBaE1DQkZyeEtPNHdEUVlKS29aSWh2Y05BUUVMQlFBd1dqRUxNQWtHQTFVRUJoTUNRVlF4RFRBTEJnTlZCQW9NQkVWSApTVm94R0RBV0JnTlZCQXNNRDJSbGJXOHVaV2RwZWk1bmRpNWhkREVpTUNBR0ExVUVBd3daVFU5QkxVbEVJRWxFVUNBb1ZHVnpkQzFXClpYSnphVzl1S1RBZUZ3MHhPREExTURnd05ETTBOVFJhRncweU1UQXhNekV3TkRNME5UUmFNRm94Q3pBSkJnTlZCQVlUQWtGVU1RMHcKQ3dZRFZRUUtEQVJGUjBsYU1SZ3dGZ1lEVlFRTERBOWtaVzF2TG1WbmFYb3VaM1l1WVhReElqQWdCZ05WQkFNTUdVMVBRUzFKUkNCSgpSRkFnS0ZSbGMzUXRWbVZ5YzJsdmJpa3dnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDYUZucW9hWW9xClVwdGVuZW1DNkZpVkRnNUYyaEVqcGppeDgrb3c2LzZRaFVsMmNQT1MwdXdaSGFJdndUL1JWYko5Q1BkaWw2KzExcWFDUGZaK0ZvWSsKTStrZTdUUmQyUlMxRHFGYmUxS0MwaW1FbndlbXlMUXJZZTVQbTdETmNhWS9rSFRUcStrMGVlR2JZSDBVL0lvcHlpMFZ1TjVPV2w0RgpWZzQ1cGY3a25oWGthaW1JdGRqbkNYbktjWU05MW1tbHRDZjZURGdVcno3VVM3UG1ndmlubmhmQmdkSVRBVDRHUnI0ZWhsaVQrL2p0CjFPekhFeVdSSGFuQkdJcFhOZVpOcXhnbnBuR3RhRGg0Slp1WVI4cWZIK0dSSzZkdFcyemllajZyR0lpVUVsR1ZDa1hzb2hneE1OenEKbldlRDlKVDgreXlwMVhabHlRZitJeGhoRVNRTEFnTUJBQUV3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUlGZWpBRlFlcGFFbC9rQwpWTHZpZE1SK01YcTVMQ0dIdGhVaUk2ZURUUVorSDdsWmRIbGo1NDdYd0VkWDE1YjZNZDNoN2VTSjRod2xmVjRnby8wRmFvTFB6dlZxCml0d3RZWTVodHl3QjNCNlpWMzRFeWk2QzU5R2wzNFhyVjhDV3hINEtLd0xzVkFqQXkrL3AvWGgwcTJwelNCa2VPQ2h6Qk1Ca2pteWMKMlVlNE1FS2RMOWd1enA2K1ljL0hML3BoSEFLWWFwa1Z5Rnd2c2RxV09neVJ6eEFISU5rbzhFeEltTU1CM3hCNWE1MmtmcUxjdWk1TwpmekVoandMRkphR0JNbUZDbUZHR09Vd3RJdmwvNlpRMkxMek9FOStnaVZLOVdzSWdIMTFQdStlalBGQWJYZjhjZjRvV2hiQWZUa2l5CjRqcFhycDc3SlhGUlNEV2RkYjB5ZVBjPTwvZHM6WDUwOUNlcnRpZmljYXRlPjwvZHM6WDUwOURhdGE+PC9kczpLZXlJbmZvPjwvZHM6U2lnbmF0dXJlPjxzYW1sMnA6RXh0ZW5zaW9ucz48ZWlkOlJlcXVlc3RlZEF0dHJpYnV0ZXMgeG1sbnM6ZWlkPSJodHRwOi8vZWlkLmd2LmF0L2VJRC9hdHRyaWJ1dGVzL3NhbWwtZXh0ZW5zaW9ucyI+PGVpZDpSZXF1ZXN0ZWRBdHRyaWJ1dGUgRnJpZW5kbHlOYW1lPSJFSUQtU0VDVE9SLUZPUi1JREVOVElGSUVSIiBOYW1lPSJ1cm46b2lkOjEuMi40MC4wLjEwLjIuMS4xLjI2MS4zNCIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDp1cmkiIGlzUmVxdWlyZWQ9InRydWUiPjxlaWQ6QXR0cmlidXRlVmFsdWUgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeHNpOnR5cGU9InhzOnN0cmluZyI+dXJuOnB1YmxpY2lkOmd2LmF0OmNkaWQrQkY8L2VpZDpBdHRyaWJ1dGVWYWx1ZT48L2VpZDpSZXF1ZXN0ZWRBdHRyaWJ1dGU+PC9laWQ6UmVxdWVzdGVkQXR0cmlidXRlcz48L3NhbWwycDpFeHRlbnNpb25zPjxzYW1sMnA6TmFtZUlEUG9saWN5IEFsbG93Q3JlYXRlPSJ0cnVlIiBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpuYW1laWQtZm9ybWF0OnBlcnNpc3RlbnQiLz48c2FtbDJwOlJlcXVlc3RlZEF1dGhuQ29udGV4dCBDb21wYXJpc29uPSJtaW5pbXVtIj48c2FtbDI6QXV0aG5Db250ZXh0Q2xhc3NSZWYgeG1sbnM6c2FtbDI9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iPmh0dHA6Ly9laWRhcy5ldXJvcGEuZXUvTG9BL2xvdzwvc2FtbDI6QXV0aG5Db250ZXh0Q2xhc3NSZWY+PC9zYW1sMnA6UmVxdWVzdGVkQXV0aG5Db250ZXh0PjxzYW1sMnA6U2NvcGluZz48c2FtbDJwOlJlcXVlc3RlcklEPmh0dHBzOi8vZGVtby5lZ2l6Lmd2LmF0L2RlbW9wb3J0YWwtb3BlbklEX2RlbW88L3NhbWwycDpSZXF1ZXN0ZXJJRD48L3NhbWwycDpTY29waW5nPjwvc2FtbDJwOkF1dGhuUmVxdWVzdD4
\ No newline at end of file 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 index 3607cbc4..2683742e 100644 --- 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 @@ -1,6 +1,6 @@  <?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> +	<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>  	<saml2p:Status>  		<saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>  	</saml2p:Status> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/assertion_sig_cert.crt b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/assertion_sig_cert.crt new file mode 100644 index 00000000..b53c558d --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/assertion_sig_cert.crt @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE----- +MIIBbTCCARKgAwIBAgIEXjF+qTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +HhcNMjAwMTI5MTI0NjMzWhcNMjcwMTI4MTI0NjMzWjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASRt7gZRrr4rSEE7Q922oKQJF+mlkwC +LZnv8ZzHtH54s4VdyQFIBjQF1PPf9PTn+5tid8QJehZPndcoeD7J8fPJMAoGCCqG +SM49BAMCA0kAMEYCIQDFUO0owvqMVRO2FmD+vb8mqJBpWCE6Cl5pEHaygTa5LwIh +ANsmjI2azWiTSFjb7Ou5fnCfbeiJUP0s66m8qS4rYl9L +-----END CERTIFICATE----- diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_metadata_sig_cert.crt b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_metadata_sig_cert.crt new file mode 100644 index 00000000..b544c194 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_metadata_sig_cert.crt @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC+jCCAeKgAwIBAgIEXjF+fTANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJB +VDENMAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxETAPBgNVBAMMCE1ldGFk +YXRhMB4XDTIwMDEyOTEyNDU0OVoXDTI2MDEyODEyNDU0OVowPzELMAkGA1UEBhMC +QVQxDTALBgNVBAcMBEVHSVoxDjAMBgNVBAoMBWpVbml0MREwDwYDVQQDDAhNZXRh +ZGF0YTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK230G3dxNbNlSYA +O5Kx/Js0aBAgxMt7q9m+dA35fK/dOvF/GjrqjWsMCnax+no9gLnq6x0gXiJclz6H +rp/YDOfLrJjMpNL/r0FWT947vbnEj7eT8TdY5d6Yi8AZulZmjiCI5nbZh2zwrP4+ +WqRroLoPhXQj8mDyp26M4xHBBUhLMRc2HV4S+XH4uNZ/vTmb8vBg31XGHCY33gl7 +/KA54JNGxJdN8Dxv6yHYsm91ZfVrX39W0iYLUNhUCkolwuQmjDVfrExM8BTLIONb +f+erJoCm3A9ghZyDYRQ/e69/UEUqDa6XOzykr88INkQscEiAXCDS+EBPMpKo+t3l +PIA9r7kCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAh/2mg4S03bdZy1OVtEAudBT9 +YZb9OF34hxPtNbkB/V04wSIg1d4TBr5KDhV7CdiUOxPZzHpS8LUCgfGX306FB6NX +zh/b67uTOPaE72AB4VIT/Np0fsM7k5WhG9k9NoprIGiqCz2lXcfpZiT+LtSO1vWS +YI87wR9KOSWjcw/5i5qZIAJuwvLCQj5JtUsmrhHK75222J3TJf4dS/gfN4xfY2rW +9vcXtH6//8WdWp/zx9V7Z1ZsDb8TDKtBCEGuFDgVeU5ScKtVq8qRoUKD3Ve76cZi +purO3KrRrVAuZP2EfLkZdHEHqe8GPigNnZ5kTn8V2VJ3iRAQ73hpJRR98tFd0A== +-----END CERTIFICATE----- diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/metadata_sig_cert.crt b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/metadata_sig_cert.crt new file mode 100644 index 00000000..61aa137b --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/metadata_sig_cert.crt @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc= +-----END CERTIFICATE-----
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_junit_keystore.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_junit_keystore.xml new file mode 100644 index 00000000..52549a88 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_junit_keystore.xml @@ -0,0 +1,125 @@ +<?xml version="1.0" encoding="UTF-8"?> +<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_2e23ca9b2ba4dc9eef15187830d07ff0" entityID="https://demo.egiz.gv.at/demoportal_demologin/" validUntil="2020-02-05T06:41:42.966Z"> +	<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="#_2e23ca9b2ba4dc9eef15187830d07ff0"> +				<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/2001/04/xmlenc#sha256"/> +				<ds:DigestValue>Jy/c0ZvVJSfWzSoAcxDx/o+T5W61vvNJNqTFz2o+ILc=</ds:DigestValue> +			</ds:Reference> +		</ds:SignedInfo> +		<ds:SignatureValue>chMxIdwrPvr78j3oTtgS7udbydy9kye1bbeQ4jm2GeFKUfxvJqY+vt9MjVnWFeR4c16gd80BjZJ6xxD5i5Ifci3YtxeKSxq0ttH/xZYEhJZkD/0NrGUhSvNV9zuLAz3uGk/LJ+2JxRq7dbnW4n9MtGuYhea8OW9/Pr1xI1KyskQS76NZDsGjjfnFWbFXahLoQZULU4Ke3SfZVqLATTn0J34RZnjNH3QieY3LhRzOVu/I5yeZtnLgUS6dg0Gab9DA/pdNFaC632iaE5QCXJmhgpqkjbkayO9e8N93YGFjbszhU1Kws5OUGjXjfCZwezLeOUZoKEfo5c+4+zEaTrEQjg==</ds:SignatureValue> +		<ds:KeyInfo> +			<ds:X509Data> +				<ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> +			</ds:X509Data> +		</ds:KeyInfo> +	</ds:Signature> +	<md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> +		<md:KeyDescriptor use="signing"> +			<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> +				<ds:X509Data> +					<ds:X509Certificate>MIIC+jCCAeKgAwIBAgIEXjF+fTANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJB +VDENMAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxETAPBgNVBAMMCE1ldGFk +YXRhMB4XDTIwMDEyOTEyNDU0OVoXDTI2MDEyODEyNDU0OVowPzELMAkGA1UEBhMC +QVQxDTALBgNVBAcMBEVHSVoxDjAMBgNVBAoMBWpVbml0MREwDwYDVQQDDAhNZXRh +ZGF0YTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK230G3dxNbNlSYA +O5Kx/Js0aBAgxMt7q9m+dA35fK/dOvF/GjrqjWsMCnax+no9gLnq6x0gXiJclz6H +rp/YDOfLrJjMpNL/r0FWT947vbnEj7eT8TdY5d6Yi8AZulZmjiCI5nbZh2zwrP4+ +WqRroLoPhXQj8mDyp26M4xHBBUhLMRc2HV4S+XH4uNZ/vTmb8vBg31XGHCY33gl7 +/KA54JNGxJdN8Dxv6yHYsm91ZfVrX39W0iYLUNhUCkolwuQmjDVfrExM8BTLIONb +f+erJoCm3A9ghZyDYRQ/e69/UEUqDa6XOzykr88INkQscEiAXCDS+EBPMpKo+t3l +PIA9r7kCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAh/2mg4S03bdZy1OVtEAudBT9 +YZb9OF34hxPtNbkB/V04wSIg1d4TBr5KDhV7CdiUOxPZzHpS8LUCgfGX306FB6NX +zh/b67uTOPaE72AB4VIT/Np0fsM7k5WhG9k9NoprIGiqCz2lXcfpZiT+LtSO1vWS +YI87wR9KOSWjcw/5i5qZIAJuwvLCQj5JtUsmrhHK75222J3TJf4dS/gfN4xfY2rW +9vcXtH6//8WdWp/zx9V7Z1ZsDb8TDKtBCEGuFDgVeU5ScKtVq8qRoUKD3Ve76cZi +purO3KrRrVAuZP2EfLkZdHEHqe8GPigNnZ5kTn8V2VJ3iRAQ73hpJRR98tFd0A==</ds:X509Certificate> +				</ds:X509Data> +                <ds:X509Data> +                  <ds:X509Certificate>MIIBbTCCARKgAwIBAgIEXjF+qTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +HhcNMjAwMTI5MTI0NjMzWhcNMjcwMTI4MTI0NjMzWjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASRt7gZRrr4rSEE7Q922oKQJF+mlkwC +LZnv8ZzHtH54s4VdyQFIBjQF1PPf9PTn+5tid8QJehZPndcoeD7J8fPJMAoGCCqG +SM49BAMCA0kAMEYCIQDFUO0owvqMVRO2FmD+vb8mqJBpWCE6Cl5pEHaygTa5LwIh +ANsmjI2azWiTSFjb7Ou5fnCfbeiJUP0s66m8qS4rYl9L +                </ds:X509Certificate> +              </ds:X509Data> +			</ds:KeyInfo> +		</md:KeyDescriptor> +		<md:KeyDescriptor use="encryption"> +			<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> +				<ds:X509Data> +					<ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> +				</ds:X509Data> +			</ds:KeyInfo> +		</md:KeyDescriptor> +		<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat> +		<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/post" index="0" isDefault="true"/> +		<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/redirect" index="1"/> +		<md:AttributeConsumingService index="0" isDefault="true"> +			<md:ServiceName xml:lang="en">Default Service</md:ServiceName> +			<md:RequestedAttribute 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" isRequired="true"/> +			<md:RequestedAttribute 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" isRequired="true"/> +			<md:RequestedAttribute 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" isRequired="true"/> +			<md:RequestedAttribute 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" isRequired="true"/> +			<md:RequestedAttribute 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" isRequired="true"/> +			<md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.76" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +			<md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-FULL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.84" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +			<md:RequestedAttribute FriendlyName="MANDATE-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.68" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +			<md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN" Name="urn:oid:1.2.40.0.10.2.1.1.261.100" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +			<md:RequestedAttribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> +			<md:RequestedAttribute 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" isRequired="true"/> +			<md:RequestedAttribute FriendlyName="MANDATE-TYPE-OID" Name="urn:oid:1.2.40.0.10.2.1.1.261.106" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +			<md:RequestedAttribute FriendlyName="EID-IDENTITY-LINK" Name="urn:oid:1.2.40.0.10.2.1.1.261.38" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +			<md:RequestedAttribute FriendlyName="EID-CITIZEN-QAA-EIDAS-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.108" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> +		</md:AttributeConsumingService> +	</md:SPSSODescriptor> +	<md:Organization> +		<md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName> +		<md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName> +		<md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL> +	</md:Organization> +	<md:ContactPerson contactType="technical"> +		<md:Company>E-Government Innovationszentrum</md:Company> +		<md:GivenName>Lenz</md:GivenName> +		<md:SurName>Thomas</md:SurName> +		<md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress> +		<md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber> +	</md:ContactPerson> +</md:EntityDescriptor> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_moaid_test.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_moaid_test.xml new file mode 100644 index 00000000..f1fbd9be --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_moaid_test.xml @@ -0,0 +1,135 @@ +<?xml version="1.0" encoding="UTF-8"?> +<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_2e23ca9b2ba4dc9eef15187830d07ff0" entityID="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata" validUntil="2020-02-05T06:41:42.966Z"> +	<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="#_2e23ca9b2ba4dc9eef15187830d07ff0"> +				<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/2001/04/xmlenc#sha256"/> +				<ds:DigestValue>Jy/c0ZvVJSfWzSoAcxDx/o+T5W61vvNJNqTFz2o+ILc=</ds:DigestValue> +			</ds:Reference> +		</ds:SignedInfo> +		<ds:SignatureValue>chMxIdwrPvr78j3oTtgS7udbydy9kye1bbeQ4jm2GeFKUfxvJqY+vt9MjVnWFeR4c16gd80BjZJ6xxD5i5Ifci3YtxeKSxq0ttH/xZYEhJZkD/0NrGUhSvNV9zuLAz3uGk/LJ+2JxRq7dbnW4n9MtGuYhea8OW9/Pr1xI1KyskQS76NZDsGjjfnFWbFXahLoQZULU4Ke3SfZVqLATTn0J34RZnjNH3QieY3LhRzOVu/I5yeZtnLgUS6dg0Gab9DA/pdNFaC632iaE5QCXJmhgpqkjbkayO9e8N93YGFjbszhU1Kws5OUGjXjfCZwezLeOUZoKEfo5c+4+zEaTrEQjg==</ds:SignatureValue> +		<ds:KeyInfo> +			<ds:X509Data> +				<ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> +			</ds:X509Data> +		</ds:KeyInfo> +	</ds:Signature> +	<md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> +		<md:KeyDescriptor use="signing"> +			<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> +				<ds:X509Data> +					<ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> +				</ds:X509Data> +        <ds:X509Data> +          <ds:X509Certificate>MIIEFTCCAv2gAwIBAgIJAI/HXXgQpJtFMA0GCSqGSIb3DQEBCwUAMGQxCzAJBgNVBAYTAkFUMRMw +            EQYDVQQIEwpTb21lLVN0YXRlMQ0wCwYDVQQHEwRHcmF6MQ0wCwYDVQQKEwRFR0laMSIwIAYDVQQD +            ExlNT0EtSUQgSURQIChUZXN0LVZlcnNpb24pMB4XDTE0MDEyMTA4NDAxOFoXDTE1MDEyMTA4NDAx +            OFowZDELMAkGA1UEBhMCQVQxEzARBgNVBAgTClNvbWUtU3RhdGUxDTALBgNVBAcTBEdyYXoxDTAL +            BgNVBAoTBEVHSVoxIjAgBgNVBAMTGU1PQS1JRCBJRFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqG +            SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFETzd0nLV2P4pUGnlLKj3V+MZ4bUyYkNK5NnkzB0PO8hm +            tsrdg+HSNsnPiU5KvD26tFpxq9lfibZcAp9JHFqjA/capOHcTDhYkTvJcSdaKJzttTPy4wivTbRu +            y+ocK9jjz6g8BFvP9wQ5/k2AwFaqj0SeJt0jJTn4CZ8XMNozA2hwkQA2heuMtOl24Ie9PRC3/Af7 +            utV2CNfV2MysGHIxazsZDIgFF+5/nybyR1yiIxKb0BYDh3gbNdyH5uLVBHOP4hvzQN5Z1xc/cdzq +            lzKn/4v6HJraNn00xLzK6nrG6gB6HvDok2l8T1Cc7f8I+sNlO2aM8rY4hGSGCfhiL6IFAgMBAAGj +            gckwgcYwHQYDVR0OBBYEFKG3LzuPtAGCXUPTw3fo9dtsS9wWMIGWBgNVHSMEgY4wgYuAFKG3LzuP +            tAGCXUPTw3fo9dtsS9wWoWikZjBkMQswCQYDVQQGEwJBVDETMBEGA1UECBMKU29tZS1TdGF0ZTEN +            MAsGA1UEBxMER3JhejENMAsGA1UEChMERUdJWjEiMCAGA1UEAxMZTU9BLUlEIElEUCAoVGVzdC1W +            ZXJzaW9uKYIJAI/HXXgQpJtFMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAME3wzEi +            UAcF2pCDtMMJzX4IDhSkWNuvWtSMMy8Vgtcc2t570teIKh+qNKQWZyX3QFVE6ovDABg3ZUhn780l +            G4/t6aMOUEeGg4udl7l0QRBRbdd+9oc0Aw5dQqku02AQ6wQd695PLj+F0GeA7cdef90aLPu6Rwa5 +            z5BiKpReJZoul3NpjQXz7A1IslZOlIhEDcFUlBSn/+QfLOeNDKurvPT0OzUGSGfrv0AoniNHc/fz +            lfyRmgFbzAVHedU5cIxcE0yHtEKFjFSVwtGng9rTJpoOoY4pvGvAHlw6GEgO+HwFukPDtnvY8vi/ +            cfmNJhb06H+6mmHz929Bk4HuHoQj8X8= +          </ds:X509Certificate> +        </ds:X509Data> +			</ds:KeyInfo> +		</md:KeyDescriptor> +		<md:KeyDescriptor use="encryption"> +			<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> +				<ds:X509Data> +					<ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> +				</ds:X509Data> +			</ds:KeyInfo> +		</md:KeyDescriptor> +		<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat> +		<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/post" index="0" isDefault="true"/> +		<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/redirect" index="1"/> +		<md:AttributeConsumingService index="0" isDefault="true"> +			<md:ServiceName xml:lang="en">Default Service</md:ServiceName> +			<md:RequestedAttribute 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" isRequired="true"/> +			<md:RequestedAttribute 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" isRequired="true"/> +			<md:RequestedAttribute 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" isRequired="true"/> +			<md:RequestedAttribute 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" isRequired="true"/> +			<md:RequestedAttribute 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" isRequired="true"/> +			<md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.76" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +			<md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-FULL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.84" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +			<md:RequestedAttribute FriendlyName="MANDATE-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.68" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +			<md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN" Name="urn:oid:1.2.40.0.10.2.1.1.261.100" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +			<md:RequestedAttribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> +			<md:RequestedAttribute 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" isRequired="true"/> +			<md:RequestedAttribute FriendlyName="MANDATE-TYPE-OID" Name="urn:oid:1.2.40.0.10.2.1.1.261.106" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +			<md:RequestedAttribute FriendlyName="EID-IDENTITY-LINK" Name="urn:oid:1.2.40.0.10.2.1.1.261.38" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +			<md:RequestedAttribute FriendlyName="EID-CITIZEN-QAA-EIDAS-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.108" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> +		</md:AttributeConsumingService> +	</md:SPSSODescriptor> +	<md:Organization> +		<md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName> +		<md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName> +		<md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL> +	</md:Organization> +	<md:ContactPerson contactType="technical"> +		<md:Company>E-Government Innovationszentrum</md:Company> +		<md:GivenName>Lenz</md:GivenName> +		<md:SurName>Thomas</md:SurName> +		<md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress> +		<md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber> +	</md:ContactPerson> +</md:EntityDescriptor> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid.xml new file mode 100644 index 00000000..d5855d43 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?><md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_ee52efc823faa4334d93d1a787fb2c24" entityID="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/metadata" validUntil="2020-02-05T10:58:10.849Z"><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="#_ee52efc823faa4334d93d1a787fb2c24"><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/2001/04/xmlenc#sha256"/><ds:DigestValue>O4rfKjKlNT+p4hNR5NtYkrnu/AATuSGxsKxn3C4+VhA=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>G8jkWHT0baEviEcd4Xd/+u/WMyVK1H/Jdy2y1YE1nv+61zrm3rEgzuW70kGGdpxGt3enWznYem9jwkckXVu21QWZa9XDICu1MIrnpWs37Iz2ph3uHqvfYLS3awEs4GzinB6sLNM+2xEgmv/hXjSFIeOsCAIxdAsA7Btbq6iIx0xIknVZHlp3pWBzXAFvsizWx7QFldaMhzsfZ1HgSd7EdqFoMEjhEr6FHsppj2NjKjqNVg4AGHFp+GkzxXcXHTcojwigIx4qFli4B6EdqGPvC1oX1fBy09iYxeA0maI/qwLsWLfShrtNE3eFi7aQblTkTaK1cFO8q5P8u61yKtv3wg==</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"><md:KeyDescriptor use="signing"><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:X509Data><ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:KeyDescriptor use="encryption"><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:X509Data><ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat><md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/post" index="0" isDefault="true"/><md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/redirect" index="1"/><md:AttributeConsumingService index="0" isDefault="true"><md:ServiceName xml:lang="en">Default Service</md:ServiceName><md:RequestedAttribute FriendlyName="MANDATOR-NATURAL-PERSON-BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.261.82" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute 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" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATOR-NATURAL-PERSON-FAMILY-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.80" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute 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" isRequired="false"/><md:RequestedAttribute 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" isRequired="false"/><md:RequestedAttribute FriendlyName="EID-CCS-URL" Name="urn:oid:1.2.40.0.10.2.1.1.261.64" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATE-PROF-REP-OID" Name="urn:oid:1.2.40.0.10.2.1.1.261.86" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-FULL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.84" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATE-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.68" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="ENC-BPK-LIST" Name="urn:oid:1.2.40.0.10.2.1.1.261.22" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="EID-SIGNER-CERTIFICATE" Name="urn:oid:1.2.40.0.10.2.1.1.261.66" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATE-PROF-REP-DESCRIPTION" Name="urn:oid:1.2.40.0.10.2.1.1.261.88" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="BPK-LIST" Name="urn:oid:1.2.40.0.10.2.1.1.261.28" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATE-REFERENCE-VALUE" Name="urn:oid:1.2.40.0.10.2.1.1.261.90" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATOR-NATURAL-PERSON-ENC-BPK-LIST" Name="urn:oid:1.2.40.0.10.2.1.1.261.72" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute 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" isRequired="false"/><md:RequestedAttribute 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" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.76" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATOR-NATURAL-PERSON-BPK" Name="urn:oid:1.2.40.0.10.2.1.1.261.98" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATOR-NATURAL-PERSON-BPK-LIST" Name="urn:oid:1.2.40.0.10.2.1.1.261.73" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN" Name="urn:oid:1.2.40.0.10.2.1.1.261.100" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute 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" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATOR-NATURAL-PERSON-GIVEN-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.78" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="EID-E-ID-TOKEN" Name="urn:oid:1.2.40.0.10.2.1.1.261.39" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATE-TYPE-OID" Name="urn:oid:1.2.40.0.10.2.1.1.261.106" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="EID-CITIZEN-QAA-EIDAS-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.108" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="EID-IDENTITY-STATUS-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.109" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/></md:AttributeConsumingService></md:SPSSODescriptor><md:Organization><md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName><md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName><md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL></md:Organization><md:ContactPerson contactType="technical"><md:Company>E-Government Innovationszentrum</md:Company><md:GivenName>Lenz</md:GivenName><md:SurName>Thomas</md:SurName><md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress><md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber></md:ContactPerson></md:EntityDescriptor>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid_with_entityCategory.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid_with_entityCategory.xml new file mode 100644 index 00000000..54ad2b03 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid_with_entityCategory.xml @@ -0,0 +1,107 @@ +<?xml version="1.0" encoding="UTF-8"?> +<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_ee52efc823faa4334d93d1a787fb2c24" entityID="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/metadata" validUntil="2020-02-05T10:58:10.849Z"> +  <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="#_ee52efc823faa4334d93d1a787fb2c24"> +        <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/2001/04/xmlenc#sha256"/> +        <ds:DigestValue>O4rfKjKlNT+p4hNR5NtYkrnu/AATuSGxsKxn3C4+VhA=</ds:DigestValue> +      </ds:Reference> +    </ds:SignedInfo> +    <ds:SignatureValue>G8jkWHT0baEviEcd4Xd/+u/WMyVK1H/Jdy2y1YE1nv+61zrm3rEgzuW70kGGdpxGt3enWznYem9jwkckXVu21QWZa9XDICu1MIrnpWs37Iz2ph3uHqvfYLS3awEs4GzinB6sLNM+2xEgmv/hXjSFIeOsCAIxdAsA7Btbq6iIx0xIknVZHlp3pWBzXAFvsizWx7QFldaMhzsfZ1HgSd7EdqFoMEjhEr6FHsppj2NjKjqNVg4AGHFp+GkzxXcXHTcojwigIx4qFli4B6EdqGPvC1oX1fBy09iYxeA0maI/qwLsWLfShrtNE3eFi7aQblTkTaK1cFO8q5P8u61yKtv3wg==</ds:SignatureValue> +    <ds:KeyInfo> +      <ds:X509Data> +        <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> +      </ds:X509Data> +    </ds:KeyInfo> +  </ds:Signature> +  <md:Extensions> +    <mdattr:EntityAttributes xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute"> +      <saml2:Attribute xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Name="http://macedir.org/entity-category" 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">http://www.ref.gv.at/ns/names/agiz/pvp/citizentoken</saml2:AttributeValue> +      </saml2:Attribute> +    </mdattr:EntityAttributes> +  </md:Extensions> +  <md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> +    <md:KeyDescriptor use="signing"> +      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> +        <ds:X509Data> +          <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> +        </ds:X509Data> +      </ds:KeyInfo> +    </md:KeyDescriptor> +    <md:KeyDescriptor use="encryption"> +      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> +        <ds:X509Data> +          <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> +        </ds:X509Data> +      </ds:KeyInfo> +    </md:KeyDescriptor> +    <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat> +    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/post" index="0" isDefault="true"/> +    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/redirect" index="1"/> +    <md:AttributeConsumingService index="0" isDefault="true"> +      <md:ServiceName xml:lang="en">Default Service</md:ServiceName> +      <md:RequestedAttribute FriendlyName="MANDATOR-NATURAL-PERSON-BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.261.82" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +    </md:AttributeConsumingService> +  </md:SPSSODescriptor> +  <md:Organization> +    <md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName> +    <md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName> +    <md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL> +  </md:Organization> +  <md:ContactPerson contactType="technical"> +    <md:Company>E-Government Innovationszentrum</md:Company> +    <md:GivenName>Lenz</md:GivenName> +    <md:SurName>Thomas</md:SurName> +    <md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress> +    <md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber> +  </md:ContactPerson> +</md:EntityDescriptor> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid_with_entityCategory_egov.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid_with_entityCategory_egov.xml new file mode 100644 index 00000000..cb680e82 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid_with_entityCategory_egov.xml @@ -0,0 +1,107 @@ +<?xml version="1.0" encoding="UTF-8"?> +<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_ee52efc823faa4334d93d1a787fb2c24" entityID="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/metadata" validUntil="2020-02-05T10:58:10.849Z"> +  <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="#_ee52efc823faa4334d93d1a787fb2c24"> +        <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/2001/04/xmlenc#sha256"/> +        <ds:DigestValue>O4rfKjKlNT+p4hNR5NtYkrnu/AATuSGxsKxn3C4+VhA=</ds:DigestValue> +      </ds:Reference> +    </ds:SignedInfo> +    <ds:SignatureValue>G8jkWHT0baEviEcd4Xd/+u/WMyVK1H/Jdy2y1YE1nv+61zrm3rEgzuW70kGGdpxGt3enWznYem9jwkckXVu21QWZa9XDICu1MIrnpWs37Iz2ph3uHqvfYLS3awEs4GzinB6sLNM+2xEgmv/hXjSFIeOsCAIxdAsA7Btbq6iIx0xIknVZHlp3pWBzXAFvsizWx7QFldaMhzsfZ1HgSd7EdqFoMEjhEr6FHsppj2NjKjqNVg4AGHFp+GkzxXcXHTcojwigIx4qFli4B6EdqGPvC1oX1fBy09iYxeA0maI/qwLsWLfShrtNE3eFi7aQblTkTaK1cFO8q5P8u61yKtv3wg==</ds:SignatureValue> +    <ds:KeyInfo> +      <ds:X509Data> +        <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> +      </ds:X509Data> +    </ds:KeyInfo> +  </ds:Signature> +  <md:Extensions> +    <mdattr:EntityAttributes xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute"> +      <saml2:Attribute xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Name="http://macedir.org/entity-category" 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">http://www.ref.gv.at/ns/names/agiz/pvp/egovtoken</saml2:AttributeValue> +      </saml2:Attribute> +    </mdattr:EntityAttributes> +  </md:Extensions> +  <md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> +    <md:KeyDescriptor use="signing"> +      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> +        <ds:X509Data> +          <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> +        </ds:X509Data> +      </ds:KeyInfo> +    </md:KeyDescriptor> +    <md:KeyDescriptor use="encryption"> +      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> +        <ds:X509Data> +          <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> +        </ds:X509Data> +      </ds:KeyInfo> +    </md:KeyDescriptor> +    <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat> +    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/post" index="0" isDefault="true"/> +    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/redirect" index="1"/> +    <md:AttributeConsumingService index="0" isDefault="true"> +      <md:ServiceName xml:lang="en">Default Service</md:ServiceName> +      <md:RequestedAttribute FriendlyName="MANDATOR-NATURAL-PERSON-BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.261.82" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +    </md:AttributeConsumingService> +  </md:SPSSODescriptor> +  <md:Organization> +    <md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName> +    <md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName> +    <md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL> +  </md:Organization> +  <md:ContactPerson contactType="technical"> +    <md:Company>E-Government Innovationszentrum</md:Company> +    <md:GivenName>Lenz</md:GivenName> +    <md:SurName>Thomas</md:SurName> +    <md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress> +    <md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber> +  </md:ContactPerson> +</md:EntityDescriptor> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_wrong_schema.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_wrong_schema.xml new file mode 100644 index 00000000..5fc61717 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_wrong_schema.xml @@ -0,0 +1,122 @@ +<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" entityID="https://demo.egiz.gv.at/demoportal_demologin/" validUntil="2059-07-27T11:23:29.736Z"> +	<ds:Signature> +		<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="#_c0303e3081ac29bb8329cade76279069"> +				<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/2001/04/xmlenc#sha256"/> +				<ds:DigestValue>IjxuoZphYVmZdZ5HfoVDr35r2b1V840+SMeC89IO/SQ=</ds:DigestValue> +			</ds:Reference> +		</ds:SignedInfo> +		<ds:SignatureValue>JILQKKPvsK7onsMweJauAcGEniFGJ5bXEOvfYhxAYCB+dXL6pH87USD1v9UqycllBDqQE/Rp2tPtqo11CjdcKs0KkceQCZjzmDlVPqMZrgh0FerTSysF0fcPKoKeAtqqk+WSu7Xk9lU+PCxGArGA+vBLTRRbAOuZpE7ORrS7AF2m5uaO1YOKfO0GN+LoxTiygI2aeqKsKMlPkboh4ZuEjv1ht9xUHeQtAf/MHtaXZDvaRQPXALf0oCRnDWpiiqvKdARJq5NXrrbrdow/M1FpoddtE0Mu65AsorIdXoPSXJnLhw/zDfHv82PQo0pW7ujc0yJY+5VzfURMZOyKmrfCmg==</ds:SignatureValue> +		<ds:KeyInfo> +			<ds:X509Data> +				<ds:X509Certificate>MIIEFTCCAv2gAwIBAgIJAI/HXXgQpJtFMA0GCSqGSIb3DQEBCwUAMGQxCzAJBgNVBAYTAkFUMRMw +EQYDVQQIEwpTb21lLVN0YXRlMQ0wCwYDVQQHEwRHcmF6MQ0wCwYDVQQKEwRFR0laMSIwIAYDVQQD +ExlNT0EtSUQgSURQIChUZXN0LVZlcnNpb24pMB4XDTE0MDEyMTA4NDAxOFoXDTE1MDEyMTA4NDAx +OFowZDELMAkGA1UEBhMCQVQxEzARBgNVBAgTClNvbWUtU3RhdGUxDTALBgNVBAcTBEdyYXoxDTAL +BgNVBAoTBEVHSVoxIjAgBgNVBAMTGU1PQS1JRCBJRFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFETzd0nLV2P4pUGnlLKj3V+MZ4bUyYkNK5NnkzB0PO8hm +tsrdg+HSNsnPiU5KvD26tFpxq9lfibZcAp9JHFqjA/capOHcTDhYkTvJcSdaKJzttTPy4wivTbRu +y+ocK9jjz6g8BFvP9wQ5/k2AwFaqj0SeJt0jJTn4CZ8XMNozA2hwkQA2heuMtOl24Ie9PRC3/Af7 +utV2CNfV2MysGHIxazsZDIgFF+5/nybyR1yiIxKb0BYDh3gbNdyH5uLVBHOP4hvzQN5Z1xc/cdzq +lzKn/4v6HJraNn00xLzK6nrG6gB6HvDok2l8T1Cc7f8I+sNlO2aM8rY4hGSGCfhiL6IFAgMBAAGj +gckwgcYwHQYDVR0OBBYEFKG3LzuPtAGCXUPTw3fo9dtsS9wWMIGWBgNVHSMEgY4wgYuAFKG3LzuP +tAGCXUPTw3fo9dtsS9wWoWikZjBkMQswCQYDVQQGEwJBVDETMBEGA1UECBMKU29tZS1TdGF0ZTEN +MAsGA1UEBxMER3JhejENMAsGA1UEChMERUdJWjEiMCAGA1UEAxMZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKYIJAI/HXXgQpJtFMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAME3wzEi +UAcF2pCDtMMJzX4IDhSkWNuvWtSMMy8Vgtcc2t570teIKh+qNKQWZyX3QFVE6ovDABg3ZUhn780l +G4/t6aMOUEeGg4udl7l0QRBRbdd+9oc0Aw5dQqku02AQ6wQd695PLj+F0GeA7cdef90aLPu6Rwa5 +z5BiKpReJZoul3NpjQXz7A1IslZOlIhEDcFUlBSn/+QfLOeNDKurvPT0OzUGSGfrv0AoniNHc/fz +lfyRmgFbzAVHedU5cIxcE0yHtEKFjFSVwtGng9rTJpoOoY4pvGvAHlw6GEgO+HwFukPDtnvY8vi/ +cfmNJhb06H+6mmHz929Bk4HuHoQj8X8=</ds:X509Certificate> +			</ds:X509Data> +		</ds:KeyInfo> +	</ds:Signature> +	<md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> +		<md:KeyDescriptor use="signing"> +			<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:KeyInfo> +				<ds:X509Data> +					<ds:X509Certificate>MIIEFTCCAv2gAwIBAgIJAI/HXXgQpJtFMA0GCSqGSIb3DQEBCwUAMGQxCzAJBgNVBAYTAkFUMRMw +EQYDVQQIEwpTb21lLVN0YXRlMQ0wCwYDVQQHEwRHcmF6MQ0wCwYDVQQKEwRFR0laMSIwIAYDVQQD +ExlNT0EtSUQgSURQIChUZXN0LVZlcnNpb24pMB4XDTE0MDEyMTA4NDAxOFoXDTE1MDEyMTA4NDAx +OFowZDELMAkGA1UEBhMCQVQxEzARBgNVBAgTClNvbWUtU3RhdGUxDTALBgNVBAcTBEdyYXoxDTAL +BgNVBAoTBEVHSVoxIjAgBgNVBAMTGU1PQS1JRCBJRFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFETzd0nLV2P4pUGnlLKj3V+MZ4bUyYkNK5NnkzB0PO8hm +tsrdg+HSNsnPiU5KvD26tFpxq9lfibZcAp9JHFqjA/capOHcTDhYkTvJcSdaKJzttTPy4wivTbRu +y+ocK9jjz6g8BFvP9wQ5/k2AwFaqj0SeJt0jJTn4CZ8XMNozA2hwkQA2heuMtOl24Ie9PRC3/Af7 +utV2CNfV2MysGHIxazsZDIgFF+5/nybyR1yiIxKb0BYDh3gbNdyH5uLVBHOP4hvzQN5Z1xc/cdzq +lzKn/4v6HJraNn00xLzK6nrG6gB6HvDok2l8T1Cc7f8I+sNlO2aM8rY4hGSGCfhiL6IFAgMBAAGj +gckwgcYwHQYDVR0OBBYEFKG3LzuPtAGCXUPTw3fo9dtsS9wWMIGWBgNVHSMEgY4wgYuAFKG3LzuP +tAGCXUPTw3fo9dtsS9wWoWikZjBkMQswCQYDVQQGEwJBVDETMBEGA1UECBMKU29tZS1TdGF0ZTEN +MAsGA1UEBxMER3JhejENMAsGA1UEChMERUdJWjEiMCAGA1UEAxMZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKYIJAI/HXXgQpJtFMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAME3wzEi +UAcF2pCDtMMJzX4IDhSkWNuvWtSMMy8Vgtcc2t570teIKh+qNKQWZyX3QFVE6ovDABg3ZUhn780l +G4/t6aMOUEeGg4udl7l0QRBRbdd+9oc0Aw5dQqku02AQ6wQd695PLj+F0GeA7cdef90aLPu6Rwa5 +z5BiKpReJZoul3NpjQXz7A1IslZOlIhEDcFUlBSn/+QfLOeNDKurvPT0OzUGSGfrv0AoniNHc/fz +lfyRmgFbzAVHedU5cIxcE0yHtEKFjFSVwtGng9rTJpoOoY4pvGvAHlw6GEgO+HwFukPDtnvY8vi/ +cfmNJhb06H+6mmHz929Bk4HuHoQj8X8=</ds:X509Certificate> +				</ds:X509Data> +			</ds:KeyInfo> +		</md:KeyDescriptor> +		<md:KeyDescriptor use="encryption"> +			<ds:KeyInfo> +				<ds:X509Data> +					<ds:X509Certificate>MIIEFTCCAv2gAwIBAgIJAI/HXXgQpJtFMA0GCSqGSIb3DQEBCwUAMGQxCzAJBgNVBAYTAkFUMRMw +EQYDVQQIEwpTb21lLVN0YXRlMQ0wCwYDVQQHEwRHcmF6MQ0wCwYDVQQKEwRFR0laMSIwIAYDVQQD +ExlNT0EtSUQgSURQIChUZXN0LVZlcnNpb24pMB4XDTE0MDEyMTA4NDAxOFoXDTE1MDEyMTA4NDAx +OFowZDELMAkGA1UEBhMCQVQxEzARBgNVBAgTClNvbWUtU3RhdGUxDTALBgNVBAcTBEdyYXoxDTAL +BgNVBAoTBEVHSVoxIjAgBgNVBAMTGU1PQS1JRCBJRFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFETzd0nLV2P4pUGnlLKj3V+MZ4bUyYkNK5NnkzB0PO8hm +tsrdg+HSNsnPiU5KvD26tFpxq9lfibZcAp9JHFqjA/capOHcTDhYkTvJcSdaKJzttTPy4wivTbRu +y+ocK9jjz6g8BFvP9wQ5/k2AwFaqj0SeJt0jJTn4CZ8XMNozA2hwkQA2heuMtOl24Ie9PRC3/Af7 +utV2CNfV2MysGHIxazsZDIgFF+5/nybyR1yiIxKb0BYDh3gbNdyH5uLVBHOP4hvzQN5Z1xc/cdzq +lzKn/4v6HJraNn00xLzK6nrG6gB6HvDok2l8T1Cc7f8I+sNlO2aM8rY4hGSGCfhiL6IFAgMBAAGj +gckwgcYwHQYDVR0OBBYEFKG3LzuPtAGCXUPTw3fo9dtsS9wWMIGWBgNVHSMEgY4wgYuAFKG3LzuP +tAGCXUPTw3fo9dtsS9wWoWikZjBkMQswCQYDVQQGEwJBVDETMBEGA1UECBMKU29tZS1TdGF0ZTEN +MAsGA1UEBxMER3JhejENMAsGA1UEChMERUdJWjEiMCAGA1UEAxMZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKYIJAI/HXXgQpJtFMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAME3wzEi +UAcF2pCDtMMJzX4IDhSkWNuvWtSMMy8Vgtcc2t570teIKh+qNKQWZyX3QFVE6ovDABg3ZUhn780l +G4/t6aMOUEeGg4udl7l0QRBRbdd+9oc0Aw5dQqku02AQ6wQd695PLj+F0GeA7cdef90aLPu6Rwa5 +z5BiKpReJZoul3NpjQXz7A1IslZOlIhEDcFUlBSn/+QfLOeNDKurvPT0OzUGSGfrv0AoniNHc/fz +lfyRmgFbzAVHedU5cIxcE0yHtEKFjFSVwtGng9rTJpoOoY4pvGvAHlw6GEgO+HwFukPDtnvY8vi/ +cfmNJhb06H+6mmHz929Bk4HuHoQj8X8=</ds:X509Certificate> +				</ds:X509Data> +			</ds:KeyInfo> +		</md:KeyDescriptor> +		<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_demologin/pvp2/sp/redirect"/> +		<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat> +		<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat> +		<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat> +		<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_demologin/pvp2/sp/post" index="0" isDefault="true"/> +		<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_demologin/pvp2/sp/redirect" index="1"/> +	</md:SPSSODescriptor> +	<md:Organization> +		<md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName> +		<md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName> +		<md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL> +	</md:Organization> +	<md:ContactPerson contactType="technical"> +		<md:Company>E-Government Innovationszentrum</md:Company> +		<md:GivenName>Lenz</md:GivenName> +		<md:SurName>Thomas</md:SurName> +		<md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress> +		<md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber> +	</md:ContactPerson> +</md:EntityDescriptor> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_wrong_sig.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_wrong_sig.xml new file mode 100644 index 00000000..510c84f8 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_wrong_sig.xml @@ -0,0 +1,162 @@ +<?xml version="1.0" encoding="UTF-8"?> +<md:EntityDescriptor +  xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" +  xmlns:ds="http://www.w3.org/2000/09/xmldsig#" +  entityID="https://demo.egiz.gv.at/demoportal_demologin/" +  validUntil="2059-07-27T11:23:29.736Z"> +  <ds:Signature> +    <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="#_c0303e3081ac29bb8329cade76279069"> +        <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/2001/04/xmlenc#sha256" /> +        <ds:DigestValue>IjxuoZphYVmZdZ5HfoVDr35r2b1V840+SMeC89IO/SQ= +        </ds:DigestValue> +      </ds:Reference> +    </ds:SignedInfo> +    <ds:SignatureValue>JILQKKPvsK7onsMweJauAcGEniFGJ5bXEOvfYhxAYCB+dXL6pH87USD1v9UqycllBDqQE/Rp2tPtqo11CjdcKs0KkceQCZjzmDlVPqMZrgh0FerTSysF0fcPKoKeAtqqk+WSu7Xk9lU+PCxGArGA+vBLTRRbAOuZpE7ORrS7AF2m5uaO1YOKfO0GN+LoxTiygI2aeqKsKMlPkboh4ZuEjv1ht9xUHeQtAf/MHtaXZDvaRQPXALf0oCRnDWpiiqvKdARJq5NXrrbrdow/M1FpoddtE0Mu65AsorIdXoPSXJnLhw/zDfHv82PQo0pW7ujc0yJY+5VzfURMZOyKmrfCmg== +    </ds:SignatureValue> +    <ds:KeyInfo> +      <ds:X509Data> +        <ds:X509Certificate>MIIEFTCCAv2gAwIBAgIJAI/HXXgQpJtFMA0GCSqGSIb3DQEBCwUAMGQxCzAJBgNVBAYTAkFUMRMw +          EQYDVQQIEwpTb21lLVN0YXRlMQ0wCwYDVQQHEwRHcmF6MQ0wCwYDVQQKEwRFR0laMSIwIAYDVQQD +          ExlNT0EtSUQgSURQIChUZXN0LVZlcnNpb24pMB4XDTE0MDEyMTA4NDAxOFoXDTE1MDEyMTA4NDAx +          OFowZDELMAkGA1UEBhMCQVQxEzARBgNVBAgTClNvbWUtU3RhdGUxDTALBgNVBAcTBEdyYXoxDTAL +          BgNVBAoTBEVHSVoxIjAgBgNVBAMTGU1PQS1JRCBJRFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqG +          SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFETzd0nLV2P4pUGnlLKj3V+MZ4bUyYkNK5NnkzB0PO8hm +          tsrdg+HSNsnPiU5KvD26tFpxq9lfibZcAp9JHFqjA/capOHcTDhYkTvJcSdaKJzttTPy4wivTbRu +          y+ocK9jjz6g8BFvP9wQ5/k2AwFaqj0SeJt0jJTn4CZ8XMNozA2hwkQA2heuMtOl24Ie9PRC3/Af7 +          utV2CNfV2MysGHIxazsZDIgFF+5/nybyR1yiIxKb0BYDh3gbNdyH5uLVBHOP4hvzQN5Z1xc/cdzq +          lzKn/4v6HJraNn00xLzK6nrG6gB6HvDok2l8T1Cc7f8I+sNlO2aM8rY4hGSGCfhiL6IFAgMBAAGj +          gckwgcYwHQYDVR0OBBYEFKG3LzuPtAGCXUPTw3fo9dtsS9wWMIGWBgNVHSMEgY4wgYuAFKG3LzuP +          tAGCXUPTw3fo9dtsS9wWoWikZjBkMQswCQYDVQQGEwJBVDETMBEGA1UECBMKU29tZS1TdGF0ZTEN +          MAsGA1UEBxMER3JhejENMAsGA1UEChMERUdJWjEiMCAGA1UEAxMZTU9BLUlEIElEUCAoVGVzdC1W +          ZXJzaW9uKYIJAI/HXXgQpJtFMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAME3wzEi +          UAcF2pCDtMMJzX4IDhSkWNuvWtSMMy8Vgtcc2t570teIKh+qNKQWZyX3QFVE6ovDABg3ZUhn780l +          G4/t6aMOUEeGg4udl7l0QRBRbdd+9oc0Aw5dQqku02AQ6wQd695PLj+F0GeA7cdef90aLPu6Rwa5 +          z5BiKpReJZoul3NpjQXz7A1IslZOlIhEDcFUlBSn/+QfLOeNDKurvPT0OzUGSGfrv0AoniNHc/fz +          lfyRmgFbzAVHedU5cIxcE0yHtEKFjFSVwtGng9rTJpoOoY4pvGvAHlw6GEgO+HwFukPDtnvY8vi/ +          cfmNJhb06H+6mmHz929Bk4HuHoQj8X8= +        </ds:X509Certificate> +      </ds:X509Data> +    </ds:KeyInfo> +  </ds:Signature> +  <md:SPSSODescriptor AuthnRequestsSigned="true" +    WantAssertionsSigned="true" +    protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> +    <md:KeyDescriptor use="signing"> +      <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:KeyValue> +          <ds:RSAKeyValue> +            <ds:Modulus>xA7SEU+e0yQH5rm9kbCDN9o3aPIo7HbP7tX6WOocLZAtNfyxSZDU16ksL6W +              jubafOqNEpcwR3RdFsT7bCqnXPBe5ELh5u4VEy19MzxkXRgrMvavzyBpVRgBUwUlV +              5foK5hhmbktQhyNdy/6LpQRhDUDsTvK+g9Ucj47es9AQJ3U= +            </ds:Modulus> +            <ds:Exponent>AQAB</ds:Exponent> +          </ds:RSAKeyValue> +        </ds:KeyValue> +        <!-- ds:X509Data> +          <ds:X509Certificate>MIIEFTCCAv2gAwIBAgIJAI/HXXgQpJtFMA0GCSqGSIb3DQEBCwUAMGQxCzAJBgNVBAYTAkFUMRMw +            EQYDVQQIEwpTb21lLVN0YXRlMQ0wCwYDVQQHEwRHcmF6MQ0wCwYDVQQKEwRFR0laMSIwIAYDVQQD +            ExlNT0EtSUQgSURQIChUZXN0LVZlcnNpb24pMB4XDTE0MDEyMTA4NDAxOFoXDTE1MDEyMTA4NDAx +            OFowZDELMAkGA1UEBhMCQVQxEzARBgNVBAgTClNvbWUtU3RhdGUxDTALBgNVBAcTBEdyYXoxDTAL +            BgNVBAoTBEVHSVoxIjAgBgNVBAMTGU1PQS1JRCBJRFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqG +            SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFETzd0nLV2P4pUGnlLKj3V+MZ4bUyYkNK5NnkzB0PO8hm +            tsrdg+HSNsnPiU5KvD26tFpxq9lfibZcAp9JHFqjA/capOHcTDhYkTvJcSdaKJzttTPy4wivTbRu +            y+ocK9jjz6g8BFvP9wQ5/k2AwFaqj0SeJt0jJTn4CZ8XMNozA2hwkQA2heuMtOl24Ie9PRC3/Af7 +            utV2CNfV2MysGHIxazsZDIgFF+5/nybyR1yiIxKb0BYDh3gbNdyH5uLVBHOP4hvzQN5Z1xc/cdzq +            lzKn/4v6HJraNn00xLzK6nrG6gB6HvDok2l8T1Cc7f8I+sNlO2aM8rY4hGSGCfhiL6IFAgMBAAGj +            gckwgcYwHQYDVR0OBBYEFKG3LzuPtAGCXUPTw3fo9dtsS9wWMIGWBgNVHSMEgY4wgYuAFKG3LzuP +            tAGCXUPTw3fo9dtsS9wWoWikZjBkMQswCQYDVQQGEwJBVDETMBEGA1UECBMKU29tZS1TdGF0ZTEN +            MAsGA1UEBxMER3JhejENMAsGA1UEChMERUdJWjEiMCAGA1UEAxMZTU9BLUlEIElEUCAoVGVzdC1W +            ZXJzaW9uKYIJAI/HXXgQpJtFMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAME3wzEi +            UAcF2pCDtMMJzX4IDhSkWNuvWtSMMy8Vgtcc2t570teIKh+qNKQWZyX3QFVE6ovDABg3ZUhn780l +            G4/t6aMOUEeGg4udl7l0QRBRbdd+9oc0Aw5dQqku02AQ6wQd695PLj+F0GeA7cdef90aLPu6Rwa5 +            z5BiKpReJZoul3NpjQXz7A1IslZOlIhEDcFUlBSn/+QfLOeNDKurvPT0OzUGSGfrv0AoniNHc/fz +            lfyRmgFbzAVHedU5cIxcE0yHtEKFjFSVwtGng9rTJpoOoY4pvGvAHlw6GEgO+HwFukPDtnvY8vi/ +            cfmNJhb06H+6mmHz929Bk4HuHoQj8X8= +          </ds:X509Certificate> +        </ds:X509Data--> +      </ds:KeyInfo> +    </md:KeyDescriptor> +    <md:KeyDescriptor use="encryption"> +      <ds:KeyInfo> +        <ds:X509Data> +          <ds:X509Certificate>MIIEFTCCAv2gAwIBAgIJAI/HXXgQpJtFMA0GCSqGSIb3DQEBCwUAMGQxCzAJBgNVBAYTAkFUMRMw +            EQYDVQQIEwpTb21lLVN0YXRlMQ0wCwYDVQQHEwRHcmF6MQ0wCwYDVQQKEwRFR0laMSIwIAYDVQQD +            ExlNT0EtSUQgSURQIChUZXN0LVZlcnNpb24pMB4XDTE0MDEyMTA4NDAxOFoXDTE1MDEyMTA4NDAx +            OFowZDELMAkGA1UEBhMCQVQxEzARBgNVBAgTClNvbWUtU3RhdGUxDTALBgNVBAcTBEdyYXoxDTAL +            BgNVBAoTBEVHSVoxIjAgBgNVBAMTGU1PQS1JRCBJRFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqG +            SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFETzd0nLV2P4pUGnlLKj3V+MZ4bUyYkNK5NnkzB0PO8hm +            tsrdg+HSNsnPiU5KvD26tFpxq9lfibZcAp9JHFqjA/capOHcTDhYkTvJcSdaKJzttTPy4wivTbRu +            y+ocK9jjz6g8BFvP9wQ5/k2AwFaqj0SeJt0jJTn4CZ8XMNozA2hwkQA2heuMtOl24Ie9PRC3/Af7 +            utV2CNfV2MysGHIxazsZDIgFF+5/nybyR1yiIxKb0BYDh3gbNdyH5uLVBHOP4hvzQN5Z1xc/cdzq +            lzKn/4v6HJraNn00xLzK6nrG6gB6HvDok2l8T1Cc7f8I+sNlO2aM8rY4hGSGCfhiL6IFAgMBAAGj +            gckwgcYwHQYDVR0OBBYEFKG3LzuPtAGCXUPTw3fo9dtsS9wWMIGWBgNVHSMEgY4wgYuAFKG3LzuP +            tAGCXUPTw3fo9dtsS9wWoWikZjBkMQswCQYDVQQGEwJBVDETMBEGA1UECBMKU29tZS1TdGF0ZTEN +            MAsGA1UEBxMER3JhejENMAsGA1UEChMERUdJWjEiMCAGA1UEAxMZTU9BLUlEIElEUCAoVGVzdC1W +            ZXJzaW9uKYIJAI/HXXgQpJtFMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAME3wzEi +            UAcF2pCDtMMJzX4IDhSkWNuvWtSMMy8Vgtcc2t570teIKh+qNKQWZyX3QFVE6ovDABg3ZUhn780l +            G4/t6aMOUEeGg4udl7l0QRBRbdd+9oc0Aw5dQqku02AQ6wQd695PLj+F0GeA7cdef90aLPu6Rwa5 +            z5BiKpReJZoul3NpjQXz7A1IslZOlIhEDcFUlBSn/+QfLOeNDKurvPT0OzUGSGfrv0AoniNHc/fz +            lfyRmgFbzAVHedU5cIxcE0yHtEKFjFSVwtGng9rTJpoOoY4pvGvAHlw6GEgO+HwFukPDtnvY8vi/ +            cfmNJhb06H+6mmHz929Bk4HuHoQj8X8= +          </ds:X509Certificate> +        </ds:X509Data> +      </ds:KeyInfo> +    </md:KeyDescriptor> +    <md:SingleLogoutService +      Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" +      Location="https://demo.egiz.gv.at/demoportal_demologin/pvp2/sp/redirect" /> +    <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent +    </md:NameIDFormat> +    <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient +    </md:NameIDFormat> +    <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified +    </md:NameIDFormat> +    <md:AssertionConsumerService +      Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" +      Location="https://demo.egiz.gv.at/demoportal_demologin/pvp2/sp/post" +      index="0" isDefault="true" /> +    <md:AssertionConsumerService +      Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" +      Location="https://demo.egiz.gv.at/demoportal_demologin/pvp2/sp/redirect" +      index="1" /> +  </md:SPSSODescriptor> +  <md:Organization> +    <md:OrganizationName xml:lang="de">EGIZ +    </md:OrganizationName> +    <md:OrganizationDisplayName xml:lang="de">E-Government +      Innovationszentrum</md:OrganizationDisplayName> +    <md:OrganizationURL xml:lang="de">http://www.egiz.gv.at +    </md:OrganizationURL> +  </md:Organization> +  <md:ContactPerson contactType="technical"> +    <md:Company>E-Government Innovationszentrum</md:Company> +    <md:GivenName>Lenz</md:GivenName> +    <md:SurName>Thomas</md:SurName> +    <md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress> +    <md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber> +  </md:ContactPerson> +</md:EntityDescriptor> 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 index de3cfbd1..375224bb 100644 --- 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 @@ -18,5 +18,8 @@    <bean id="dummyGuiBuilderConfigFactory"          class="at.gv.egiz.eaaf.core.impl.idp.module.gui.DummyGuiBuilderConfigurationFactory" /> +   +  <bean id="httpClientFactory" +        class="at.gv.egiz.eaaf.core.impl.utils.HttpClientFactory" />  </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 index f261e893..aac94041 100644 --- 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 @@ -10,20 +10,11 @@      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"/> +  <import resource="test_eaaf_core.beans.xml"/>   +  <import resource="classpath:/eaaf_pvp.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 diff --git a/eaaf_modules/eaaf_module_pvp2_idp/pom.xml b/eaaf_modules/eaaf_module_pvp2_idp/pom.xml index e687f48a..2e9cb88d 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/pom.xml +++ b/eaaf_modules/eaaf_module_pvp2_idp/pom.xml @@ -8,7 +8,7 @@      <version>1.1.0-SNAPSHOT</version>    </parent>    <artifactId>eaaf_module_pvp2_idp</artifactId> -  <name>eaaf_module_pvp2_core</name> +  <name>eaaf_module_pvp2_idp</name>    <url>http://maven.apache.org</url>    <properties>      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> @@ -32,6 +32,23 @@        <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> +    <dependency> +      <groupId>at.gv.egiz.eaaf</groupId> +      <artifactId>eaaf_module_pvp2_core</artifactId> +      <scope>test</scope> +      <type>test-jar</type> +    </dependency>    </dependencies>    <build> @@ -49,21 +66,20 @@        </plugin>        <!-- enable co-existence of testng and junit --> -			<plugin> -				<artifactId>maven-surefire-plugin</artifactId> -				<version>${surefire.version}</version> -				<configuration> -					<threadCount>1</threadCount> -					<argLine>--add-modules java.xml.bind</argLine> -				</configuration> -				<dependencies> -					<dependency> -						<groupId>org.apache.maven.surefire</groupId> -						<artifactId>surefire-junit47</artifactId> -						<version>${surefire.version}</version> -					</dependency> -				</dependencies> -			</plugin> +      <plugin> +        <artifactId>maven-surefire-plugin</artifactId> +        <version>${surefire.version}</version> +        <configuration> +          <threadCount>1</threadCount>           +        </configuration> +        <dependencies> +          <dependency> +            <groupId>org.apache.maven.surefire</groupId> +            <artifactId>surefire-junit47</artifactId> +            <version>${surefire.version}</version> +          </dependency> +        </dependencies> +      </plugin>      </plugins>    </build> diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/Pvp2SProfileIdpSpringResourceProvider.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/Pvp2SProfileIdpSpringResourceProvider.java index 9414dc33..7e572d70 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/Pvp2SProfileIdpSpringResourceProvider.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/Pvp2SProfileIdpSpringResourceProvider.java @@ -20,6 +20,7 @@  package at.gv.egiz.eaaf.modules.pvp2.idp;  import at.gv.egiz.components.spring.api.SpringResourceProvider; +  import org.springframework.core.io.ClassPathResource;  import org.springframework.core.io.Resource; @@ -41,7 +42,7 @@ public class Pvp2SProfileIdpSpringResourceProvider implements SpringResourceProv      final ClassPathResource sl20AuthConfig = new ClassPathResource("/eaaf_pvp_idp.beans.xml",          Pvp2SProfileIdpSpringResourceProvider.class); -    return new Resource[] {sl20AuthConfig}; +    return new Resource[] { sl20AuthConfig };    }  } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionConsumerServiceException.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionConsumerServiceException.java index 0003b829..a7e05664 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionConsumerServiceException.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionConsumerServiceException.java @@ -28,21 +28,19 @@ public class InvalidAssertionConsumerServiceException extends Pvp2Exception {    private static final long serialVersionUID = 7861790149343943091L;    public InvalidAssertionConsumerServiceException(final int idx) { -    super("pvp2.28", new Object[] {idx}); +    super("pvp2.28", new Object[] { idx });      this.statusCodeValue = StatusCode.REQUESTER;    }    /**     * Invalid assertion consumer-service URL.     * -   *  @param wrongUrl invalid URL +   * @param wrongUrl invalid URL     */    public InvalidAssertionConsumerServiceException(final String wrongUrl) { -    super("pvp2.23", new Object[] {wrongUrl}); +    super("pvp2.23", new Object[] { wrongUrl });      this.statusCodeValue = StatusCode.REQUESTER;    } - -  } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSignedException.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSignedException.java index c02e534c..add2103b 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSignedException.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSignedException.java @@ -37,7 +37,4 @@ public class SamlRequestNotSignedException extends Pvp2Exception {      this.statusCodeValue = StatusCode.REQUESTER;    } - - -  } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSupported.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSupported.java index b0dcdb2e..d672f457 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSupported.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSupported.java @@ -23,7 +23,6 @@ import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;  import org.opensaml.saml.saml2.core.StatusCode; -  public class SamlRequestNotSupported extends Pvp2Exception {    private static final long serialVersionUID = 1244883178458802767L; @@ -33,7 +32,4 @@ public class SamlRequestNotSupported extends Pvp2Exception {      this.statusCodeValue = StatusCode.REQUEST_UNSUPPORTED;    } - - -  } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/UnprovideableAttributeException.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/UnprovideableAttributeException.java index 0f84b8fb..3a56b414 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/UnprovideableAttributeException.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/UnprovideableAttributeException.java @@ -28,7 +28,7 @@ public class UnprovideableAttributeException extends Pvp2Exception {    private static final long serialVersionUID = 3972197758163647157L;    public UnprovideableAttributeException(final String attributeName) { -    super("pvp2.10", new Object[] {attributeName}); +    super("pvp2.10", new Object[] { attributeName });      this.statusCodeValue = StatusCode.UNKNOWN_ATTR_PROFILE;    }  } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AbstractPvp2XProtocol.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AbstractPvp2XProtocol.java index f86fd883..1ef7da29 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AbstractPvp2XProtocol.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AbstractPvp2XProtocol.java @@ -46,6 +46,7 @@ import at.gv.egiz.eaaf.modules.pvp2.exception.InvalidPvpRequestException;  import at.gv.egiz.eaaf.modules.pvp2.exception.NameIdFormatNotSupportedException;  import at.gv.egiz.eaaf.modules.pvp2.exception.NoMetadataInformationException;  import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException;  import at.gv.egiz.eaaf.modules.pvp2.idp.exception.InvalidAssertionConsumerServiceException;  import at.gv.egiz.eaaf.modules.pvp2.impl.binding.PostBinding;  import at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding; @@ -72,7 +73,6 @@ import org.opensaml.saml.saml2.core.StatusMessage;  import org.opensaml.saml.saml2.metadata.AssertionConsumerService;  import org.opensaml.saml.saml2.metadata.EntityDescriptor;  import org.opensaml.saml.saml2.metadata.SPSSODescriptor; -import org.opensaml.ws.security.SecurityPolicyException;  import org.opensaml.xmlsec.signature.SignableXMLObject;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory; @@ -81,6 +81,9 @@ import org.springframework.beans.factory.annotation.Autowired;  public abstract class AbstractPvp2XProtocol extends AbstractController implements IModulInfo {    private static final Logger log = LoggerFactory.getLogger(AbstractPvp2XProtocol.class); +  private static final String HTTP_PARAM_SAMLREQ = "SAMLRequest"; +  private static final String ERROR_INVALID_REQUEST = "Receive INVALID protocol request: {}"; +    @Autowired(required = true)    protected IPvp2BasicConfiguration pvpBasicConfiguration;    @Autowired(required = true) @@ -92,8 +95,6 @@ public abstract class AbstractPvp2XProtocol extends AbstractController implement    private AbstractCredentialProvider pvpIdpCredentials; - -    /**     * Sets a specific credential provider for PVP S-Profile IDP component.     * @@ -151,7 +152,6 @@ public abstract class AbstractPvp2XProtocol extends AbstractController implement        moaError = statusMessager.getResponseErrorCode(e);      } -      if (StringUtils.isNotEmpty(moaError)) {        final StatusCode moaStatusCode = Saml2Utils.createSamlObject(StatusCode.class);        moaStatusCode.setValue(moaError); @@ -245,16 +245,16 @@ public abstract class AbstractPvp2XProtocol extends AbstractController implement        // get POST-Binding decoder implementation        final InboundMessage msg = (InboundMessage) new PostBinding().decode(req, resp, -          metadataProvider, false, +          metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME,            new EaafUriCompare(pvpBasicConfiguration.getIdpSsoPostService(pendingReq.getAuthUrl())));        pendingReq.setRequest(msg);        // preProcess Message        preProcess(req, resp, pendingReq); -    } catch (final SecurityPolicyException e) { -      final String samlRequest = req.getParameter("SAMLRequest"); -      log.warn("Receive INVALID protocol request: " + samlRequest, e); +    } catch (final SamlSigningException e) { +      final String samlRequest = req.getParameter(HTTP_PARAM_SAMLREQ); +      log.warn(ERROR_INVALID_REQUEST, samlRequest, null, e);        // write revision log entries        if (pendingReq != null) { @@ -264,9 +264,9 @@ public abstract class AbstractPvp2XProtocol extends AbstractController implement        throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); -    } catch (final SecurityException e) { -      final String samlRequest = req.getParameter("SAMLRequest"); -      log.warn("Receive INVALID protocol request: " + samlRequest, e); +    } catch (final Pvp2Exception e) { +      final String samlRequest = req.getParameter(HTTP_PARAM_SAMLREQ); +      log.warn(ERROR_INVALID_REQUEST, samlRequest, null, e);        // write revision log entries        if (pendingReq != null) { @@ -274,7 +274,7 @@ public abstract class AbstractPvp2XProtocol extends AbstractController implement              pendingReq.getUniqueTransactionIdentifier());        } -      throw new InvalidProtocolRequestException("pvp2.22", new Object[] {e.getMessage()}); +      throw new InvalidProtocolRequestException("pvp2.22", new Object[] { e.getMessage() });      } catch (final EaafException e) { @@ -287,8 +287,8 @@ public abstract class AbstractPvp2XProtocol extends AbstractController implement        throw e;      } catch (final Throwable e) { -      final String samlRequest = req.getParameter("SAMLRequest"); -      log.warn("Receive INVALID protocol request: " + samlRequest, e); +      final String samlRequest = req.getParameter(HTTP_PARAM_SAMLREQ); +      log.warn(ERROR_INVALID_REQUEST, samlRequest, null, e);        // write revision log entries        if (pendingReq != null) { @@ -296,7 +296,7 @@ public abstract class AbstractPvp2XProtocol extends AbstractController implement              pendingReq.getUniqueTransactionIdentifier());        } -      throw new EaafException("pvp2.24", new Object[] {e.getMessage()}, e); +      throw new EaafException("pvp2.24", new Object[] { e.getMessage() }, e);      }    } @@ -319,16 +319,16 @@ public abstract class AbstractPvp2XProtocol extends AbstractController implement        // get POST-Binding decoder implementation        final InboundMessage msg = (InboundMessage) new RedirectBinding().decode(req, resp, -          metadataProvider, false, new EaafUriCompare( +          metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, new EaafUriCompare(                pvpBasicConfiguration.getIdpSsoRedirectService(pendingReq.getAuthUrl())));        pendingReq.setRequest(msg);        // preProcess Message        preProcess(req, resp, pendingReq); -    } catch (final SecurityPolicyException e) { -      final String samlRequest = req.getParameter("SAMLRequest"); -      log.warn("Receive INVALID protocol request: " + samlRequest, e); +    } catch (final SamlSigningException e) { +      final String samlRequest = req.getParameter(HTTP_PARAM_SAMLREQ); +      log.warn(ERROR_INVALID_REQUEST, samlRequest, null, e);        // write revision log entries        if (pendingReq != null) { @@ -338,9 +338,9 @@ public abstract class AbstractPvp2XProtocol extends AbstractController implement        throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); -    } catch (final SecurityException e) { -      final String samlRequest = req.getParameter("SAMLRequest"); -      log.warn("Receive INVALID protocol request: " + samlRequest, e); +    } catch (final Pvp2Exception e) { +      final String samlRequest = req.getParameter(HTTP_PARAM_SAMLREQ); +      log.warn(ERROR_INVALID_REQUEST, samlRequest, null, e);        // write revision log entries        if (pendingReq != null) { @@ -348,11 +348,11 @@ public abstract class AbstractPvp2XProtocol extends AbstractController implement              pendingReq.getUniqueTransactionIdentifier());        } -      throw new InvalidProtocolRequestException("pvp2.22", new Object[] {e.getMessage()}); +      throw new InvalidProtocolRequestException("pvp2.22", new Object[] { e.getMessage() });      } catch (final EaafException e) { -      final String samlRequest = req.getParameter("SAMLRequest"); -      log.info("Receive INVALID protocol request: " + samlRequest); +      final String samlRequest = req.getParameter(HTTP_PARAM_SAMLREQ); +      log.info(ERROR_INVALID_REQUEST, samlRequest, null, e);        // write revision log entries        if (pendingReq != null) { @@ -363,8 +363,8 @@ public abstract class AbstractPvp2XProtocol extends AbstractController implement        throw e;      } catch (final Throwable e) { -      final String samlRequest = req.getParameter("SAMLRequest"); -      log.warn("Receive INVALID protocol request: " + samlRequest, e); +      final String samlRequest = req.getParameter(HTTP_PARAM_SAMLREQ); +      log.warn(ERROR_INVALID_REQUEST, samlRequest, null, e);        // write revision log entries        if (pendingReq != null) { @@ -372,17 +372,15 @@ public abstract class AbstractPvp2XProtocol extends AbstractController implement              pendingReq.getUniqueTransactionIdentifier());        } -      throw new EaafException("pvp2.24", new Object[] {e.getMessage()}, e); +      throw new EaafException("pvp2.24", new Object[] { e.getMessage() }, e);      }    } - -    /**     * Authentication request pre-processor.     * -   * @param request http request -   * @param response http response +   * @param request    http request +   * @param response   http response     * @param pendingReq current pending request     * @return true if preprocess can handle this request type, otherwise false     * @throws Throwable In case of an error @@ -419,20 +417,17 @@ public abstract class AbstractPvp2XProtocol extends AbstractController implement        log.error("Receive unsupported PVP21 message of type: "            + ((PvpSProfileRequest) msg).getSamlRequest().getClass().getName());        throw new InvalidPvpRequestException("pvp2.09", -          new Object[] {((PvpSProfileRequest) msg).getSamlRequest().getClass().getName()}); +          new Object[] { ((PvpSProfileRequest) msg).getSamlRequest().getClass().getName() });      } - -      // switch to session authentication      protAuthService.performAuthentication(request, response, pendingReq);    } -    /**     * PreProcess Authn request.     * -   * @param request http request +   * @param request    http request     * @param pendingReq current pending request     * @throws Throwable in case of an error     */ @@ -458,7 +453,7 @@ public abstract class AbstractPvp2XProtocol extends AbstractController implement      if (authnRequest.getIssueInstant() == null) {        log.warn("Unsupported request: No IssueInstant Attribute found.");        throw new AuthnRequestValidatorException("pvp2.22", -          new Object[] {"Unsupported request: No IssueInstant Attribute found"}, pendingReq); +          new Object[] { "Unsupported request: No IssueInstant Attribute found" }, pendingReq);      } @@ -466,7 +461,7 @@ public abstract class AbstractPvp2XProtocol extends AbstractController implement          .isAfterNow()) {        log.warn("Unsupported request: No IssueInstant DateTime is not valid anymore.");        throw new AuthnRequestValidatorException("pvp2.22", -          new Object[] {"Unsupported request: No IssueInstant DateTime is not valid anymore."}, +          new Object[] { "Unsupported request: No IssueInstant DateTime is not valid anymore." },            pendingReq);      } @@ -496,14 +491,13 @@ public abstract class AbstractPvp2XProtocol extends AbstractController implement        } -      } else {        // use AssertionConsumerServiceIndex and select consumerService from metadata        final Integer aIdx = authnRequest.getAssertionConsumerServiceIndex();        int assertionidx = 0;        if (aIdx != null) { -        assertionidx = aIdx.intValue(); +        assertionidx = aIdx;        } else {          assertionidx = Saml2Utils.getDefaultAssertionConsumerServiceIndex(spSsoDescriptor); @@ -517,7 +511,6 @@ public abstract class AbstractPvp2XProtocol extends AbstractController implement        }      } -      // validate AuthnRequest      final AuthnRequest authReq = (AuthnRequest) samlReq;      final String oaUrl = moaRequest.getEntityMetadata(metadataProvider).getEntityID(); diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AuthenticationAction.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AuthenticationAction.java index 200d98c4..c0190959 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AuthenticationAction.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AuthenticationAction.java @@ -23,19 +23,6 @@ import javax.annotation.PostConstruct;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; -import org.joda.time.DateTime; -import org.opensaml.saml.common.xml.SAMLConstants; -import org.opensaml.saml.saml2.core.Assertion; -import org.opensaml.saml.saml2.core.AuthnRequest; -import org.opensaml.saml.saml2.core.Response; -import org.opensaml.saml.saml2.metadata.AssertionConsumerService; -import org.opensaml.saml.saml2.metadata.EntityDescriptor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.stereotype.Service; -  import at.gv.egiz.eaaf.core.api.IRequest;  import at.gv.egiz.eaaf.core.api.idp.IAction;  import at.gv.egiz.eaaf.core.api.idp.IAuthData; @@ -57,13 +44,23 @@ import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileRequest;  import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider;  import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import org.joda.time.DateTime; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.saml2.core.Assertion; +import org.opensaml.saml.saml2.core.AuthnRequest; +import org.opensaml.saml.saml2.core.Response; +import org.opensaml.saml.saml2.metadata.AssertionConsumerService; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Service; +  @Service("PVPAuthenticationRequestAction")  public class AuthenticationAction implements IAction {    private static final Logger log = LoggerFactory.getLogger(AuthenticationAction.class); -  private static final String CONFIG_PROPERTY_PVP2_ENABLE_ENCRYPTION = -      "protocols.pvp2.assertion.encryption.active"; -    @Autowired(required = true)    private IPvp2MetadataProvider metadataProvider;    @Autowired(required = true) @@ -115,7 +112,7 @@ public class AuthenticationAction implements IAction {        final Response authResponse = AuthResponseBuilder.buildResponse(metadataProvider,            issuerEntityID, authnRequest, date, assertion, -          authConfig.getBasicConfigurationBoolean(CONFIG_PROPERTY_PVP2_ENABLE_ENCRYPTION, true)); +          authConfig);        IEncoder binding = null; @@ -141,7 +138,7 @@ public class AuthenticationAction implements IAction {        sloInformation.setSpEntityID(req.getServiceProviderConfiguration().getUniqueIdentifier());        return sloInformation; -    } catch (SecurityException e) { +    } catch (final SecurityException e) {        log.warn("Message Encoding exception", e);        throw new ResponderErrorException("pvp2.01", null, e); diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/MetadataAction.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/MetadataAction.java index a1e8b5ba..3f0ad0b6 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/MetadataAction.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/MetadataAction.java @@ -22,6 +22,7 @@ package at.gv.egiz.eaaf.modules.pvp2.idp.impl;  import javax.annotation.PostConstruct;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; +  import at.gv.egiz.eaaf.core.api.IRequest;  import at.gv.egiz.eaaf.core.api.idp.IAction;  import at.gv.egiz.eaaf.core.api.idp.IAuthData; @@ -33,6 +34,7 @@ import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataConfigurationFactor  import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException;  import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpMetadataBuilder;  import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider; +  import org.slf4j.Logger;  import org.slf4j.LoggerFactory;  import org.springframework.beans.factory.annotation.Autowired; @@ -74,8 +76,6 @@ public class MetadataAction implements IAction {        final IPvpMetadataBuilderConfiguration metadataConfig = configFactory            .generateMetadataBuilderConfiguration(req.getAuthUrlWithOutSlash(), pvpIdpCredentials); - -        final String metadataXml = metadatabuilder.buildPvpMetadata(metadataConfig);        log.trace("METADATA: " + metadataXml); @@ -117,5 +117,4 @@ public class MetadataAction implements IAction {      }    } -  } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/PvpSProfilePendingRequest.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/PvpSProfilePendingRequest.java index 6c621841..26e04881 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/PvpSProfilePendingRequest.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/PvpSProfilePendingRequest.java @@ -21,6 +21,7 @@ package at.gv.egiz.eaaf.modules.pvp2.idp.impl;  import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl;  import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage; +  import org.springframework.beans.factory.config.BeanDefinition;  import org.springframework.context.annotation.Scope;  import org.springframework.stereotype.Component; diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/AuthResponseBuilder.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/AuthResponseBuilder.java index 8cafebb9..55e3e8b4 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/AuthResponseBuilder.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/AuthResponseBuilder.java @@ -19,37 +19,55 @@  package at.gv.egiz.eaaf.modules.pvp2.idp.impl.builder; +import java.security.PublicKey; +import java.security.interfaces.ECPublicKey; +import java.security.interfaces.RSAPublicKey;  import java.util.ArrayList;  import java.util.List; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; +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.idp.exception.InvalidAssertionEncryptionException; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +  import org.joda.time.DateTime;  import org.opensaml.core.criterion.EntityIdCriterion;  import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.criterion.EntityRoleCriterion; +import org.opensaml.saml.criterion.ProtocolCriterion; +import org.opensaml.saml.metadata.resolver.impl.PredicateRoleDescriptorResolver;  import org.opensaml.saml.saml2.core.Assertion;  import org.opensaml.saml.saml2.core.EncryptedAssertion;  import org.opensaml.saml.saml2.core.Issuer;  import org.opensaml.saml.saml2.core.NameIDType;  import org.opensaml.saml.saml2.core.RequestAbstractType;  import org.opensaml.saml.saml2.core.Response; +import org.opensaml.saml.saml2.encryption.Encrypter;  import org.opensaml.saml.saml2.encryption.Encrypter.KeyPlacement;  import org.opensaml.saml.saml2.metadata.SPSSODescriptor;  import org.opensaml.saml.security.impl.MetadataCredentialResolver; -import org.opensaml.security.MetadataCriteria;  import org.opensaml.security.credential.UsageType;  import org.opensaml.security.criteria.UsageCriterion;  import org.opensaml.security.x509.X509Credential; -import org.opensaml.xmlsec.EncryptionParameters; +import org.opensaml.xmlsec.SecurityConfigurationSupport; +import org.opensaml.xmlsec.encryption.support.DataEncryptionParameters;  import org.opensaml.xmlsec.encryption.support.EncryptionException;  import org.opensaml.xmlsec.encryption.support.KeyEncryptionParameters; +import org.opensaml.xmlsec.keyinfo.KeyInfoCredentialResolver;  import org.opensaml.xmlsec.keyinfo.KeyInfoGeneratorFactory; +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.slf4j.Logger;  import org.slf4j.LoggerFactory; -import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; -import at.gv.egiz.eaaf.modules.pvp2.idp.exception.InvalidAssertionEncryptionException; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException;  import net.shibboleth.utilities.java.support.resolver.CriteriaSet; +import net.shibboleth.utilities.java.support.resolver.ResolverException;  /**   * Authentication response builder. @@ -65,17 +83,17 @@ public class AuthResponseBuilder {     * Build PVP2 S-Profile authentication response.     *     * @param metadataProvider Service-Provider metadata -   * @param issuerEntityID IDP entityId -   * @param req current pending request -   * @param date Timestamp -   * @param assertion PVP2 S-Profil Assertion -   * @param enableEncryption encrypt Assertion flag +   * @param issuerEntityID   IDP entityId +   * @param req              current pending request +   * @param date             Timestamp +   * @param assertion        PVP2 S-Profil Assertion +   * @param authConfig       {@link IConfiguration}     * @return PVP2 S-Profile authentication response     * @throws InvalidAssertionEncryptionException In case of an error     */    public static Response buildResponse(final IPvp2MetadataProvider metadataProvider,        final String issuerEntityID, final RequestAbstractType req, final DateTime date, -      final Assertion assertion, final boolean enableEncryption) +      final Assertion assertion, IConfiguration authConfig)        throws InvalidAssertionEncryptionException {      final Response authResponse = Saml2Utils.createSamlObject(Response.class); @@ -90,72 +108,117 @@ public class AuthResponseBuilder {      final String remoteSessionID = Saml2Utils.getSecureIdentifier();      authResponse.setID(remoteSessionID); -      // SAML2 response required IssueInstant      authResponse.setIssueInstant(date);      authResponse.setStatus(Saml2Utils.getSuccessStatus());      // check, if metadata includes an encryption key -    final MetadataCredentialResolver mdCredResolver = -        new MetadataCredentialResolver(metadataProvider); - -    final CriteriaSet criteriaSet = new CriteriaSet(); -    criteriaSet.add(new EntityIdCriterion(req.getIssuer().getValue())); -    criteriaSet -        .add(new MetadataCriteria(SPSSODescriptor.DEFAULT_ELEMENT_NAME, SAMLConstants.SAML20P_NS)); -    criteriaSet.add(new UsageCriterion(UsageType.ENCRYPTION)); +    final X509Credential encryptionCredentials = resolveEncryptionCredential(req, metadataProvider); -    X509Credential encryptionCredentials = null; -    try { -      encryptionCredentials = (X509Credential) mdCredResolver.resolveSingle(criteriaSet); +    if (encryptionCredentials != null +        && authConfig.getBasicConfigurationBoolean( +            PvpConstants.CONFIG_PROPERTY_PVP2_ENABLE_ENCRYPTION, true)) { +      authResponse.getEncryptedAssertions().add( +          doEncryption(assertion, encryptionCredentials, authConfig)); -    } catch (final SecurityException e2) { -      log.warn("Can not extract the Assertion Encryption-Key from metadata", e2); -      throw new InvalidAssertionEncryptionException(); +    } else { +      authResponse.getAssertions().add(assertion);      } -    if (encryptionCredentials != null && enableEncryption) { -      // encrypt SAML2 assertion +    return authResponse; +  } + +  private static EncryptedAssertion doEncryption(Assertion assertion, +      X509Credential encryptionCredentials, IConfiguration authConfig) +      throws InvalidAssertionEncryptionException { +    try { +      final String keyEncAlg = selectKeyEncryptionAlgorithm(encryptionCredentials, authConfig); -      try { +      final DataEncryptionParameters dataEncParams = new DataEncryptionParameters(); +      dataEncParams.setAlgorithm(authConfig.getBasicConfiguration( +          PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_DATA, PvpConstants.DEFAULT_SYM_ENCRYPTION_METHODE)); -        final EncryptionParameters dataEncParams = new EncryptionParameters(); -        dataEncParams.setAlgorithm(PvpConstants.DEFAULT_SYM_ENCRYPTION_METHODE); +      final List<KeyEncryptionParameters> keyEncParamList = new ArrayList<>(); +      final KeyEncryptionParameters keyEncParam = new KeyEncryptionParameters(); +      keyEncParam.setEncryptionCredential(encryptionCredentials); +      keyEncParam.setAlgorithm(keyEncAlg); -        final List<KeyEncryptionParameters> keyEncParamList = new ArrayList<>(); -        final KeyEncryptionParameters keyEncParam = new KeyEncryptionParameters(); +      final KeyInfoGeneratorFactory kigf = +          SecurityConfigurationSupport.getGlobalEncryptionConfiguration() +              .getKeyTransportKeyInfoGeneratorManager().getDefaultManager().getFactory(encryptionCredentials); +      keyEncParam.setKeyInfoGenerator(kigf.newInstance()); +      keyEncParamList.add(keyEncParam); -        keyEncParam.setEncryptionCredential(encryptionCredentials); -        keyEncParam.setAlgorithm(PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE); -        final KeyInfoGeneratorFactory kigf = -            org.opensaml.xml.Configuration.getGlobalSecurityConfiguration() -                .getKeyInfoGeneratorManager().getDefaultManager().getFactory(encryptionCredentials); -        keyEncParam.setKeyInfoGenerator(kigf.newInstance()); -        keyEncParamList.add(keyEncParam); +      final Encrypter samlEncrypter = new Encrypter(dataEncParams, keyEncParamList); +      samlEncrypter.setKeyPlacement(KeyPlacement.PEER); -        final Encrypter samlEncrypter = new Encrypter(dataEncParams, keyEncParamList); -        // samlEncrypter.setKeyPlacement(KeyPlacement.INLINE); -        samlEncrypter.setKeyPlacement(KeyPlacement.PEER); +      return samlEncrypter.encrypt(assertion); -        EncryptedAssertion encryptAssertion = null; +    } catch (final EncryptionException | SamlSigningException e1) { +      log.warn("Can not encrypt the PVP2 assertion", e1); +      throw new InvalidAssertionEncryptionException(); -        encryptAssertion = samlEncrypter.encrypt(assertion); +    } -        authResponse.getEncryptedAssertions().add(encryptAssertion); +  } -      } catch (final EncryptionException e1) { -        log.warn("Can not encrypt the PVP2 assertion", e1); -        throw new InvalidAssertionEncryptionException(); +  private static String selectKeyEncryptionAlgorithm(X509Credential encryptionCredentials, +      IConfiguration authConfig) throws SamlSigningException { +    final PublicKey privatekey = encryptionCredentials.getPublicKey(); +    if (privatekey instanceof RSAPublicKey) { +      return authConfig.getBasicConfiguration( +          PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_RSA_ALG, +          PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_RSA); -      } +    } else if (privatekey instanceof ECPublicKey) { +      return authConfig.getBasicConfiguration( +          PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_EC_ALG, +          PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_EC);      } else { -      authResponse.getAssertions().add(assertion); +      log.warn("Could NOT evaluate the Private-Key type from " + encryptionCredentials.getEntityId() +          + " credential."); +      throw new SamlSigningException("internal.pvp.97", +          new Object[] { encryptionCredentials.getEntityId(), privatekey.getClass().getName() });      } -    return authResponse; +  } + +  private static X509Credential resolveEncryptionCredential(RequestAbstractType req, +      IPvp2MetadataProvider metadataProvider) throws InvalidAssertionEncryptionException { +    try { +      final List<KeyInfoProvider> keyInfoProvider = new ArrayList<>(); +      keyInfoProvider.add(new DSAKeyValueProvider()); +      keyInfoProvider.add(new RSAKeyValueProvider()); +      keyInfoProvider.add(new InlineX509DataProvider()); +      final KeyInfoCredentialResolver keyInfoCredentialResolver = new BasicProviderKeyInfoCredentialResolver( +          keyInfoProvider); + +      final PredicateRoleDescriptorResolver roleDescriptorResolver = new PredicateRoleDescriptorResolver( +          metadataProvider); +      roleDescriptorResolver.setRequireValidMetadata(true); +      roleDescriptorResolver.initialize(); + +      final MetadataCredentialResolver mdCredResolver = new MetadataCredentialResolver(); +      mdCredResolver.setRoleDescriptorResolver(roleDescriptorResolver); +      mdCredResolver.setKeyInfoCredentialResolver(keyInfoCredentialResolver); +      mdCredResolver.initialize(); + +      final CriteriaSet criteriaSet = new CriteriaSet(); +      criteriaSet.add(new EntityIdCriterion(req.getIssuer().getValue())); +      criteriaSet.add(new ProtocolCriterion(SAMLConstants.SAML20P_NS)); +      criteriaSet.add(new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME)); +      criteriaSet.add(new UsageCriterion(UsageType.ENCRYPTION)); + +      return (X509Credential) mdCredResolver.resolveSingle(criteriaSet); + +    } catch (final SecurityException | ComponentInitializationException | ResolverException e2) { +      log.warn("Can not extract the Assertion Encryption-Key from metadata", e2); +      throw new InvalidAssertionEncryptionException(); + +    }    }  } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/Pvp2AssertionBuilder.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/Pvp2AssertionBuilder.java index 922e7efe..b7b18f0f 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/Pvp2AssertionBuilder.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/Pvp2AssertionBuilder.java @@ -24,6 +24,8 @@ import java.util.ArrayList;  import java.util.Iterator;  import java.util.List; +import javax.naming.ConfigurationException; +  import at.gv.egiz.eaaf.core.api.data.EaafConstants;  import at.gv.egiz.eaaf.core.api.data.ILoALevelMapper;  import at.gv.egiz.eaaf.core.api.idp.IAuthData; @@ -86,17 +88,16 @@ public class Pvp2AssertionBuilder implements PvpConstants {    @Autowired    private ISubjectNameIdGenerator subjectNameIdGenerator; -    /**     * Build a PVP assertion as response for a SAML2 AttributeQuery request.     *     * @param issuerEntityID EnitiyID, which should be used for this IDP response -   * @param attrQuery AttributeQuery request from Service-Provider -   * @param attrList List of PVP response attributes -   * @param now Current time -   * @param validTo ValidTo time of the assertion -   * @param qaaLevel QAA level of the authentication -   * @param sessionIndex SAML2 SessionIndex, which should be included * +   * @param attrQuery      AttributeQuery request from Service-Provider +   * @param attrList       List of PVP response attributes +   * @param now            Current time +   * @param validTo        ValidTo time of the assertion +   * @param qaaLevel       QAA level of the authentication +   * @param sessionIndex   SAML2 SessionIndex, which should be included *     * @return PVP 2.1 Assertion     * @throws Pvp2Exception In case of an error     */ @@ -119,18 +120,21 @@ public class Pvp2AssertionBuilder implements PvpConstants {          validTo);    } -    /**     * Build a PVP 2.1 assertion as response of a SAML2 AuthnRequest.     * -   * @param issuerEntityID EnitiyID, which should be used for this IDP response -   * @param pendingReq Current processed pendingRequest DAO -   * @param authnRequest Current processed PVP AuthnRequest -   * @param authData AuthenticationData of the user, which is already authenticated -   * @param peerEntity SAML2 EntityDescriptor of the service-provider, which receives the response -   * @param date TimeStamp -   * @param assertionConsumerService SAML2 endpoint of the service-provider, which should be used -   * @param sloInformation Single LogOut information DAO +   * @param issuerEntityID           EnitiyID, which should be used for this IDP +   *                                 response +   * @param pendingReq               Current processed pendingRequest DAO +   * @param authnRequest             Current processed PVP AuthnRequest +   * @param authData                 AuthenticationData of the user, which is +   *                                 already authenticated +   * @param peerEntity               SAML2 EntityDescriptor of the +   *                                 service-provider, which receives the response +   * @param date                     TimeStamp +   * @param assertionConsumerService SAML2 endpoint of the service-provider, which +   *                                 should be used +   * @param sloInformation           Single LogOut information DAO     * @return PVP2 S-Profil Assertion     * @throws Pvp2Exception In case of an error     */ @@ -203,7 +207,6 @@ public class Pvp2AssertionBuilder implements PvpConstants {        }      } -      // load SPSS decriptor from service-provider metadata      final SPSSODescriptor spSsoDescriptor = peerEntity.getSPSSODescriptor(SAMLConstants.SAML20P_NS); @@ -217,7 +220,7 @@ public class Pvp2AssertionBuilder implements PvpConstants {        AttributeConsumingService attributeConsumingService = null;        if (aIdx != null) { -        idx = aIdx.intValue(); +        idx = aIdx;          attributeConsumingService = spSsoDescriptor.getAttributeConsumingServices().get(idx);        } else { @@ -231,8 +234,8 @@ public class Pvp2AssertionBuilder implements PvpConstants {        }        /* -       * TODO: maybe use first AttributeConsumingService if no is selected in request or on service -       * is marked as default +       * TODO: maybe use first AttributeConsumingService if no is selected in request +       * or on service is marked as default         *         */        if (attributeConsumingService == null) { @@ -244,7 +247,6 @@ public class Pvp2AssertionBuilder implements PvpConstants {        } -        if (attributeConsumingService != null) {          final Iterator<RequestedAttribute> it =              attributeConsumingService.getRequestAttributes().iterator(); @@ -268,7 +270,6 @@ public class Pvp2AssertionBuilder implements PvpConstants {                throw new UnprovideableAttributeException(reqAttribut.getName());              } -            } catch (final Pvp2Exception e) {              log.info("Attribute generation failed! for " + reqAttribut.getFriendlyName());              if (reqAttribut.isRequired()) { @@ -342,10 +343,10 @@ public class Pvp2AssertionBuilder implements PvpConstants {        subjectNameID.setFormat(nameIdFormat);      } -      String sessionIndex = null; -    // if request is a reauthentication and NameIDFormat match reuse old session information +    // if request is a reauthentication and NameIDFormat match reuse old session +    // information      if (StringUtils.isNotEmpty(authData.getNameID())          && StringUtils.isNotEmpty(authData.getNameIdFormat())          && nameIdFormat.equals(authData.getNameIdFormat())) { @@ -368,7 +369,8 @@ public class Pvp2AssertionBuilder implements PvpConstants {      // set 'recipient' attribute in subjectConformationData      subjectConfirmationData.setRecipient(assertionConsumerService.getLocation()); -    // set IP address of the user machine as 'Address' attribute in subjectConformationData +    // set IP address of the user machine as 'Address' attribute in +    // subjectConformationData      final String usersIpAddress =          pendingReq.getRawData(RequestImpl.DATAID_REQUESTER_IP_ADDRESS, String.class);      if (StringUtils.isNotEmpty(usersIpAddress)) { @@ -388,15 +390,15 @@ public class Pvp2AssertionBuilder implements PvpConstants {    /**     * Build generic part of PVP S-Profile Assertion.     * -   * @param issuer IDP EntityID -   * @param entityID Service Provider EntityID -   * @param date Timestamp -   * @param authnContextClassRef SAML2 AuthnContextClassReference -   * @param attrList List of attributes -   * @param subjectNameID SubjectNameId +   * @param issuer                  IDP EntityID +   * @param entityID                Service Provider EntityID +   * @param date                    Timestamp +   * @param authnContextClassRef    SAML2 AuthnContextClassReference +   * @param attrList                List of attributes +   * @param subjectNameID           SubjectNameId     * @param subjectConfirmationData SubjectConfirmationInformation -   * @param sessionIndex SessionIndex -   * @param isValidTo ValidTo Timestamp +   * @param sessionIndex            SessionIndex +   * @param isValidTo               ValidTo Timestamp     * @return PVP S-Profile Assertion     * @throws ConfigurationException In case on an error     */ diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/AuthnResponseBuilderTest.java b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/AuthnResponseBuilderTest.java new file mode 100644 index 00000000..98cf5f40 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/AuthnResponseBuilderTest.java @@ -0,0 +1,102 @@ +package at.gv.egiz.eaaf.modules.pvp2.idp.test; + +import java.io.IOException; + +import javax.xml.transform.TransformerException; + +import at.gv.egiz.eaaf.core.impl.idp.module.test.DummyAuthConfig; +import at.gv.egiz.eaaf.core.impl.utils.DomUtils; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.idp.exception.InvalidAssertionEncryptionException; +import at.gv.egiz.eaaf.modules.pvp2.idp.impl.builder.AuthResponseBuilder; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import at.gv.egiz.eaaf.modules.pvp2.test.binding.PostBindingTest; + +import org.apache.commons.lang3.RandomStringUtils; +import org.joda.time.DateTime; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.MarshallingException; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.saml.saml2.core.Assertion; +import org.opensaml.saml.saml2.core.RequestAbstractType; +import org.opensaml.saml.saml2.core.Response; +import org.springframework.beans.factory.annotation.Autowired; +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 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 AuthnResponseBuilderTest { + +  @Autowired private DummyAuthConfig authConfig; +  @Autowired private PvpMetadataResolverFactory metadataResolverFactory; + +  /** +   * JUnit class initializer. +   * +   * @throws Exception In case of an OpenSAML3 initialization error +   */ +  @BeforeClass +  public static void classInitializer() throws Exception { +    EaafOpenSaml3xInitializer.eaafInitialize(); + +  } + +  @Test +  public void encryptedAssertion() throws InvalidAssertionEncryptionException, Pvp2MetadataException, +      XMLParserException, UnmarshallingException, MarshallingException, TransformerException, IOException { +    final String issuerEntityID = RandomStringUtils.randomAlphabetic(15); + +    final IPvp2MetadataProvider metadataProvider = +        metadataResolverFactory.createMetadataProvider( +            "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); + +    final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( +        XMLObjectProviderRegistrySupport.getParserPool(), +        PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml")); +    authnReq.setID("_" + RandomStringUtils.randomAlphanumeric(10)); + +    final Assertion assertion = (Assertion) XMLObjectSupport.unmarshallFromInputStream( +        XMLObjectProviderRegistrySupport.getParserPool(), +        PostBindingTest.class.getResourceAsStream("/data/Assertion_1.xml")); + +    //build response +    final DateTime now = DateTime.now(); +    final Response response = AuthResponseBuilder.buildResponse( +        metadataProvider, issuerEntityID, authnReq, +        now, assertion, authConfig); + + +    //validate +    Assert.assertNotNull("SAML2 response is null", response); +    Assert.assertTrue("Assertion not null", response.getAssertions().isEmpty()); +    Assert.assertNotNull("Enc. assertion is null", response.getEncryptedAssertions()); +    Assert.assertFalse("Enc. assertion is empty", response.getEncryptedAssertions().isEmpty()); +    Assert.assertEquals("# enc. assertions wrong", 1, response.getEncryptedAssertions().size()); + +    Assert.assertEquals("InResponseTo", authnReq.getID(), response.getInResponseTo()); +    Assert.assertEquals("Issuer EntityId", issuerEntityID, response.getIssuer().getValue()); +    Assert.assertNotNull("ResponseId is null", response.getID()); +    Assert.assertFalse("ResponseId is emptry", response.getID().isEmpty()); + +    final Element responseElement = XMLObjectSupport.getMarshaller(response).marshall(response); +    final String xmlResp = DomUtils.serializeNode(responseElement); +    Assert.assertNotNull("XML response is null", xmlResp); +    Assert.assertFalse("XML response is empty", xmlResp.isEmpty()); + +  } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_1.props b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_1.props new file mode 100644 index 00000000..6324f190 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_1.props @@ -0,0 +1,14 @@ +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= + +pvp2.assertion.encryption.active=true + +client.http.connection.timeout.socket=2 +client.http.connection.timeout.connection=2 +client.http.connection.timeout.request=2
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/Assertion_1.xml b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/Assertion_1.xml new file mode 100644 index 00000000..7c45b5fa --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/Assertion_1.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +	<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> diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/AuthRequest_without_sig_1.xml b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/AuthRequest_without_sig_1.xml new file mode 100644 index 00000000..ef35ea92 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/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_idp/src/test/resources/data/junit.jks b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/junit.jksBinary files differ new file mode 100644 index 00000000..b5262cb8 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/junit.jks diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/pvp_metadata_junit_keystore.xml b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/pvp_metadata_junit_keystore.xml new file mode 100644 index 00000000..52549a88 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/pvp_metadata_junit_keystore.xml @@ -0,0 +1,125 @@ +<?xml version="1.0" encoding="UTF-8"?> +<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_2e23ca9b2ba4dc9eef15187830d07ff0" entityID="https://demo.egiz.gv.at/demoportal_demologin/" validUntil="2020-02-05T06:41:42.966Z"> +	<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="#_2e23ca9b2ba4dc9eef15187830d07ff0"> +				<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/2001/04/xmlenc#sha256"/> +				<ds:DigestValue>Jy/c0ZvVJSfWzSoAcxDx/o+T5W61vvNJNqTFz2o+ILc=</ds:DigestValue> +			</ds:Reference> +		</ds:SignedInfo> +		<ds:SignatureValue>chMxIdwrPvr78j3oTtgS7udbydy9kye1bbeQ4jm2GeFKUfxvJqY+vt9MjVnWFeR4c16gd80BjZJ6xxD5i5Ifci3YtxeKSxq0ttH/xZYEhJZkD/0NrGUhSvNV9zuLAz3uGk/LJ+2JxRq7dbnW4n9MtGuYhea8OW9/Pr1xI1KyskQS76NZDsGjjfnFWbFXahLoQZULU4Ke3SfZVqLATTn0J34RZnjNH3QieY3LhRzOVu/I5yeZtnLgUS6dg0Gab9DA/pdNFaC632iaE5QCXJmhgpqkjbkayO9e8N93YGFjbszhU1Kws5OUGjXjfCZwezLeOUZoKEfo5c+4+zEaTrEQjg==</ds:SignatureValue> +		<ds:KeyInfo> +			<ds:X509Data> +				<ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> +			</ds:X509Data> +		</ds:KeyInfo> +	</ds:Signature> +	<md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> +		<md:KeyDescriptor use="signing"> +			<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> +				<ds:X509Data> +					<ds:X509Certificate>MIIC+jCCAeKgAwIBAgIEXjF+fTANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJB +VDENMAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxETAPBgNVBAMMCE1ldGFk +YXRhMB4XDTIwMDEyOTEyNDU0OVoXDTI2MDEyODEyNDU0OVowPzELMAkGA1UEBhMC +QVQxDTALBgNVBAcMBEVHSVoxDjAMBgNVBAoMBWpVbml0MREwDwYDVQQDDAhNZXRh +ZGF0YTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK230G3dxNbNlSYA +O5Kx/Js0aBAgxMt7q9m+dA35fK/dOvF/GjrqjWsMCnax+no9gLnq6x0gXiJclz6H +rp/YDOfLrJjMpNL/r0FWT947vbnEj7eT8TdY5d6Yi8AZulZmjiCI5nbZh2zwrP4+ +WqRroLoPhXQj8mDyp26M4xHBBUhLMRc2HV4S+XH4uNZ/vTmb8vBg31XGHCY33gl7 +/KA54JNGxJdN8Dxv6yHYsm91ZfVrX39W0iYLUNhUCkolwuQmjDVfrExM8BTLIONb +f+erJoCm3A9ghZyDYRQ/e69/UEUqDa6XOzykr88INkQscEiAXCDS+EBPMpKo+t3l +PIA9r7kCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAh/2mg4S03bdZy1OVtEAudBT9 +YZb9OF34hxPtNbkB/V04wSIg1d4TBr5KDhV7CdiUOxPZzHpS8LUCgfGX306FB6NX +zh/b67uTOPaE72AB4VIT/Np0fsM7k5WhG9k9NoprIGiqCz2lXcfpZiT+LtSO1vWS +YI87wR9KOSWjcw/5i5qZIAJuwvLCQj5JtUsmrhHK75222J3TJf4dS/gfN4xfY2rW +9vcXtH6//8WdWp/zx9V7Z1ZsDb8TDKtBCEGuFDgVeU5ScKtVq8qRoUKD3Ve76cZi +purO3KrRrVAuZP2EfLkZdHEHqe8GPigNnZ5kTn8V2VJ3iRAQ73hpJRR98tFd0A==</ds:X509Certificate> +				</ds:X509Data> +                <ds:X509Data> +                  <ds:X509Certificate>MIIBbTCCARKgAwIBAgIEXjF+qTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +HhcNMjAwMTI5MTI0NjMzWhcNMjcwMTI4MTI0NjMzWjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASRt7gZRrr4rSEE7Q922oKQJF+mlkwC +LZnv8ZzHtH54s4VdyQFIBjQF1PPf9PTn+5tid8QJehZPndcoeD7J8fPJMAoGCCqG +SM49BAMCA0kAMEYCIQDFUO0owvqMVRO2FmD+vb8mqJBpWCE6Cl5pEHaygTa5LwIh +ANsmjI2azWiTSFjb7Ou5fnCfbeiJUP0s66m8qS4rYl9L +                </ds:X509Certificate> +              </ds:X509Data> +			</ds:KeyInfo> +		</md:KeyDescriptor> +		<md:KeyDescriptor use="encryption"> +			<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> +				<ds:X509Data> +					<ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> +				</ds:X509Data> +			</ds:KeyInfo> +		</md:KeyDescriptor> +		<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat> +		<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/post" index="0" isDefault="true"/> +		<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/redirect" index="1"/> +		<md:AttributeConsumingService index="0" isDefault="true"> +			<md:ServiceName xml:lang="en">Default Service</md:ServiceName> +			<md:RequestedAttribute 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" isRequired="true"/> +			<md:RequestedAttribute 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" isRequired="true"/> +			<md:RequestedAttribute 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" isRequired="true"/> +			<md:RequestedAttribute 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" isRequired="true"/> +			<md:RequestedAttribute 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" isRequired="true"/> +			<md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.76" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +			<md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-FULL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.84" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +			<md:RequestedAttribute FriendlyName="MANDATE-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.68" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +			<md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN" Name="urn:oid:1.2.40.0.10.2.1.1.261.100" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +			<md:RequestedAttribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> +			<md:RequestedAttribute 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" isRequired="true"/> +			<md:RequestedAttribute FriendlyName="MANDATE-TYPE-OID" Name="urn:oid:1.2.40.0.10.2.1.1.261.106" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +			<md:RequestedAttribute FriendlyName="EID-IDENTITY-LINK" Name="urn:oid:1.2.40.0.10.2.1.1.261.38" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +			<md:RequestedAttribute FriendlyName="EID-CITIZEN-QAA-EIDAS-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.108" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> +		</md:AttributeConsumingService> +	</md:SPSSODescriptor> +	<md:Organization> +		<md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName> +		<md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName> +		<md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL> +	</md:Organization> +	<md:ContactPerson contactType="technical"> +		<md:Company>E-Government Innovationszentrum</md:Company> +		<md:GivenName>Lenz</md:GivenName> +		<md:SurName>Thomas</md:SurName> +		<md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress> +		<md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber> +	</md:ContactPerson> +</md:EntityDescriptor> diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_core.beans.xml b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_core.beans.xml new file mode 100644 index 00000000..375224bb --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_core.beans.xml @@ -0,0 +1,25 @@ +<?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" /> +   +  <bean id="httpClientFactory" +        class="at.gv.egiz.eaaf.core.impl.utils.HttpClientFactory" /> + +</beans>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_pvp.beans.xml b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_pvp.beans.xml new file mode 100644 index 00000000..aac94041 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_pvp.beans.xml @@ -0,0 +1,20 @@ +<?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"/>   +  <import resource="classpath:/eaaf_pvp.beans.xml"/> + +  <bean id="dummyCredentialProvider" +        class="at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider" /> + +  +</beans>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_sp/pom.xml b/eaaf_modules/eaaf_module_pvp2_sp/pom.xml index 51219563..5b16a151 100644 --- a/eaaf_modules/eaaf_module_pvp2_sp/pom.xml +++ b/eaaf_modules/eaaf_module_pvp2_sp/pom.xml @@ -54,21 +54,20 @@        </plugin>        <!-- enable co-existence of testng and junit --> -			<plugin> -				<artifactId>maven-surefire-plugin</artifactId> -				<version>${surefire.version}</version> -				<configuration> -					<threadCount>1</threadCount> -					<argLine>--add-modules java.xml.bind</argLine> -				</configuration> -				<dependencies> -					<dependency> -						<groupId>org.apache.maven.surefire</groupId> -						<artifactId>surefire-junit47</artifactId> -						<version>${surefire.version}</version> -					</dependency> -				</dependencies> -			</plugin> +      <plugin> +        <artifactId>maven-surefire-plugin</artifactId> +        <version>${surefire.version}</version> +        <configuration> +          <threadCount>1</threadCount>           +        </configuration> +        <dependencies> +          <dependency> +            <groupId>org.apache.maven.surefire</groupId> +            <artifactId>surefire-junit47</artifactId> +            <version>${surefire.version}</version> +          </dependency> +        </dependencies> +      </plugin>      </plugins>    </build> @@ -470,7 +470,13 @@          <scope>test</scope>          <type>test-jar</type>        </dependency> -     +      <dependency> +        <groupId>at.gv.egiz.eaaf</groupId> +        <artifactId>eaaf_module_pvp2_core</artifactId> +        <version>${egiz.eaaf.version}</version> +        <scope>test</scope> +        <type>test-jar</type> +      </dependency>          </dependencies>    </dependencyManagement>    <dependencies> @@ -498,6 +504,21 @@          <version>2.7</version>        </plugin> +      <plugin> +        <artifactId>maven-surefire-plugin</artifactId> +        <version>${surefire.version}</version> +        <configuration> +          <threadCount>1</threadCount> +        </configuration> +        <dependencies> +          <dependency> +            <groupId>org.apache.maven.surefire</groupId> +            <artifactId>surefire-junit47</artifactId> +            <version>${surefire.version}</version> +          </dependency> +        </dependencies> +      </plugin> +        <!-- Code quality checks -->        <plugin>          <groupId>org.apache.maven.plugins</groupId> | 
