diff options
Diffstat (limited to 'eaaf_modules')
43 files changed, 2838 insertions, 213 deletions
diff --git a/eaaf_modules/eaaf_module_pvp2_core/pom.xml b/eaaf_modules/eaaf_module_pvp2_core/pom.xml index 318fa500..a81ad889 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/pom.xml +++ b/eaaf_modules/eaaf_module_pvp2_core/pom.xml @@ -66,6 +66,12 @@ </dependency> <dependency> <groupId>at.gv.egiz.eaaf</groupId> + <artifactId>eaaf_core_utils</artifactId> + <scope>test</scope> + <type>test-jar</type> + </dependency> + <dependency> + <groupId>at.gv.egiz.eaaf</groupId> <artifactId>eaaf-core</artifactId> <scope>test</scope> <type>test-jar</type> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlAssertionValidationExeption.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlAssertionValidationExeption.java new file mode 100644 index 00000000..9ba7ccb2 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlAssertionValidationExeption.java @@ -0,0 +1,28 @@ +package at.gv.egiz.eaaf.modules.pvp2.exception; + +public class SamlAssertionValidationExeption extends SamlMessageValidationException { + + private static final long serialVersionUID = 2054578783736917817L; + + /** + * In case of a SAML2-Assertion validation error. + * + * @param messageId errorId + * @param parameters Message parameters + */ + public SamlAssertionValidationExeption(String messageId, Object[] parameters) { + super(messageId, parameters); + } + + /** + * In case of a SAML2-Assertion validation error. + * + * @param messageId errorId + * @param parameters Message parameters + * @param wrapped Exception that was thrown + */ + public SamlAssertionValidationExeption(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/SamlMessageValidationException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlMessageValidationException.java index 774d0927..56d8c4a5 100644 --- 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 @@ -4,6 +4,24 @@ public class SamlMessageValidationException extends Pvp2Exception { private static final long serialVersionUID = 2545822499416501014L; + /** + * In case of a SAML2-message validation error. + * + * @param messageId errorId + * @param parameters Message parameters + */ + public SamlMessageValidationException(String messageId, Object[] parameters) { + super(messageId, parameters); + + } + + /** + * In case of a SAML2-message validation error. + * + * @param messageId errorId + * @param parameters Message parameters + * @param wrapped Exception that was thrown + */ 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/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 0ffa3789..f77243c2 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 @@ -22,20 +22,20 @@ package at.gv.egiz.eaaf.modules.pvp2.impl.message; import java.io.IOException; import java.io.Serializable; +import javax.annotation.Nonnull; 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 { @@ -57,13 +57,9 @@ public class InboundMessage implements InboundMessageInterface, Serializable { * @return EntityDescriptor from metadata * @throws NoMetadataInformationException In case of an error */ - public EntityDescriptor getEntityMetadata(final IPvp2MetadataProvider metadataProvider) + public EntityDescriptor getEntityMetadata(@Nonnull final IPvp2MetadataProvider metadataProvider) throws NoMetadataInformationException { try { - if (metadataProvider == null) { - throw new NullPointerException("No PVP MetadataProvider found."); - } - return metadataProvider.getEntityDescriptor(this.entityID); } catch (final ResolverException e) { 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 b9d0161f..902f84c7 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 @@ -447,13 +447,6 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec 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); - } } 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 a3154b0d..c476846b 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 @@ -134,10 +134,7 @@ public class Saml2Utils { @Nonnull EaafX509Credential signingCredential, boolean injectCertificate) throws SamlSigningException { try { - final String usedSigAlg = getKeyOperationAlgorithmFromCredential(signingCredential, - PvpConstants.DEFAULT_SIGNING_METHODE_RSA, - PvpConstants.DEFAULT_SIGNING_METHODE_EC); - + final String usedSigAlg = signingCredential.getSignatureAlgorithmForSigning(); final Signature signature = createSignature(signingCredential, usedSigAlg, injectCertificate); toSign.setSignature(signature); 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 2e26de7f..e0a3ab8e 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 @@ -19,6 +19,9 @@ package at.gv.egiz.eaaf.modules.pvp2.impl.verification; +import java.util.ArrayList; +import java.util.List; + import javax.xml.namespace.QName; import javax.xml.transform.dom.DOMSource; import javax.xml.validation.Schema; @@ -26,27 +29,45 @@ import javax.xml.validation.Validator; import at.gv.egiz.eaaf.core.exceptions.EaafProtocolException; import at.gv.egiz.eaaf.core.exceptions.InvalidProtocolRequestException; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlAssertionValidationExeption; import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException; import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage; import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileRequest; import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileResponse; import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; import org.opensaml.core.criterion.EntityIdCriterion; import org.opensaml.saml.common.xml.SAMLConstants; import org.opensaml.saml.common.xml.SAMLSchemaBuilder; import org.opensaml.saml.common.xml.SAMLSchemaBuilder.SAML1Version; import org.opensaml.saml.criterion.EntityRoleCriterion; import org.opensaml.saml.criterion.ProtocolCriterion; +import org.opensaml.saml.saml2.core.Assertion; +import org.opensaml.saml.saml2.core.Audience; +import org.opensaml.saml.saml2.core.AudienceRestriction; +import org.opensaml.saml.saml2.core.Conditions; +import org.opensaml.saml.saml2.core.EncryptedAssertion; import org.opensaml.saml.saml2.core.RequestAbstractType; +import org.opensaml.saml.saml2.core.Response; +import org.opensaml.saml.saml2.core.StatusCode; import org.opensaml.saml.saml2.core.StatusResponseType; +import org.opensaml.saml.saml2.encryption.Decrypter; +import org.opensaml.saml.saml2.encryption.EncryptedElementTypeEncryptedKeyResolver; import org.opensaml.saml.saml2.metadata.IDPSSODescriptor; import org.opensaml.saml.saml2.metadata.SPSSODescriptor; import org.opensaml.saml.security.impl.SAMLSignatureProfileValidator; import org.opensaml.security.credential.UsageType; import org.opensaml.security.criteria.UsageCriterion; +import org.opensaml.xmlsec.encryption.support.ChainingEncryptedKeyResolver; +import org.opensaml.xmlsec.encryption.support.DecryptionException; +import org.opensaml.xmlsec.encryption.support.EncryptedKeyResolver; +import org.opensaml.xmlsec.encryption.support.InlineEncryptedKeyResolver; +import org.opensaml.xmlsec.encryption.support.SimpleRetrievalMethodEncryptedKeyResolver; +import org.opensaml.xmlsec.keyinfo.impl.StaticKeyInfoCredentialResolver; import org.opensaml.xmlsec.signature.support.SignatureException; import org.opensaml.xmlsec.signature.support.SignatureTrustEngine; import org.springframework.beans.factory.annotation.Autowired; @@ -54,18 +75,40 @@ import org.w3c.dom.Element; import org.xml.sax.SAXException; import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.net.BasicURLComparator; +import net.shibboleth.utilities.java.support.net.URIException; import net.shibboleth.utilities.java.support.resolver.CriteriaSet; @Slf4j public class SamlVerificationEngine { private static SAMLSchemaBuilder schemaBuilder = new SAMLSchemaBuilder(SAML1Version.SAML_11); + private static final String ERROR_03 = "internal.pvp.03"; + private static final String ERROR_10 = "internal.pvp.10"; + private static final String ERROR_14 = "internal.pvp.14"; + private static final String ERROR_15 = "internal.pvp.15"; + private static final String ERROR_16 = "internal.pvp.16"; + private static final String ERROR_17 = "internal.pvp.17"; + + private static final Object SIG_VAL_ERROR_MSG = "Signature verification return false"; + + /** + * 5 allow 3 minutes time jitter in before validation. + */ + private static final int TIME_JITTER = 3; + + + + + @Autowired(required = true) IPvp2MetadataProvider metadataProvider; /** * Verify signature of a signed SAML2 object. * + *<p>This method only perform signature verification</p> + * * @param msg SAML2 message * @param sigTrustEngine TrustEngine * @throws org.opensaml.xml.security.SecurityException In case of invalid @@ -85,7 +128,7 @@ public class SamlVerificationEngine { } else { log.warn("SAML2 message type: {} not supported", msg.getClass().getName()); - throw new EaafProtocolException("9999", null); + throw new EaafProtocolException("internal.pvp.99", null); } @@ -94,13 +137,14 @@ public class SamlVerificationEngine { throw e; } - log.debug( - "PVP2X message validation FAILED. Relead metadata for entityID: " + msg.getEntityID()); + log.debug("PVP2X message validation FAILED. Relead metadata for entityID: {}", + msg.getEntityID()); if (metadataProvider == null || !(metadataProvider instanceof IRefreshableMetadataProvider) || !((IRefreshableMetadataProvider) metadataProvider) .refreshMetadataProvider(msg.getEntityID())) { throw e; + } else { log.trace("PVP2X metadata reload finished. Check validate message again."); @@ -108,30 +152,261 @@ public class SamlVerificationEngine { && ((PvpSProfileRequest) msg).getSamlRequest() instanceof RequestAbstractType) { verifyRequest((RequestAbstractType) ((PvpSProfileRequest) msg).getSamlRequest(), sigTrustEngine); + } else { verifyIdpResponse(((PvpSProfileResponse) msg).getResponse(), sigTrustEngine); + } } log.trace("Second PVP2X message validation finished"); + } } + /** + * Verify the signature of a signed SAML2 object from ServiceProvider. + * + * @param samlObj signed Response from ServiceProvider + * @param sigTrustEngine TrustEngie for verification + * @throws InvalidProtocolRequestException In case of a verification error + */ public void verifySloResponse(final StatusResponseType samlObj, final SignatureTrustEngine sigTrustEngine) throws InvalidProtocolRequestException { verifyResponse(samlObj, sigTrustEngine, SPSSODescriptor.DEFAULT_ELEMENT_NAME); } + /** + * Verify the signature of a signed SAML2 object from IDP. + * + * <p>This method only perform signature verification</p> + * + * @param samlObj signed SAML2 message from IDP + * @param sigTrustEngine TrustEngie for verification + * @throws InvalidProtocolRequestException In case of a verification error + */ public void verifyIdpResponse(final StatusResponseType samlObj, final SignatureTrustEngine sigTrustEngine) throws InvalidProtocolRequestException { verifyResponse(samlObj, sigTrustEngine, IDPSSODescriptor.DEFAULT_ELEMENT_NAME); } + /** + * Validate a PVP response and all included assertions. + * + *<p> + * If the SAML2 assertions are encrypted than they will be decrypted afterwards + * </p> + * + *<p>This method <b>DOES NOT</b> verify the <i>Destination</i> attribute in SAML2 Response</p> + * + * @param samlResp SAML2 Response object + * @param assertionDecryption Assertion decryption-credentials to decrypt SAML2 + * assertions + * @param spEntityID EntityId of the SAML2 client + * @param loggerName Name for logging purposes + * @throws SamlAssertionValidationExeption In case of a validation error + */ + public void validateAssertion(Response samlResp, + EaafX509Credential assertionDecryption, String spEntityID, String loggerName) + throws SamlAssertionValidationExeption { + validateAssertion(samlResp, assertionDecryption, spEntityID, loggerName, true); + + } + + /** + * Validate each SAML2 assertions in a SAML2 response. <br> + * <p> + * If the SAML2 assertions are encrypted than they will be decrypted afterwards + * </p> + * + *<p>This method <b>DOES NOT</b> verify the <i>Destination</i> attribute in SAML2 Response</p> + * + * @param samlResp SAML2 Response object + * @param assertionDecryption Assertion decryption-credentials to decrypt SAML2 + * assertions + * @param spEntityID EntityId of the SAML2 client + * @param loggerName Name for logging purposes + * @param validateDateTime <code>true</code> if <i>getIssueInstant</i> + * attribute should be validated, otherwise false + * @throws SamlAssertionValidationExeption In case of a validation error + */ + public void validateAssertion(Response samlResp, EaafX509Credential assertionDecryption, + String spEntityID, String loggerName, boolean validateDateTime) + throws SamlAssertionValidationExeption { + try { + // pre-validate the SAML2 response + assertionPreValidation(samlResp, loggerName, validateDateTime); + + // get Assertion from response and decrypt them if the are encrypted + final List<Assertion> saml2assertions = getOrDecryptAndGetAssertions(samlResp, assertionDecryption); + + // validate each assertion + final List<Assertion> validatedassertions = new ArrayList<>(); + for (final Assertion saml2assertion : saml2assertions) { + if (internalAssertionValidation(saml2assertion, spEntityID, validateDateTime)) { + log.debug("Add valid Assertion:" + saml2assertion.getID()); + validatedassertions.add(saml2assertion); + + } else { + log.warn("Remove non-valid Assertion:" + saml2assertion.getID()); + } + + } + + if (validatedassertions.isEmpty()) { + log.info("No valid PVP 2.1 assertion received."); + throw new SamlAssertionValidationExeption(ERROR_15, new Object[] { loggerName }); + + } + + samlResp.getAssertions().clear(); + samlResp.getEncryptedAssertions().clear(); + samlResp.getAssertions().addAll(validatedassertions); + + } catch (final DecryptionException e) { + log.warn("Assertion decrypt FAILED.", e); + throw new SamlAssertionValidationExeption(ERROR_16, + new Object[] { e.getMessage() }, e); + +// } catch (final ConfigurationException e) { +// throw new AssertionValidationExeption("pvp.12", +// new Object[]{loggerName, e.getMessage()}, e); + } + } + + private boolean internalAssertionValidation(Assertion saml2assertion, String spEntityId, + boolean validateDateTime) { + boolean isAssertionValid = true; + try { + // schema validation + performSchemaValidation(saml2assertion.getDOM()); + + // validate DateTime conditions + final Conditions conditions = saml2assertion.getConditions(); + if (conditions != null) { + final DateTime notbefore = conditions.getNotBefore().minusMinutes(5); + final DateTime notafter = conditions.getNotOnOrAfter(); + if (validateDateTime + && (notbefore.isAfterNow() || notafter.isBeforeNow())) { + isAssertionValid = false; + log.info("Assertion with ID:{} is out of Date. [ Current:{} NotBefore:{} NotAfter:{} ]", + saml2assertion.getID(), new DateTime(), notbefore, notafter); + + } + + // validate audienceRestrictions are valid for this SP + final List<AudienceRestriction> audienceRest = conditions.getAudienceRestrictions(); + if (audienceRest == null || audienceRest.size() == 0) { + log.info("Assertion with ID:{} has not 'AudienceRestriction' element", + saml2assertion.getID()); + isAssertionValid = false; + + } else { + for (final AudienceRestriction el : audienceRest) { + for (final Audience audience : el.getAudiences()) { + if (!urlCompare(spEntityId, audience.getAudienceURI())) { + log.info("Assertion with ID:{} 'AudienceRestriction' is not valid.", + saml2assertion.getID()); + isAssertionValid = false; + + } + } + } + } + + } else { + log.info("Assertion with ID:{} contains not 'Conditions' element", + saml2assertion.getID()); + isAssertionValid = false; + + } + + } catch (final SchemaValidationException e) { + isAssertionValid = false; + log.info("Assertion with ID:{} FAILED Schema validation. Msg: {}", + saml2assertion.getID(), e.getMessage()); + + } catch (final URIException e) { + isAssertionValid = false; + log.info("Assertion with ID:{} FAILED AudienceRestriction validation. Msg:", + saml2assertion.getID(), e.getMessage()); + + } + + return isAssertionValid; + + } + + private List<Assertion> getOrDecryptAndGetAssertions(Response samlResp, + EaafX509Credential assertionDecryption) throws DecryptionException { + final List<Assertion> saml2assertions = new ArrayList<>(); + + // check encrypted Assertions + final List<EncryptedAssertion> encryAssertionList = samlResp.getEncryptedAssertions(); + if (encryAssertionList != null && encryAssertionList.size() > 0) { + // decrypt assertions + log.debug("Found encryped assertion. Start decryption ..."); + final List<EncryptedKeyResolver> listOfKeyResolvers = new ArrayList<>(); + listOfKeyResolvers.add(new InlineEncryptedKeyResolver()); + listOfKeyResolvers.add(new EncryptedElementTypeEncryptedKeyResolver()); + listOfKeyResolvers.add(new SimpleRetrievalMethodEncryptedKeyResolver()); + + final Decrypter samlDecrypter = new Decrypter(null, + new StaticKeyInfoCredentialResolver(assertionDecryption), + new ChainingEncryptedKeyResolver(listOfKeyResolvers)); + + for (final EncryptedAssertion encAssertion : encryAssertionList) { + saml2assertions.add(samlDecrypter.decrypt(encAssertion)); + + } + log.debug("Assertion decryption finished. "); + + } + + saml2assertions.addAll(samlResp.getAssertions()); + + return saml2assertions; + + } + + private void performSchemaValidation(final Element source) throws SchemaValidationException { + + String err = null; + try { + final Schema test = schemaBuilder.getSAMLSchema(); + final Validator val = test.newValidator(); + val.validate(new DOMSource(source)); + log.debug("Schema validation check done OK"); + return; + + } catch (final SAXException e) { + err = e.getMessage(); + if (log.isDebugEnabled() || log.isTraceEnabled()) { + log.warn("Schema validation FAILED with exception:", e); + } else { + log.warn("Schema validation FAILED with message: " + e.getMessage()); + } + + } catch (final Exception e) { + err = e.getMessage(); + if (log.isDebugEnabled() || log.isTraceEnabled()) { + log.warn("Schema validation FAILED with exception:", e); + } else { + log.warn("Schema validation FAILED with message: " + e.getMessage()); + } + + } + + throw new SchemaValidationException(ERROR_03, new Object[] { err }); + + } + private void verifyResponse(final StatusResponseType samlObj, final SignatureTrustEngine sigTrustEngine, final QName defaultElementName) throws InvalidProtocolRequestException { + final SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator(); try { profileValidator.validate(samlObj.getSignature()); @@ -139,10 +414,10 @@ public class SamlVerificationEngine { } catch (final SignatureException e) { log.warn("Signature is not conform to SAML signature profile", e); - throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); + throw new InvalidProtocolRequestException(ERROR_10, new Object[] {e.getMessage() }, e); } catch (final SchemaValidationException e) { - throw new InvalidProtocolRequestException("pvp2.22", new Object[] { e.getMessage() }); + throw new InvalidProtocolRequestException(ERROR_03, new Object[] { e.getMessage() }, e); } @@ -154,11 +429,14 @@ public class SamlVerificationEngine { try { if (!sigTrustEngine.validate(samlObj.getSignature(), criteriaSet)) { - throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); + throw new InvalidProtocolRequestException(ERROR_10, new Object[] {SIG_VAL_ERROR_MSG}); + } + } catch (final org.opensaml.security.SecurityException e) { log.warn("PVP2x message signature validation FAILED.", e); - throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); + throw new InvalidProtocolRequestException(ERROR_10, new Object[] {e.getMessage()}, e); + } } @@ -171,10 +449,10 @@ public class SamlVerificationEngine { } catch (final SignatureException e) { log.warn("Signature is not conform to SAML signature profile", e); - throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); + throw new InvalidProtocolRequestException(ERROR_10, new Object[] {e.getMessage()}, e); } catch (final SchemaValidationException e) { - throw new InvalidProtocolRequestException("pvp2.22", new Object[] { e.getMessage() }); + throw new InvalidProtocolRequestException(ERROR_03, new Object[] { e.getMessage() }, e); } @@ -186,44 +464,53 @@ public class SamlVerificationEngine { try { if (!sigTrustEngine.validate(samlObj.getSignature(), criteriaSet)) { - throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); + throw new InvalidProtocolRequestException(ERROR_10, new Object[] {SIG_VAL_ERROR_MSG}); + } } catch (final org.opensaml.security.SecurityException e) { log.warn("PVP2x message signature validation FAILED.", e); - throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); + throw new InvalidProtocolRequestException(ERROR_10, new Object[] {e.getMessage()}, e); + } + } - protected void performSchemaValidation(final Element source) throws SchemaValidationException { + private void assertionPreValidation(Response samlResp, String loggerName, boolean validateDateTime) + throws SamlAssertionValidationExeption { + if (samlResp.getStatus().getStatusCode().getValue().equals(StatusCode.SUCCESS)) { + // validate response issueInstant + final DateTime issueInstant = samlResp.getIssueInstant(); + if (issueInstant == null) { + log.warn("PVP response does not include a 'IssueInstant' attribute"); + throw new SamlAssertionValidationExeption(ERROR_14, + new Object[] { loggerName, "'IssueInstant' attribute is not included" }); - String err = null; - try { - final Schema test = schemaBuilder.getSAMLSchema(); - final Validator val = test.newValidator(); - val.validate(new DOMSource(source)); - log.debug("Schema validation check done OK"); - return; - - } catch (final SAXException e) { - err = e.getMessage(); - if (log.isDebugEnabled() || log.isTraceEnabled()) { - log.warn("Schema validation FAILED with exception:", e); - } else { - log.warn("Schema validation FAILED with message: " + e.getMessage()); } + if (validateDateTime && issueInstant.minusMinutes(TIME_JITTER).isAfterNow()) { + log.warn("PVP response: IssueInstant DateTime is not valid anymore."); + throw new SamlAssertionValidationExeption(ERROR_14, + new Object[] { loggerName, "'IssueInstant' Time is not valid any more" }); - } catch (final Exception e) { - err = e.getMessage(); - if (log.isDebugEnabled() || log.isTraceEnabled()) { - log.warn("Schema validation FAILED with exception:", e); - } else { - log.warn("Schema validation FAILED with message: " + e.getMessage()); } - } + } else { + log.info("PVP 2.x assertion includes an error. Receive errorcode " + + samlResp.getStatus().getStatusCode().getValue()); + throw new SamlAssertionValidationExeption(ERROR_17, + new Object[] { loggerName, + samlResp.getIssuer().getValue(), + samlResp.getStatus().getStatusCode().getValue(), + samlResp.getStatus().getStatusMessage() != null + ? samlResp.getStatus().getStatusMessage().getMessage() + : " no status message" }); - throw new SchemaValidationException("pvp2.22", new Object[] { err }); + } + } + private static boolean urlCompare(String url1, String url2) throws URIException { + final BasicURLComparator comparator = new BasicURLComparator(); + comparator.setCaseInsensitive(false); + return comparator.compare(url1, url2); } } 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 8a91c68c..824f17d4 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 @@ -12,6 +12,10 @@ 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} +internal.pvp.14=SAML2 assertion validator: {0} found an error: Reason {1} +internal.pvp.15=SAML2 assertion validator: {0} find NO valid assertion in SAML2 response. +internal.pvp.16=Decryption of SAML2 assertion FAILED with reason: {0} +internal.pvp.17=SAML2 assertion validator:{0} find invalid PVP Response from Issuer:{1}. StatusCodes:{2} Msg:{3} pvp2.21=Signature validation of SAML2 Authn. request failed. Reason: {0} pvp2.22=Validation of SAML2 Authn. request failed. Reason: {0} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/CredentialProviderTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/CredentialProviderTest.java index 3ba4629e..22ee389f 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/CredentialProviderTest.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/CredentialProviderTest.java @@ -28,7 +28,7 @@ import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration({ - "/spring/test_eaaf_core_spring_config.beans.xml", + "/spring/test_eaaf_core_map_config.beans.xml", "/spring/SpringTest-context_lazy.xml" }) @TestPropertySource(locations = {"/config/config_1.props"}) diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/Pvp2SProfileCoreSpringResourceProviderTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/Pvp2SProfileCoreSpringResourceProviderTest.java new file mode 100644 index 00000000..67c59dec --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/Pvp2SProfileCoreSpringResourceProviderTest.java @@ -0,0 +1,56 @@ +package at.gv.egiz.eaaf.modules.pvp2.test; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.io.IOUtils; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.BlockJUnit4ClassRunner; +import org.springframework.core.io.Resource; + +import at.gv.egiz.eaaf.core.test.TestConstants; +import at.gv.egiz.eaaf.modules.pvp2.Pvp2SProfileCoreSpringResourceProvider; + + + +@RunWith(BlockJUnit4ClassRunner.class) +public class Pvp2SProfileCoreSpringResourceProviderTest { + + @Test + public void testSpringConfig() { + final Pvp2SProfileCoreSpringResourceProvider test = + new Pvp2SProfileCoreSpringResourceProvider(); + for (final Resource el : test.getResourcesToLoad()) { + try { + IOUtils.toByteArray(el.getInputStream()); + + } catch (final IOException e) { + Assert.fail("Ressouce: " + el.getFilename() + " not found"); + } + + } + + Assert.assertNotNull("no Name", test.getName()); + Assert.assertNull("Find package definitions", test.getPackagesToScan()); + + } + + @Test + public void testSpILoaderConfig() { + final InputStream el = this.getClass().getResourceAsStream(TestConstants.TEST_SPI_LOADER_PATH); + try { + final String spiFile = IOUtils.toString(el, "UTF-8"); + + Assert.assertEquals("Wrong classpath in SPI file", + Pvp2SProfileCoreSpringResourceProvider.class.getName(), spiFile); + + + } catch (final IOException e) { + Assert.fail("Ressouce: " + TestConstants.TEST_SPI_LOADER_PATH + " not found"); + + } + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/QaaLevelVerifierTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/QaaLevelVerifierTest.java new file mode 100644 index 00000000..44cdf111 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/QaaLevelVerifierTest.java @@ -0,0 +1,147 @@ +package at.gv.egiz.eaaf.modules.pvp2.test; + +import java.util.Arrays; +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.BlockJUnit4ClassRunner; + +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.modules.pvp2.exception.QaaNotAllowedException; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.QaaLevelVerifier; + +@RunWith(BlockJUnit4ClassRunner.class) +public class QaaLevelVerifierTest { + + QaaLevelVerifier verifyer = new QaaLevelVerifier(); + + @Test + public void matchingModeUnknown() { + String matchingMode = "notExist"; + List<String> requiredLoAs = Arrays.asList(EaafConstants.EIDAS_LOA_SUBSTANTIAL); + + try { + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_LOW, requiredLoAs, matchingMode); + Assert.fail("LoA should not be allowed"); + + } catch (QaaNotAllowedException e) { + + } + + try { + QaaLevelVerifier.verifyQaaLevel("not_exist", requiredLoAs, matchingMode); + Assert.fail("LoA should not be allowed"); + + } catch (QaaNotAllowedException e) { + + } + + } + + @Test + public void matchingMinimumRequiredLow() throws QaaNotAllowedException { + String matchingMode = EaafConstants.EIDAS_LOA_MATCHING_MINIMUM; + List<String> requiredLoAs = Arrays.asList(EaafConstants.EIDAS_LOA_LOW); + + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_LOW, requiredLoAs, matchingMode); + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_SUBSTANTIAL, requiredLoAs, matchingMode); + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_HIGH, requiredLoAs, matchingMode); + + try { + QaaLevelVerifier.verifyQaaLevel("not_exist", requiredLoAs, matchingMode); + Assert.fail("LoA should not be allowed"); + + } catch (QaaNotAllowedException e) { + + } + + } + + @Test + public void matchingMinimumRequiredSubstantial() throws QaaNotAllowedException { + String matchingMode = EaafConstants.EIDAS_LOA_MATCHING_MINIMUM; + List<String> requiredLoAs = Arrays.asList(EaafConstants.EIDAS_LOA_SUBSTANTIAL); + + try { + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_LOW, requiredLoAs, matchingMode); + Assert.fail("LoA should not be allowed"); + + } catch (QaaNotAllowedException e) { + + } + + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_SUBSTANTIAL, requiredLoAs, matchingMode); + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_HIGH, requiredLoAs, matchingMode); + + try { + QaaLevelVerifier.verifyQaaLevel("not_exist", requiredLoAs, matchingMode); + Assert.fail("LoA should not be allowed"); + + } catch (QaaNotAllowedException e) { + + } + + } + + @Test + public void matchingMinimumRequiredHigh() throws QaaNotAllowedException { + String matchingMode = EaafConstants.EIDAS_LOA_MATCHING_MINIMUM; + List<String> requiredLoAs = Arrays.asList(EaafConstants.EIDAS_LOA_HIGH); + + try { + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_LOW, requiredLoAs, matchingMode); + Assert.fail("LoA should not be allowed"); + + } catch (QaaNotAllowedException e) { + + } + + try { + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_SUBSTANTIAL, requiredLoAs, matchingMode); + Assert.fail("LoA should not be allowed"); + + } catch (QaaNotAllowedException e) { + + } + + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_HIGH, requiredLoAs, matchingMode); + + try { + QaaLevelVerifier.verifyQaaLevel("not_exist", requiredLoAs, matchingMode); + Assert.fail("LoA should not be allowed"); + + } catch (QaaNotAllowedException e) { + + } + + } + + @Test + public void matchingExact1() throws QaaNotAllowedException { + String matchingMode = EaafConstants.EIDAS_LOA_MATCHING_EXACT; + List<String> requiredLoAs = Arrays.asList(EaafConstants.EIDAS_LOA_SUBSTANTIAL, EaafConstants.EIDAS_LOA_LOW); + + try { + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_HIGH, requiredLoAs, matchingMode); + Assert.fail("LoA should not be allowed"); + + } catch (QaaNotAllowedException e) { + + } + + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_LOW, requiredLoAs, matchingMode); + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_SUBSTANTIAL, requiredLoAs, matchingMode); + + try { + QaaLevelVerifier.verifyQaaLevel("not_exist", requiredLoAs, matchingMode); + Assert.fail("LoA should not be allowed"); + + } catch (QaaNotAllowedException e) { + + } + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/SamlVerificationEngineTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/SamlVerificationEngineTest.java new file mode 100644 index 00000000..66e87537 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/SamlVerificationEngineTest.java @@ -0,0 +1,720 @@ +package at.gv.egiz.eaaf.modules.pvp2.test; + +import java.util.ArrayList; +import java.util.List; + +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.exceptions.EaafProtocolException; +import at.gv.egiz.eaaf.core.exceptions.InvalidProtocolRequestException; +import at.gv.egiz.eaaf.core.impl.data.Pair; +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.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.SamlAssertionValidationExeption; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; +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.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.verification.SamlVerificationEngine; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyMetadataProvider; + +import org.joda.time.DateTime; +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.UnmarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; +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.EncryptedAssertion; +import org.opensaml.saml.saml2.core.Issuer; +import org.opensaml.saml.saml2.core.Response; +import org.opensaml.saml.saml2.core.StatusCode; +import org.opensaml.saml.saml2.encryption.Encrypter; +import org.opensaml.saml.saml2.encryption.Encrypter.KeyPlacement; +import org.opensaml.security.x509.X509Credential; +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.KeyInfoGeneratorFactory; +import org.opensaml.xmlsec.signature.support.SignatureConstants; +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.springframework.util.Assert; +import org.w3c.dom.Element; + +import net.shibboleth.utilities.java.support.xml.XMLParserException; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ "/spring/test_eaaf_pvp.beans.xml", + "/spring/test_eaaf_core_spring_config.beans.xml" }) +@TestPropertySource(locations = { "/config/config_1.props" }) +public class SamlVerificationEngineTest { + + @Autowired + private PvpMetadataResolverFactory metadataResolverFactory; + @Autowired + private SamlVerificationEngine verifyEngine; + @Autowired + private DummyCredentialProvider credentialProvider; + + @Autowired DummyMetadataProvider metadataProvider; + @Autowired IConfiguration authConfig; + + /** + * JUnit class initializer. + * + * @throws Exception In case of an OpenSAML3 initialization error + */ + @BeforeClass + public static void classInitializer() throws Exception { + EaafOpenSaml3xInitializer.eaafInitialize(); + + } + + @Test + public void validateSamlRequestSuccess() throws SecurityException, Exception { + + final String authnReqPath = "/data/AuthRequest_without_sig_1.xml"; + final String metadataPath = "classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml"; + final String spEntityId = metadataPath; + + final Pair<AuthnRequest, IPvp2MetadataProvider> inputMsg = + initializeAuthnRequest(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final PvpSProfileRequest msg = new PvpSProfileRequest( + inputMsg.getFirst(), + SAMLConstants.SAML2_POST_BINDING_URI); + msg.setEntityID(spEntityId); + + verifyEngine.verify(msg, + TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); + + } + + @Test + public void validateSamlRequestWrongSignature() throws SecurityException, Exception { + + final String authnReqPath = "/data/AuthRequest_without_sig_1.xml"; + final String metadataPath = "classpath:/data/pvp_metadata_junit_keystore.xml"; + final String spEntityId = metadataPath; + + final Pair<AuthnRequest, IPvp2MetadataProvider> inputMsg = + initializeAuthnRequest(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + metadataProvider.addMetadataResolverIntoChain(inputMsg.getSecond()); + + final PvpSProfileRequest msg = new PvpSProfileRequest( + inputMsg.getFirst(), + SAMLConstants.SAML2_POST_BINDING_URI); + msg.setEntityID(spEntityId); + + try { + verifyEngine.verify(msg, + TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); + org.junit.Assert.fail("Wrong signature not detected"); + + } catch (final Exception e) { + Assert.isInstanceOf(InvalidProtocolRequestException.class, e, "Wrong exceptionType"); + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.10", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void validateSamlInvalidRequest() throws SecurityException, Exception { + + final String authnReqPath = "/data/AuthRequest_without_sig_missing_id.xml"; + final String metadataPath = "classpath:/data/pvp_metadata_junit_keystore.xml"; + final String spEntityId = metadataPath; + + final Pair<AuthnRequest, IPvp2MetadataProvider> inputMsg = + initializeAuthnRequest(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + metadataProvider.addMetadataResolverIntoChain(inputMsg.getSecond()); + + final PvpSProfileRequest msg = new PvpSProfileRequest( + inputMsg.getFirst(), + SAMLConstants.SAML2_POST_BINDING_URI); + msg.setEntityID(spEntityId); + + try { + verifyEngine.verify(msg, + TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); + org.junit.Assert.fail("invalid request not detected"); + + } catch (final Exception e) { + Assert.isInstanceOf(InvalidProtocolRequestException.class, e, "Wrong exceptionType"); + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.03", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void validateSamlRequestWrongSignatureAlg() throws SecurityException, Exception { + + final String authnReqPath = "/data/AuthRequest_without_sig_1.xml"; + final String metadataPath = "classpath:/data/pvp_metadata_junit_keystore.xml"; + final String spEntityId = metadataPath; + + metadataProvider.runGarbageCollector(); + + final EaafX509Credential cred = credentialProvider.getMetaDataSigningCredential(); + cred.setSignatureAlgorithmForSigning(SignatureConstants.ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5); + final Pair<AuthnRequest, IPvp2MetadataProvider> inputMsg = + initializeAuthnRequest(spEntityId, metadataPath, authnReqPath, + cred); + + final PvpSProfileRequest msg = new PvpSProfileRequest( + inputMsg.getFirst(), + SAMLConstants.SAML2_POST_BINDING_URI); + msg.setEntityID(spEntityId); + + try { + verifyEngine.verify(msg, + TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); + org.junit.Assert.fail("Wrong SigAlg not detected"); + + } catch (final Exception e) { + Assert.isInstanceOf(EaafProtocolException.class, e, "Wrong exceptionType"); + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.99", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void verifyResponseSuccessTest() throws Pvp2InternalErrorException, SecurityException, Exception { + metadataProvider.runGarbageCollector(); + + final String authnReqPath = "/data/Response_without_sig_1.xml"; + final String metadataPath = "classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml"; + final String spEntityId = metadataPath; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final PvpSProfileResponse msg = new PvpSProfileResponse( + inputMsg.getFirst()); + msg.setEntityID(spEntityId); + + verifyEngine.verify(msg, + TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); + + } + + @Test + public void verifyResponseSuccessSecondTest() + throws Pvp2InternalErrorException, SecurityException, Exception { + + final String authnReqPath = "/data/Response_without_sig_1.xml"; + final String metadataPath = "classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml"; + final String spEntityId = metadataPath; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + verifyEngine.verifyIdpResponse(inputMsg.getFirst(), + TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); + + } + + @Test + public void verifySpResponse() + throws Pvp2InternalErrorException, SecurityException, Exception { + + final String authnReqPath = "/data/Response_without_sig_1.xml"; + final String metadataPath = "classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml"; + final String spEntityId = metadataPath; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + verifyEngine.verifySloResponse(inputMsg.getFirst(), + TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); + + } + + @Test + public void verifyResponseWithoutId() throws Pvp2InternalErrorException, SecurityException, Exception { + + final String authnReqPath = "/data/Response_with_sig_1.xml"; + final String metadataPath = "classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml"; + final String spEntityId = metadataPath; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final PvpSProfileResponse msg = new PvpSProfileResponse( + inputMsg.getFirst()); + msg.setEntityID(spEntityId); + + try { + verifyEngine.verify(msg, + TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); + org.junit.Assert.fail("Wrong XML schema not detected"); + + } catch (final Exception e) { + Assert.isInstanceOf(InvalidProtocolRequestException.class, e, "Wrong exceptionType"); + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.03", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void verifyResponseWrongTrust() throws Pvp2InternalErrorException, SecurityException, Exception { + + final String authnReqPath = "/data/Response_without_sig_1.xml"; + final String metadataPath = "classpath:/data/pvp_metadata_junit_keystore.xml"; + final String spEntityId = metadataPath; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final PvpSProfileResponse msg = new PvpSProfileResponse( + inputMsg.getFirst()); + msg.setEntityID(spEntityId); + + try { + verifyEngine.verify(msg, + TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); + org.junit.Assert.fail("No TrustedCert not detected"); + + } catch (final Exception e) { + Assert.isInstanceOf(InvalidProtocolRequestException.class, e, "Wrong exceptionType"); + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.10", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void verifyAssertionSucessNotEncrypted() throws SamlSigningException, Pvp2MetadataException, + CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { + final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; + final String metadataPath = "classpath:/data/pvp_metadata_junit_keystore.xml"; + final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + verifyEngine.validateAssertion(inputMsg.getFirst(), credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", false); + + + } + + @Test + public void verifyAssertionWrongAudiency() throws SamlSigningException, Pvp2MetadataException, + CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { + final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; + final String metadataPath = "classpath:/data/pvp_metadata_junit_keystore.xml"; + final String spEntityId = "https://demo.egiz.gv.at/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + try { + verifyEngine.validateAssertion(inputMsg.getFirst(), credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", false); + org.junit.Assert.fail("Wrong Audiency not detected"); + + } catch (final SamlAssertionValidationExeption e) { + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.15", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void verifyAssertionWrongStatusCode() throws SamlSigningException, Pvp2MetadataException, + CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { + final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; + final String metadataPath = "classpath:/data/pvp_metadata_junit_keystore.xml"; + final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final Response response = inputMsg.getFirst(); + response.getStatus().getStatusCode().setValue(StatusCode.RESPONDER); + + try { + verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", false); + org.junit.Assert.fail("Wrong StatusCode not detected"); + + } catch (final SamlAssertionValidationExeption e) { + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.17", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void verifyAssertionWrongIssueInstant() throws SamlSigningException, Pvp2MetadataException, + CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { + final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; + final String metadataPath = "classpath:/data/pvp_metadata_junit_keystore.xml"; + final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final Response response = inputMsg.getFirst(); + response.setIssueInstant(DateTime.now().plusMinutes(10)); + + try { + verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", true); + org.junit.Assert.fail("Wrong date not detected"); + + } catch (final SamlAssertionValidationExeption e) { + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.14", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void verifyAssertionNoContitions() throws SamlSigningException, Pvp2MetadataException, + CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { + final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; + final String metadataPath = "classpath:/data/pvp_metadata_junit_keystore.xml"; + final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final Response response = inputMsg.getFirst(); + response.getAssertions().get(0).setConditions(null); + + try { + verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", true); + org.junit.Assert.fail("Wrong date not detected"); + + } catch (final SamlAssertionValidationExeption e) { + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.15", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void verifyAssertionWrongContitions() throws SamlSigningException, Pvp2MetadataException, + CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { + final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; + final String metadataPath = "classpath:/data/pvp_metadata_junit_keystore.xml"; + final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final Response response = inputMsg.getFirst(); + + try { + verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", true); + org.junit.Assert.fail("Wrong date not detected"); + + } catch (final SamlAssertionValidationExeption e) { + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.15", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void verifyAssertionWrongContitionsAudienceRestrictions() throws SamlSigningException, Pvp2MetadataException, + CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { + final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; + final String metadataPath = "classpath:/data/pvp_metadata_junit_keystore.xml"; + final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final Response response = inputMsg.getFirst(); + response.getAssertions().get(0).getConditions().setNotBefore(DateTime.now()); + response.getAssertions().get(0).getConditions().setNotOnOrAfter(DateTime.now().plusMinutes(15)); + response.getAssertions().get(0).getConditions().getAudienceRestrictions().clear(); + + try { + verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", true); + org.junit.Assert.fail("Wrong date not detected"); + + } catch (final SamlAssertionValidationExeption e) { + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.15", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void verifyAssertionWrongContitionsNotBefore() throws SamlSigningException, Pvp2MetadataException, + CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { + final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; + final String metadataPath = "classpath:/data/pvp_metadata_junit_keystore.xml"; + final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final Response response = inputMsg.getFirst(); + response.getAssertions().get(0).getConditions().setNotBefore(DateTime.now().plusMinutes(10)); + response.getAssertions().get(0).getConditions().setNotOnOrAfter(DateTime.now().plusMinutes(15)); + + try { + verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", true); + org.junit.Assert.fail("Wrong date not detected"); + + } catch (final SamlAssertionValidationExeption e) { + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.15", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void verifyAssertionWrongContitionsNotOnOrAfter() throws SamlSigningException, Pvp2MetadataException, + CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { + final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; + final String metadataPath = "classpath:/data/pvp_metadata_junit_keystore.xml"; + final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final Response response = inputMsg.getFirst(); + response.getAssertions().get(0).getConditions().setNotBefore(DateTime.now()); + response.getAssertions().get(0).getConditions().setNotOnOrAfter(DateTime.now().minusMinutes(5)); + + try { + verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", true); + org.junit.Assert.fail("Wrong date not detected"); + + } catch (final SamlAssertionValidationExeption e) { + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.15", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void verifyAssertionValidContitions() throws SamlSigningException, Pvp2MetadataException, + CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { + final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; + final String metadataPath = "classpath:/data/pvp_metadata_junit_keystore.xml"; + final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final Response response = inputMsg.getFirst(); + response.getAssertions().get(0).getConditions().setNotBefore(DateTime.now()); + response.getAssertions().get(0).getConditions().setNotOnOrAfter(DateTime.now().plusMinutes(5)); + + + verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", true); + + } + + @Test + public void verifyEncAssertionWrongKey() throws SamlSigningException, Pvp2MetadataException, + CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { + final String authnReqPath = "/data/Asserion_enc_no_key.xml"; + final String metadataPath = "classpath:/data/pvp_metadata_junit_keystore.xml"; + final String spEntityId = "https://eid.a-sit.at/Shibboleth.sso/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + try { + verifyEngine.validateAssertion(inputMsg.getFirst(), credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", false); + org.junit.Assert.fail("Wrong date not detected"); + + } catch (final SamlAssertionValidationExeption e) { + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.16", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void verifyEncAssertion() throws Exception { + final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; + final String metadataPath = "classpath:/data/pvp_metadata_junit_keystore.xml"; + final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final Response response = inputMsg.getFirst(); + response.getAssertions().get(0).getConditions().setNotBefore(DateTime.now()); + response.getAssertions().get(0).getConditions().setNotOnOrAfter(DateTime.now().plusMinutes(5)); + + final Element secAssertionElement = XMLObjectSupport.marshall(response.getAssertions().get(0)); + + secAssertionElement.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xs", "http://www.w3.org/2001/XMLSchema"); + final Assertion secAssertion = (Assertion) XMLObjectSupport.getUnmarshaller(secAssertionElement) + .unmarshall(secAssertionElement); + + final EncryptedAssertion encAsserton = doEncryption(secAssertion, + credentialProvider.getMetaDataSigningCredential(), + authConfig); + response.getEncryptedAssertions().add(encAsserton); + + + verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", false); + + org.junit.Assert.assertEquals("Assertions not match", 2, response.getAssertions().size()); + + } + + @Test + public void verifyEncAssertionWrongSchema() throws Exception { + final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; + final String metadataPath = "classpath:/data/pvp_metadata_junit_keystore.xml"; + final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final Response response = inputMsg.getFirst(); + response.getAssertions().get(0).getConditions().setNotBefore(DateTime.now()); + response.getAssertions().get(0).getConditions().setNotOnOrAfter(DateTime.now().plusMinutes(5)); + + final Element secAssertionElement = XMLObjectSupport.marshall(response.getAssertions().get(0)); + + final Assertion secAssertion = (Assertion) XMLObjectSupport.getUnmarshaller(secAssertionElement) + .unmarshall(secAssertionElement); + + final EncryptedAssertion encAsserton = doEncryption(secAssertion, + credentialProvider.getMetaDataSigningCredential(), + authConfig); + response.getEncryptedAssertions().add(encAsserton); + + try { + verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", false); + + org.junit.Assert.fail("Wrong XML Schema not detected"); + + } catch (final SamlAssertionValidationExeption e) { + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.15", ((EaafException) e).getErrorId()); + + } + + } + + private Pair<Response, IPvp2MetadataProvider> initializeResponse(String spEntityId, String metadataPath, + String authnReqPath, EaafX509Credential credential) + throws SamlSigningException, XMLParserException, UnmarshallingException, Pvp2MetadataException { + final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( + metadataPath, null, "jUnit metadata resolver", null); + + final Response authnReq = (Response) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + SamlVerificationEngineTest.class.getResourceAsStream(authnReqPath)); + authnReq.setIssueInstant(DateTime.now()); + final Issuer issuer = Saml2Utils.createSamlObject(Issuer.class); + issuer.setValue(spEntityId); + authnReq.setIssuer(issuer); + + return Pair.newInstance( + Saml2Utils.signSamlObject(authnReq, credential, true), + mdResolver); + } + + private Pair<AuthnRequest, IPvp2MetadataProvider> initializeAuthnRequest(String spEntityId, + String metadataPath, String authnReqPath, EaafX509Credential credential) + throws SamlSigningException, CredentialsNotAvailableException, + XMLParserException, UnmarshallingException, Pvp2InternalErrorException, Pvp2MetadataException { + + final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( + metadataPath, null, "jUnit metadata resolver", null); + + final AuthnRequest authnReq = (AuthnRequest) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + SamlVerificationEngineTest.class.getResourceAsStream(authnReqPath)); + authnReq.setIssueInstant(DateTime.now()); + final Issuer issuer = Saml2Utils.createSamlObject(Issuer.class); + issuer.setValue(spEntityId); + authnReq.setIssuer(issuer); + + return Pair.newInstance( + Saml2Utils.signSamlObject(authnReq, credential, true), + mdResolver); + + } + + private static EncryptedAssertion doEncryption(Assertion assertion, + X509Credential encryptionCredentials, IConfiguration authConfig) + throws Exception { + try { + final String keyEncAlg = Saml2Utils.getKeyOperationAlgorithmFromCredential( + encryptionCredentials, + authConfig.getBasicConfiguration( + PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_RSA_ALG, + PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_RSA), + authConfig.getBasicConfiguration( + PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_EC_ALG, + PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_EC)); + + final DataEncryptionParameters dataEncParams = new DataEncryptionParameters(); + dataEncParams.setAlgorithm(authConfig.getBasicConfiguration( + PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_DATA, PvpConstants.DEFAULT_SYM_ENCRYPTION_METHODE)); + + final List<KeyEncryptionParameters> keyEncParamList = new ArrayList<>(); + final KeyEncryptionParameters keyEncParam = new KeyEncryptionParameters(); + keyEncParam.setEncryptionCredential(encryptionCredentials); + keyEncParam.setAlgorithm(keyEncAlg); + + final KeyInfoGeneratorFactory kigf = + SecurityConfigurationSupport.getGlobalEncryptionConfiguration() + .getKeyTransportKeyInfoGeneratorManager().getDefaultManager().getFactory(encryptionCredentials); + keyEncParam.setKeyInfoGenerator(kigf.newInstance()); + keyEncParamList.add(keyEncParam); + + final Encrypter samlEncrypter = new Encrypter(dataEncParams, keyEncParamList); + samlEncrypter.setKeyPlacement(KeyPlacement.PEER); + + return samlEncrypter.encrypt(assertion); + + } catch (final EncryptionException | SamlSigningException e1) { + throw new Exception(e1); + + } + + } + +} 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 76dba510..8833202a 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 @@ -9,27 +9,6 @@ import java.util.Map; import javax.xml.parsers.ParserConfigurationException; -import at.gv.egiz.eaaf.core.api.IRequest; -import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiBuilderConfiguration; -import at.gv.egiz.eaaf.core.impl.idp.module.gui.DummyGuiBuilderConfigurationFactory; -import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl; -import at.gv.egiz.eaaf.core.impl.utils.DomUtils; -import at.gv.egiz.eaaf.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; @@ -38,14 +17,19 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; +import org.opensaml.core.xml.XMLObject; import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.MarshallingException; import org.opensaml.core.xml.io.Unmarshaller; import org.opensaml.core.xml.io.UnmarshallerFactory; import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.core.xml.schema.XSString; import org.opensaml.core.xml.util.XMLObjectSupport; import org.opensaml.messaging.decoder.MessageDecodingException; import org.opensaml.messaging.encoder.MessageEncodingException; import org.opensaml.saml.common.SignableSAMLObject; +import org.opensaml.saml.saml2.core.AuthnRequest; +import org.opensaml.saml.saml2.core.Issuer; import org.opensaml.saml.saml2.core.RequestAbstractType; import org.opensaml.saml.saml2.core.StatusResponseType; import org.opensaml.saml.saml2.metadata.SPSSODescriptor; @@ -58,7 +42,34 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.w3c.dom.Element; import org.xml.sax.SAXException; +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiBuilderConfiguration; +import at.gv.egiz.eaaf.core.impl.idp.module.gui.DummyGuiBuilderConfigurationFactory; +import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl; +import at.gv.egiz.eaaf.core.impl.utils.DomUtils; +import at.gv.egiz.eaaf.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.api.reqattr.EaafRequestedAttribute; +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttributes; +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.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.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 at.gv.egiz.eaaf.modules.pvp2.test.metadata.MetadataResolverTest; import net.shibboleth.utilities.java.support.net.URIComparator; +import net.shibboleth.utilities.java.support.xml.SerializeSupport; import net.shibboleth.utilities.java.support.xml.XMLParserException; import okhttp3.HttpUrl; import okhttp3.mockwebserver.MockResponse; @@ -125,6 +136,34 @@ public class PostBindingTest { } @Test + public void wrongPostBindingEncoding() 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); + httpReq.setParameter("SAMLEncoding", RandomStringUtils.randomAlphabetic(5)); + + 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, Pvp2MetadataException { final String serviceUrl = "https://wrongEndpoint/pvp2/post"; @@ -315,6 +354,73 @@ public class PostBindingTest { } @Test + public void decodeRequestSuccessWithRequestAttributes() throws MessageDecodingException, SecurityException, + IOException, Pvp2Exception, CredentialsNotAvailableException, XMLParserException, UnmarshallingException, MarshallingException { + final String serviceUrl = "https://eidas-test.bmi.gv.at/ms_connector/pvp/post"; + final String relayState = RandomStringUtils.randomAlphanumeric(10); + + final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/eIDAS_connector_authn.xml")); + authnReq.setIssueInstant(DateTime.now()); + Issuer issuer = Saml2Utils.createSamlObject(Issuer.class); + issuer.setValue("https://demo.egiz.gv.at/demoportal_demologin/"); + authnReq.setIssuer(issuer); + + RequestAbstractType signedAuthn = Saml2Utils.signSamlObject(authnReq, credentialProvider.getMessageSigningCredential(), true); + Element signedElement = XMLObjectSupport.getMarshaller(signedAuthn).marshall(signedAuthn); + final String b64AuthnReq = + Base64.getEncoder().encodeToString(SerializeSupport.nodeToString(signedElement).getBytes("UTF-8")); + 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 URIComparator comparator = new EaafUriCompare(serviceUrl); + + final InboundMessageInterface msg = + 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.assertTrue("Wrong isVerified flag", msg.isVerified()); + + org.springframework.util.Assert.isInstanceOf(PvpSProfileRequest.class, msg, "Inbound message is of wrong type"); + org.springframework.util.Assert.isInstanceOf(AuthnRequest.class, ((PvpSProfileRequest)msg).getSamlRequest(), + "Inbound message is of wrong type"); + + AuthnRequest parsedAuthnReq = (AuthnRequest)((PvpSProfileRequest)msg).getSamlRequest(); + Assert.assertNotNull("No extension", parsedAuthnReq.getExtensions()); + Assert.assertNotNull("No extension child", parsedAuthnReq.getExtensions().getUnknownXMLObjects()); + Assert.assertEquals("extension child size", 1, parsedAuthnReq.getExtensions().getUnknownXMLObjects().size()); + + XMLObject reqAttrs = parsedAuthnReq.getExtensions().getUnknownXMLObjects().get(0); + org.springframework.util.Assert.isInstanceOf(EaafRequestedAttributes.class, reqAttrs, "Wrong requested Attributes type"); + EaafRequestedAttributes eaafReqAttrs = (EaafRequestedAttributes) reqAttrs; + Assert.assertNotNull("Req attr is null", eaafReqAttrs.getAttributes()); + Assert.assertFalse("Req attr is empty", eaafReqAttrs.getAttributes().isEmpty()); + Assert.assertEquals("Req attr size", 1, eaafReqAttrs.getAttributes().size()); + + EaafRequestedAttribute eaafReqAttr = eaafReqAttrs.getAttributes().get(0); + Assert.assertNotNull("Req Attibute is null", eaafReqAttr); + Assert.assertEquals("Req. Attr. Friendlyname", "EID-SECTOR-FOR-IDENTIFIER", eaafReqAttr.getFriendlyName()); + Assert.assertEquals("Req. Attr. Name", "urn:oid:1.2.40.0.10.2.1.1.261.34", eaafReqAttr.getName()); + + Assert.assertEquals("Req. Attr. Value size", 1, eaafReqAttr.getAttributeValues().size()); + org.springframework.util.Assert.isInstanceOf(XSString.class, eaafReqAttr.getAttributeValues().get(0), + "Wrong requested Attributes Value type"); + Assert.assertEquals("Req. Attr. Value", "urn:publicid:gv.at:cdid+BF", ((XSString)eaafReqAttr.getAttributeValues().get(0)).getValue()); + + } + + @Test public void decodeRequestSuccessWithoutRelayStateEcdsaSig() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception, CredentialsNotAvailableException, XMLParserException, UnmarshallingException { final String serviceUrl = "http://testservice.org"; @@ -340,6 +446,13 @@ public class PostBindingTest { 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()); + + //check if reconstraction from serialized form work well + ((InboundMessage)msg).setSamlMessage(null); + try { + Assert.assertNotNull("AuthnReq is null", msg.getInboundMessage()); + + } catch (RuntimeException e) { } } @@ -367,6 +480,8 @@ public class PostBindingTest { 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()); + + org.springframework.util.Assert.isInstanceOf(PvpSProfileResponse.class, msg, "Inbound message is of wrong type"); } 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 f85e5c2a..408729e3 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 @@ -2,36 +2,15 @@ package at.gv.egiz.eaaf.modules.pvp2.test.binding; import java.io.IOException; import java.net.URLDecoder; -import java.util.Base64; import javax.xml.parsers.ParserConfigurationException; -import at.gv.egiz.eaaf.core.api.IRequest; -import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl; -import at.gv.egiz.eaaf.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.xml.config.XMLObjectProviderRegistrySupport; @@ -50,6 +29,24 @@ 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.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 net.shibboleth.utilities.java.support.net.URIComparator; import net.shibboleth.utilities.java.support.net.URISupport; import net.shibboleth.utilities.java.support.xml.XMLParserException; @@ -129,6 +126,93 @@ public class RedirectBindingTest { } @Test + public void wrongHttpRequestMethod() 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("POST"); + 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.95", e.getErrorId()); + + } + } + + @Test + public void wrongRedirectBindingType() 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("POST"); + 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("SAMLEncoding", RandomStringUtils.randomAlphabetic(5)); + + 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.95", e.getErrorId()); + + } + } + + @Test public void decodeRequestNoSignature() throws MessageDecodingException, SecurityException, IOException, Pvp2MetadataException { final String serviceUrl = "http://testservice.org"; @@ -169,7 +253,6 @@ public class RedirectBindingTest { Assert.assertEquals("Wrong errorCode", "internal.pvp.02", e.getErrorId()); } - } @Test @@ -362,38 +445,6 @@ public class RedirectBindingTest { } - @Ignore - @Test - public void decodeRequestSuccessWithRelayState() throws MessageDecodingException, - SecurityException, IOException, Pvp2Exception { - final String serviceUrl = "http://testservice.org"; - final String relayState = RandomStringUtils.randomAlphanumeric(10); - - final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray( - RedirectBindingTest.class.getResourceAsStream("/data/AuthRequest_with_sig_1.xml"))); - httpReq.setMethod("POST"); - httpReq.addParameter("SAMLRequest", b64AuthnReq); - httpReq.addParameter("RelayState", relayState); - - final IPvp2MetadataProvider metadataProvider = null; - - final URIComparator comparator = new EaafUriCompare(serviceUrl); - - final InboundMessageInterface msg = - 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.assertFalse("Wrong isVerified flag", msg.isVerified()); - - } - @Test public void decodeResponseSuccess() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception, CredentialsNotAvailableException, XMLParserException, UnmarshallingException { diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/dummy/DummyMetadataProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/dummy/DummyMetadataProvider.java new file mode 100644 index 00000000..64ebe00c --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/dummy/DummyMetadataProvider.java @@ -0,0 +1,80 @@ +package at.gv.egiz.eaaf.modules.pvp2.test.dummy; + +import java.io.IOException; +import java.security.cert.CertificateException; +import java.util.ArrayList; +import java.util.List; + +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; +import at.gv.egiz.eaaf.core.impl.utils.IHttpClientFactory; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.AbstractChainingMetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; + +import org.opensaml.saml.metadata.resolver.MetadataResolver; +import org.opensaml.saml.metadata.resolver.filter.MetadataFilter; +import org.opensaml.saml.metadata.resolver.filter.MetadataFilterChain; +import org.springframework.beans.factory.annotation.Autowired; + +public class DummyMetadataProvider extends AbstractChainingMetadataProvider { + + private final List<String> configuredMetadataUrls = new ArrayList<>(); + private String metadataProviderName; + + @Autowired PvpMetadataResolverFactory resolverFactory; + @Autowired IHttpClientFactory httpClientFactory; + private final MetadataFilterChain metadataFilters = new MetadataFilterChain(); + + @Override + protected String getMetadataUrl(String entityId) throws EaafConfigurationException { + return entityId; + + } + + @Override + protected MetadataResolver createNewMetadataProvider(String entityId) throws EaafConfigurationException, + IOException, CertificateException { + try { + return resolverFactory.createMetadataProvider(entityId, metadataFilters, entityId, null, + httpClientFactory.getHttpClient()); + + } catch (final Pvp2MetadataException e) { + throw new EaafConfigurationException("internal.pvp.04", new Object[] {entityId}, e); + + } + + } + + @Override + protected List<String> getAllMetadataUrlsFromConfiguration() throws EaafConfigurationException { + return configuredMetadataUrls; + + } + + @Override + protected String getMetadataProviderId() { + return metadataProviderName; + + } + + public void addMetadataUrls(List<String> metadataUrls) { + configuredMetadataUrls.addAll(metadataUrls); + + } + + public void clearMetadataUrls() { + configuredMetadataUrls.clear(); + + } + + public void setMetadataProviderName(String name) { + metadataProviderName = name; + + } + + public void setMetadataFilters(List<MetadataFilter> filtersToUse) { + metadataFilters.setFilters(filtersToUse); + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/ChainingMetadataTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/ChainingMetadataTest.java new file mode 100644 index 00000000..8e00068f --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/ChainingMetadataTest.java @@ -0,0 +1,166 @@ +package at.gv.egiz.eaaf.modules.pvp2.test.metadata; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.Arrays; + +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.impl.utils.FileUtils; +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.Pvp2MetadataException; +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.dummy.DummyMetadataProvider; + +import org.apache.commons.io.IOUtils; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opensaml.core.criterion.EntityIdCriterion; +import org.opensaml.saml.criterion.EntityRoleCriterion; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml.saml2.metadata.SPSSODescriptor; +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.resolver.CriteriaSet; +import net.shibboleth.utilities.java.support.resolver.ResolverException; +import okhttp3.HttpUrl; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; + + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ "/spring/test_eaaf_pvp.beans.xml", + "/spring/test_eaaf_core_spring_config.beans.xml" }) +@TestPropertySource(locations = { "/config/config_1.props" }) +public class ChainingMetadataTest { + + private static MockWebServer mockWebServer; + private static HttpUrl mockServerUrl; + + @Autowired DummyMetadataProvider metadataProvider; + @Autowired PvpMetadataResolverFactory factory; + @Autowired IConfiguration authConfig; + @Autowired IHttpClientFactory httpFactory; + + + /** + * 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"); + } + + @Test + public void runGarbageCollector() throws ResolverException, Pvp2MetadataException, + UnsupportedEncodingException, IOException { + + 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 EntityDescriptor entityDesc = + metadataProvider.getEntityDescriptor("classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml"); + Assert.assertNotNull("EntityDesc is null", entityDesc); + + final IPvp2MetadataProvider provider2 = factory.createMetadataProvider( + "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit", null); + metadataProvider.addMetadataResolverIntoChain(provider2); + + final IPvp2MetadataProvider provider3 = factory.createMetadataProvider( + "classpath:/data/pvp_metadata_valid_with_entityCategory_egov.xml", null, "jUnit", null); + metadataProvider.addMetadataResolverIntoChain(provider3); + + final IPvp2MetadataProvider provider4 = factory.createMetadataProvider( + mockServerUrl.url().toString(), null, "jUnit", httpFactory.getHttpClient()); + metadataProvider.addMetadataResolverIntoChain(provider4); + + + + + metadataProvider.addMetadataUrls(Arrays.asList( + FileUtils.makeAbsoluteUrl("classpath:/data/pvp_metadata_junit_keystore.xml", + authConfig.getConfigurationRootDirectory()), mockServerUrl.url().toString())); + + metadataProvider.runGarbageCollector(); + + final EntityDescriptor entityDesc4 = + metadataProvider.getEntityDescriptor("classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml"); + Assert.assertNotNull("EntityDesc is null", entityDesc4); + + + metadataProvider.clearMetadataUrls(); + metadataProvider.runGarbageCollector(); + + final CriteriaSet criteria = new CriteriaSet(); + criteria.add(new EntityIdCriterion("classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml")); + final EntityDescriptor entityDesc5 = metadataProvider.resolveSingle(criteria); + Assert.assertNotNull("EntityDesc is null", entityDesc5); + + + final CriteriaSet criteria6 = new CriteriaSet(); + criteria6.add(new EntityIdCriterion("classpath:/data/classpath:/data/pvp_metadata_junit_keystore.xml")); + final EntityDescriptor entityDesc6 = metadataProvider.resolveSingle(criteria6); + Assert.assertNull("EntityDesc not null", entityDesc6); + + metadataProvider.refreshMetadataProvider("classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml"); + + metadataProvider.clear(); + + metadataProvider.refreshMetadataProvider("classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml"); + + metadataProvider.clear("classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml"); + + Assert.assertFalse("Wrong refresh flag", metadataProvider.wasLastRefreshSuccess()); + + metadataProvider.getMetadataFilter(); + + metadataProvider.fullyDestroy(); + + metadataProvider.refreshMetadataProvider("classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml"); + + final CriteriaSet criteria7 = new CriteriaSet(); + criteria7.add(new EntityIdCriterion("classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml")); + final Iterable<EntityDescriptor> entityDesc7 = metadataProvider.resolve(criteria7); + Assert.assertNotNull("EntityDesc is null", entityDesc7); + Assert.assertTrue("is Empty", entityDesc7.iterator().hasNext()); + + final CriteriaSet criteria8 = new CriteriaSet(); + criteria8.add(new EntityIdCriterion("classpath:/data/classpath:/data/pvp_metadata_junit_keystore.xml")); + final Iterable<EntityDescriptor> entityDesc8 = metadataProvider.resolve(criteria8); + Assert.assertNotNull("EntityDesc not null", entityDesc8); + Assert.assertFalse("is not Empty", entityDesc8.iterator().hasNext()); + + metadataProvider.refresh(); + + metadataProvider.getLastRefresh(); + + metadataProvider.getLastSuccessfulRefresh(); + + metadataProvider.getLastUpdate(); + + metadataProvider.refreshMetadataProvider("classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml"); + + + final CriteriaSet criteria9 = new CriteriaSet(); + criteria9.add(new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME)); + final Iterable<EntityDescriptor> entityDesc9 = metadataProvider.resolve(criteria9); + Assert.assertNotNull("EntityDesc not null", entityDesc9); + + } + + +} 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 index f8402510..6cf81d2b 100644 --- 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 @@ -14,14 +14,6 @@ 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; @@ -49,6 +41,14 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +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.api.utils.IPvp2CredentialProvider; +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 net.shibboleth.utilities.java.support.xml.XMLParserException; @@ -84,7 +84,7 @@ public class MetadataBuilderTest { TransformerException, ParserConfigurationException, IOException, SignatureException, XMLParserException, UnmarshallingException, CertificateException { - final IPvpMetadataBuilderConfiguration config = idpMetadataConfig(false, true); + final IPvpMetadataBuilderConfiguration config = idpMetadataConfig(credentialProvider, false, true); //generate metadata final String metadata = metadataBuilder.buildPvpMetadata(config); @@ -102,7 +102,7 @@ public class MetadataBuilderTest { TransformerException, ParserConfigurationException, IOException, SignatureException, XMLParserException, UnmarshallingException, CertificateException { - final IPvpMetadataBuilderConfiguration config = idpMetadataConfig(true, false); + final IPvpMetadataBuilderConfiguration config = idpMetadataConfig(credentialProvider, true, false); //generate metadata final String metadata = metadataBuilder.buildPvpMetadata(config); @@ -120,7 +120,7 @@ public class MetadataBuilderTest { TransformerException, ParserConfigurationException, IOException, SignatureException, XMLParserException, UnmarshallingException, CertificateException { - final IPvpMetadataBuilderConfiguration config = idpMetadataConfig(true, true); + final IPvpMetadataBuilderConfiguration config = idpMetadataConfig(credentialProvider, true, true); //generate metadata final String metadata = metadataBuilder.buildPvpMetadata(config); @@ -155,7 +155,7 @@ public class MetadataBuilderTest { return entity; } - private IPvpMetadataBuilderConfiguration idpMetadataConfig(boolean buildSpInfos, boolean buildIdpInfos) { + public static IPvpMetadataBuilderConfiguration idpMetadataConfig(IPvp2CredentialProvider credentialProvider, boolean buildSpInfos, boolean buildIdpInfos) { return new IPvpMetadataBuilderConfiguration() { @Override diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Asserion_enc_no_key.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Asserion_enc_no_key.xml new file mode 100644 index 00000000..a1428347 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Asserion_enc_no_key.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8"?> +<saml2p:Response Destination="https://eid.a-sit.at/Shibboleth.sso/SAML2/POST" ID="_d4c5806eb9d7aec2a37541184023d38d" InResponseTo="_f9db5e7b5ddfd119edc3f9b63b086071" IssueInstant="2020-02-05T13:06:55.691Z" Version="2.0" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"> + <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://eid.a-sit.at/idp/shibboleth</saml2:Issuer> + <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:SignedInfo> + <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"/> + <ds:Reference URI="#_d4c5806eb9d7aec2a37541184023d38d"> + <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#sha512"/> + <ds:DigestValue>InYZAEShnT3qk+4LlRpjt+nxCQAnerLIMQpoMzT8/SQ8E8vG36c06b4pjnjUa91p4ehdn1NSV52+9GlbXCBp8Q==</ds:DigestValue> + </ds:Reference> + </ds:SignedInfo> + <ds:SignatureValue>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE=</ds:SignatureValue> + <ds:KeyInfo> + <ds:X509Data> + <ds:X509Certificate>MIIDBzCCAq2gAwIBAgIINiXH097lKl4wCgYIKoZIzj0EAwIwGjEYMBYGA1UEAwwPTG9jYWxQa2lT +ZXJ2aWNlMB4XDTIwMDIwNTEyMjQyOVoXDTIwMDUwNTExMjQyOVowLjEZMBcGA1UEAwwQN2xXOUps +S2FYRW93eDJFYzERMA8GA1UECgwIc29mdHdhcmUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQDCOl3IYslq+HV1/FlSJxCdzKJ439pM98U+UfJ+bMEI6k/heFS/MNCsDDiWbIpeD2G8mDss +N1dl5xKvhgBaibYoKCjNS/sToOzhUVNfIdy/S9fc74nrXsaHB1sAf33L/2srpE2dTy/KQKAqtZ7M +eSC3GRnIyqb6KWBDSNItQ0o/6EGn+enFSkTiZM/WUWfMhe46vCVF2QWV6NvRv64xMJtYsC3dHiGs +xYgG9uZitcs0dfsY/DH4xr/vd3g5uioTDs5PElFrvzx4lbpsWMRy5OmfCRvt0R+VXP53+9o6xvNg +TbkV9rh54xwzf6geqMxT7S9na7/YzCq4hg9V4FkYCZfvXXazcxJeUNTChhvKBBXozia+FnDM67/s +QlTW2ZhGzTWv/Zs1a1xA65qahJuDeHVKo6fagAGlYNNFXNDbzPdpydtbj+5vF8dnpMp9fC9nPeQD +8BF3DOA4vraNET4XraX/vaWkvaKVCtoWYnX510TbMqtwLmksq2KiIe4mEcuEINhQ/3ERwH0mwn+/ +LKVVBRdN0gucMTSlglFe0ctuyDb8sId5kGxxucwjFBjqsRSCXpHEjlydFE0fPF6slTGl0+GCJdpJ +StDuaQ38a35U+N7x9IucakNGBXfZcwWp4dx4t8cokxLN5bpPpLo3PVfMBQ0dnH9MSzm5nVhJL5fJ +Q1asrQIDAQABMAoGCCqGSM49BAMCA0gAMEUCIQD04k68PMq+VuwfIbIWJkg3weQUASVKxKDjHnfH +/YsrPQIgVkmT8vTKC6YrfaAiMlFXsQGX9iDJBbnqNB3+9GUY7Z0=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </ds:Signature> + <saml2p:Status> + <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> + </saml2p:Status> + <saml2:EncryptedAssertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"> + <xenc:EncryptedData Id="_8bfb44aaaec124f25496619c3c59daa9" Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"> + <xenc:EncryptionMethod Algorithm="http://www.w3.org/2009/xmlenc11#aes128-gcm" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"/> + <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <xenc:EncryptedKey Id="_9af666773660a6b50b4da5879a0ed6a5" Recipient="https://eid.a-sit.at/shibboleth" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"> + <xenc:EncryptionMethod Algorithm="http://www.w3.org/2009/xmlenc11#rsa-oaep" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"> + <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/> + <xenc11:MGF Algorithm="http://www.w3.org/2009/xmlenc11#mgf1sha1" xmlns:xenc11="http://www.w3.org/2009/xmlenc11#"/> + </xenc:EncryptionMethod> + <ds:KeyInfo> + <ds:X509Data> + <ds:X509Certificate>MIID6zCCAlOgAwIBAgIJAPoNcjesqrTTMA0GCSqGSIb3DQEBCwUAMBcxFTATBgNVBAMTDGVpZC5h +LXNpdC5hdDAeFw0yMDAyMDUwODQ3MjlaFw0zMDAyMDIwODQ3MjlaMBcxFTATBgNVBAMTDGVpZC5h +LXNpdC5hdDCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBALxWBbZxOq06T+jUsJdpl8B2 +r6EYlY8MoNGsFDGyc/KuEALitFboBkgH0ztNS4YLGGdaTi3WPX3NZGr5zBx8bsxVvEW67mTkLSlw +3/FWhO8oMUuBQlR21piecVZBLj91NHstkcTSD5Cbq4uBRpPKBha7b5DrCD1BvLBYto5BCsLYeNp4 +UFgBFaLP+nUpS5fOaA6IGPRPDVKkL9wxob4Md75FuuE58MdiwaByzGjNtsmYM8uTy8wnFpXvYDwj +g3z3Pe3jrpoUglSdrFweTnXCCrkuqzjWtt5CHYW47NgrcV7hRARHFlzzBgYW2kmLnMNdhJHOldkN +DKaqn0oV2gCaemxvWKVbSYcZ27kyYFqPWaou/o4ufvQT9P8LeFKayL10b7chEU4UbJYTjh4Pi4On +VhOtOrguNJDd/qbcKrlHRb+DpDVHmZi5w9HDpg3l3SlGTzuib0nWZ64IG4Y8a1c2tpFRoiYv/aXu +7JHPMRNp/LoA1qwoF19jUzV8TWZbrrPkIwIDAQABozowODAXBgNVHREEEDAOggxlaWQuYS1zaXQu +YXQwHQYDVR0OBBYEFLP5q5ESOCfShH5tQmk6gN+PgSNSMA0GCSqGSIb3DQEBCwUAA4IBgQBHHhCl +un9DsVkT+LSEkKwyRI90wppWRpzEg2HFhbc+G53jF/qPX2WlvAASDULzPH+uBrqdbiAUlXk1JBYc +Ux0u6xV0mGSHdgq0eSzlLI/exjJTtsIOT8zeSTwjvhlNiXlJGSanoOUVNysIXM4Nv+NUB/MbYcVT +xDXzYGl45qhNhCcLSD4pQmVRAuhElH/ZwNXtUjaN2x48alZTq/+hdGK+YpNqeHS8+LcqkX9Mctth +xkF6piecW9QYzzmDlq+sOaezdhRcUS4tABaOmBFysO2GdMUtaDnBGeFiMLdRRijAEwBFYSO425pW +9Sj9ce32RgsopRF1Sz1SbbH4COrf5LdQwzS7qEUdDXQIOP7HbO9NrXkyN3W/lp5c/uVBe5fQt8Ke +v7jKaanqQozChmu6/iO7Y8DHj2/4o3QHfw4qjraJoGOSbqHDq4wBr8c403nnuGQzW0BWA04Cm0J1 +UAq08IPUdLQdsRtHOb+IVig/3S2PekIIl/U73OJChRg9566vwNo=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + <xenc:CipherData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"> + <xenc:CipherValue>ex7yi4ATGyUZmH9deZW5zwG8DGE/38pIR4hMJKQpOhxWMkwIgDmQ9AxB9qjYb7Rg7sVm6Tzeyy7cYkKvC3v5yLkCJ4JMfBSn2jmovAUW9o6m0S/IVSyzWUknIzVO5ZRK91M0TINmlo7kKeD9mtW2LNgo2Ai5mfCThjPGbkJFelHJjDCnu2IGu+3g1uif8kx5m3NAVg7vT8SrpdQSCZrsuhw7IM5OEKxtutAeLDdu8W88bkLDeaM+Oe7jKRfa25q5ZEpFWfDKnju0qIybjzGifS/nZDT0CRftFsusZ8QMoytvQ2Brget6ymH723sAjngDE+JZ6Za9U4FJH/8P2n7Fs91i1QCPMbuib0oLvgW4TR4rZebrWtDlYDe5MlDwdGtJX3iWu2Rt/gK5HKztFFeo0+6O2kvdZsqmnmXLV14RK+e3upoY+crcSofyqU61ouwnyYLTOqoR5xMUDl4QSCfbkoUngVKxDQr4c5eulnhQqs3WIBM83BVpqSPFnfrdJP3q</xenc:CipherValue> + </xenc:CipherData> + </xenc:EncryptedKey> + </ds:KeyInfo> + <xenc:CipherData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"> + <xenc:CipherValue>tr9Nhnr8opMNTj5+fWTSfnPhuVm2g3VxF9UPLbub0yrXgEOpIFvR6vf/c2r0g4o1f1ddPmndPPOjqYTln4OT04PT/WLS3lrfoPj4fu+KS3WGfZjL8JmgL/6hkhUHll1tzx4PiBvMVP4MCrH4ieKfHWQDDxVexPznJ3yLbGiplh/jOcot8zgDIEu87x9vQoEM71pDjz2/vBje2DgZN1Bf2K8lRERLWl1dC06EPqH99eUXBVo94LdMqsOEECBJmzfOvivd5JsoQ7x5eZ3cfYmPwtQkQjg8FDLxFpLcXAmadZQrYK9dVIKLRZtI7QxEKV+rd/dHvIvyqRT+YMCobkvSC8xdneVlr0PgXL2oY3yFaGbL4a1paIpDxkEe1sCbz4ucY/SRoKd6zqmBFXIS1wZSkUcrvuIzuGBho7Bn0GPc167kaplLshW/CoklNLQJEFnjWu2VPGLj8IZjApYVkRgv/LZZRLJ8I4zfAI6wblqPQPsLm1adiBtBsI2CygkOkL5T5PPHmjJxFWoczIiNGfxwOUpMSGrQE2GVjsAc3r76FwJW40PjcgEsDeAsZaX0ct7LfJolhZSMI/h9cu2VtDgxq/eeGZzXVvTIG68oKUjLnKlCXCcwE+KdHjLnVF8N0gwWYau59Ln8DODP6l1kvmb7O034uI3eiTumqgJT27uAJ9KQol1LsmHZZoeiDJY4nMV7MAHfIMSHetzPiOSF2xilkwi0te7cWfJRDhWtymIilMTDkJTTqN9EHK5GbZ3JzPVsyw+PbI36PudiS3KOsb6qdb42fcWfOFeeOLOEsb1pxk/aHk8sG14i01MTGGJRhPZcBmrxJmLy5TNZ8Xp/kiA1w4cTwoDk8aQcUeMg350rEGbhW6/9Jm5BPC+z0GhnzWo0DnzLuJCu1zSmO2s+bUwBnGH/ZFxbf4DWCmYrq+T32hfrTFUncZOenlLkPgM7vJK/o4ND/d76z00ud6BoPPa67q4ZxAMgo2T2+HGjrL6JsbivcjOazByKSq9aCOYy9LpaWD20k8c3voqzt+GUJadc7bEeEn7fBI0Y7J4hRfFQiSanXn/fHbUPUZMlctDgkJrQFeRI0Jrkrlp8k8RErMdAdYQI8j5cMphKTXAF/gpc0dFI6HPgVQk7ioEYIUh/44OssVLKjYoQAZnZN1ndgVHHl8jogB3KQ+mVJoBlnckyWneO9bNcnekfWI6F4UHdzzjiPeujobglkzc5eOnw2fL8ELqHW4gzKFfrukQgOCgmEHIJV8TBzGRLmIN3kLvPvA7Q3oneb6J2+FPwT1wZupKoqwmKDiUtu+O99JGsjW6J5C9MdVT5DE0NShM4FU/XvmPAQIOO31Rg1HIdNH9fodCtyA8YT76Xjpi73nt7SjkJyKX/jdHMhFzHTblYpDV98ZoRq8I/AU71KbV1w7u5ThNfPHYBsWVm28KtpzfvxV0yFV5HtTHwLiXmu9P0D2o1K6aB6XC6hlgeB1VtujJBya7zaF45xLGVfYDj4HALqxqDDv0T+qIlgoRe1/c8LbVdYzZU8Yseqe1QC6NQA7277xBheF8LqHTXBaOeIOVgkKHHTb64AZ2eqrnKGnWV3VT1k3GszboZz4TNKg3izu7R54+UmF6psLhVW1mUaHvjVviZiXlu215XlOVop7P3Q6WBR1i8p4PvLSy5IiEwCRIPzXSjVPkFHujwcaqHZ0VgD+p9lfHHh4LARcZM9+tvD67FNt4Uq9W+l3mocN2suGEJfWElm9Z1TdPKzqQUJwZPEnL1JZKykAic5CmTqo7uqGHzIL0SzIrsnkbPclFFgHjXWJOgMfnya58pUh3RX7QQ1+ZH6/C0qeILzXjAJXNKfHEgro99GFGN5kxQShDqJljWKDjbJ9M8ioDqt/4KvMwkferpaNro4/06k8/qhKmFh/I/cNd9SfIaYEU95Ej121nFBD20qOXCUKCQ3rP1z33ezZ2Lld+RSr+fkJ/8IlarVCitENmR6fn7cVCmwEYcK7kfZSCZ0FFgb9gf/LpPE4jlZ3voyNquvXIrlG47WC6IwHOieY4PalONmhKHkYzhngnAyvuHQ/vUJ5PxF/9Ks7KQA+UVFaP/fiuNED8UZ/iziBmEolw2/A==</xenc:CipherValue> + </xenc:CipherData> + </xenc:EncryptedData> + </saml2:EncryptedAssertion> +</saml2p:Response> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_without_sig_missing_id.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_without_sig_missing_id.xml new file mode 100644 index 00000000..e028d8d1 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_without_sig_missing_id.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" IssueInstant="2014-03-05T06:39:02.775Z" Version="2.0"> + <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_demologin/</saml2:Issuer> + <saml2:Subject xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"> + <saml2:NameID>https://demo.egiz.gv.at/demoportal_demologin/</saml2:NameID> + </saml2:Subject> + <saml2p:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/> + <saml2p:RequestedAuthnContext> + <saml2:AuthnContextClassRef xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://www.stork.gov.eu/1.0/citizenQAALevel/4</saml2:AuthnContextClassRef> + </saml2p:RequestedAuthnContext> +</saml2p:AuthnRequest> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_without_sig_1.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_without_sig_1.xml index 2683742e..e6530cca 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,5 +1,5 @@ <?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"> +<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" ID="_4c1c39ee0969b320bf0cae37816f7d5b" 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_demologin/</saml2:Issuer> <saml2p:Status> <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_without_sig_classpath_entityid.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_without_sig_classpath_entityid.xml new file mode 100644 index 00000000..2683742e --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_without_sig_classpath_entityid.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://demo.egiz.gv.at/demoportal_demologin/securearea.action" InResponseTo="_aeebfae3ce681fe3ddcaf213a42f01d3" IssueInstant="2014-03-05T06:39:51.017Z" Version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"> + <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_demologin/</saml2:Issuer> + <saml2p:Status> + <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> + </saml2p:Status> + <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_602c3236bffaf71ac3ac88674e76ff9f" IssueInstant="2014-03-05T06:39:51.017Z" Version="2.0"> + <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata</saml2:Issuer> + <saml2:Subject> + <saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" NameQualifier="urn:publicid:gv.at:cdid+BF">QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:NameID> + <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> + <saml2:SubjectConfirmationData InResponseTo="_aeebfae3ce681fe3ddcaf213a42f01d3" NotOnOrAfter="2014-03-05T06:44:51.017Z" Recipient="https://demo.egiz.gv.at/demoportal_demologin/securearea.action"/> + </saml2:SubjectConfirmation> + </saml2:Subject> + <saml2:Conditions NotBefore="2014-03-05T06:39:51.017Z" NotOnOrAfter="2014-03-05T06:44:51.017Z"> + <saml2:AudienceRestriction> + <saml2:Audience>https://demo.egiz.gv.at/demoportal_demologin/</saml2:Audience> + </saml2:AudienceRestriction> + </saml2:Conditions> + <saml2:AuthnStatement AuthnInstant="2014-03-05T06:39:51.017Z" SessionIndex="_c0c683509a8ff6ac372a9cf9c5c5a406"> + <saml2:AuthnContext> + <saml2:AuthnContextClassRef>http://www.stork.gov.eu/1.0/citizenQAALevel/4</saml2:AuthnContextClassRef> + </saml2:AuthnContext> + </saml2:AuthnStatement> + <saml2:AttributeStatement> + <saml2:Attribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">2.1</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Mustermann</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Max</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">1940-01-01</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">BF:QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="EID-CITIZEN-QAA-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.94" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:integer">4</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">AT</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">urn:publicid:gv.at:cdid+BF</saml2:AttributeValue> + </saml2:Attribute> + </saml2:AttributeStatement> + </saml2:Assertion> +</saml2p:Response> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/eIDAS_connector_authn.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/eIDAS_connector_authn.xml new file mode 100644 index 00000000..8ca219a7 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/eIDAS_connector_authn.xml @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="UTF-8"?> +<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:xs="http://www.w3.org/2001/XMLSchema" AssertionConsumerServiceIndex="0" Destination="https://eidas-test.bmi.gv.at/ms_connector/pvp/post" ID="_d9748baa2c1d4cdaa436b2191307fc0e" IsPassive="false" IssueInstant="2020-02-06T15:18:56.002Z" ProviderName="OpenID Connect Demo" 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_moaid-2.0/sp/eidas/metadata</saml2:Issuer> + <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:SignedInfo> + <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> + <ds:Reference URI="#_d9748baa2c1d4cdaa436b2191307fc0e"> + <ds:Transforms> + <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> + <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"> + <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs"/> + </ds:Transform> + </ds:Transforms> + <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> + <ds:DigestValue>LxI6QpEx3gT26uxEJi9xZBSVeZIEPUiFYn48Kn8484E=</ds:DigestValue> + </ds:Reference> + </ds:SignedInfo> + <ds:SignatureValue>Id1Zxcrp5RgQw63/NnsYItW82JIWbBhyhL2l/vvcDNN6ccMo5NMY8qcPfmUuOmzi4JdbolAlR3wvoOu4CTXSl8w6Gz67Bbv4qP2kn+Mn6y2Eo40DMM2eEPq529yu9Aa4vU7uLVCHVUGw6vjvlnBeLw4Axwi2v1uxmGIEORb2XKeoy1DjWI9EdhJf7bufL+fEW3AdzZ5GRAUtZ3zh569G9BNnigzUg+j5Rn7An99QR1+2OrxTCFazH7m+Z8ouFXD9LEFtuJJzSEsRGIrU9/9RVYE6gYlb3qA3At2pY5sso2TEUqY2uknBCybz5PoSChAt+SgMp63nWoc9XRk4j/Lkww==</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> + <saml2p:Extensions> + <eid:RequestedAttributes xmlns:eid="http://eid.gv.at/eID/attributes/saml-extensions"> + <eid: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"> + <eid:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">urn:publicid:gv.at:cdid+BF</eid:AttributeValue> + </eid:RequestedAttribute> + </eid:RequestedAttributes> + </saml2p:Extensions> + <saml2p:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/> + <saml2p:RequestedAuthnContext Comparison="minimum"> + <saml2:AuthnContextClassRef xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://eidas.europa.eu/LoA/low</saml2:AuthnContextClassRef> + </saml2p:RequestedAuthnContext> + <saml2p:Scoping> + <saml2p:RequesterID>https://demo.egiz.gv.at/demoportal-openID_demo</saml2p:RequesterID> + </saml2p:Scoping> +</saml2p:AuthnRequest>
\ 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 index 96560960..7fdbef90 100644 --- 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 @@ -71,21 +71,22 @@ ANsmjI2azWiTSFjb7Ou5fnCfbeiJUP0s66m8qS4rYl9L <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: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:KeyInfo> </md:KeyDescriptor> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_junit_keystore_classpath_entityId.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_junit_keystore_classpath_entityId.xml new file mode 100644 index 00000000..cfc334a6 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_junit_keystore_classpath_entityId.xml @@ -0,0 +1,204 @@ +<?xml version="1.0" encoding="UTF-8"?> +<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_2e23ca9b2ba4dc9eef15187830d07ff0" entityID="classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml" validUntil="2045-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:IDPSSODescriptor WantAuthnRequestsSigned="true" 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:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/post"/> + <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/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:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/post"/> + <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/redirect"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="EID-AUTH-BLOCK" Name="urn:oid:1.2.40.0.10.2.1.1.261.62" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="MANDATE-FULL-MANDATE" Name="urn:oid:1.2.40.0.10.2.1.1.261.92" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="MANDATOR-NATURAL-PERSON-SOURCE-PIN" Name="urn:oid:1.2.40.0.10.2.1.1.261.70" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="EID-STORK-TOKEN" Name="urn:oid:1.2.40.0.10.2.1.1.261.96" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="EID-SOURCE-PIN" Name="urn:oid:1.2.40.0.10.2.1.1.261.36" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="MANDATOR-NATURAL-PERSON-SOURCE-PIN-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.102" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="EID-SOURCE-PIN-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.104" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" 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"/> + </md:IDPSSODescriptor> + <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_valid_with_entityCategory_egov.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid_with_entityCategory_egov.xml index cb680e82..5129c494 100644 --- 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 @@ -1,5 +1,5 @@ <?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"> +<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="2045-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#"/> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core_map_config.beans.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core_map_config.beans.xml index 3e1df7d2..c1660a70 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core_map_config.beans.xml +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core_map_config.beans.xml @@ -10,7 +10,9 @@ 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="dummyAuthConfigMap" + class="at.gv.egiz.eaaf.core.impl.idp.module.test.DummyAuthConfigMap"> + <constructor-arg value="/config/config_1.props" /> + </bean> </beans>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core_spring_config.beans.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core_spring_config.beans.xml index 5aef9544..5319236b 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core_spring_config.beans.xml +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core_spring_config.beans.xml @@ -10,10 +10,9 @@ 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="dummyAuthConfigMap" - class="at.gv.egiz.eaaf.core.impl.idp.module.test.DummyAuthConfigMap"> - <constructor-arg value="/config/config_1.props" /> - </bean> + <bean id="dummyAuthConfig" + class="at.gv.egiz.eaaf.core.impl.idp.module.test.DummyAuthConfig" /> + <bean id="eaafKeyStoreFactory" class="at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory" /> 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 aac94041..e7cc42ed 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 @@ -16,5 +16,10 @@ <bean id="dummyCredentialProvider" class="at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider" /> + <bean id="dummyChainingMetadataResolver" + class="at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyMetadataProvider"/> + + <bean id="samlVerificationEngine" + class="at.gv.egiz.eaaf.modules.pvp2.impl.verification.SamlVerificationEngine"/> </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 2e9cb88d..0170febf 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/pom.xml +++ b/eaaf_modules/eaaf_module_pvp2_idp/pom.xml @@ -39,6 +39,12 @@ </dependency> <dependency> <groupId>at.gv.egiz.eaaf</groupId> + <artifactId>eaaf_core_utils</artifactId> + <scope>test</scope> + <type>test-jar</type> + </dependency> + <dependency> + <groupId>at.gv.egiz.eaaf</groupId> <artifactId>eaaf-core</artifactId> <scope>test</scope> <type>test-jar</type> 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 16cd27cd..f9d7767f 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,6 +23,19 @@ 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; @@ -44,19 +57,6 @@ import at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding; import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileRequest; 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); @@ -117,10 +117,10 @@ public class AuthenticationAction implements IAction { IEncoder binding = null; if (consumerService.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { - binding = springContext.getBean("PVPRedirectBinding", RedirectBinding.class); + binding = springContext.getBean("PvpRedirectBinding", RedirectBinding.class); } else if (consumerService.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) { - binding = springContext.getBean("PVPPOSTBinding", PostBinding.class); + binding = springContext.getBean("PvpPostBinding", PostBinding.class); } 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 565f28fb..482a2a09 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 @@ -31,6 +31,10 @@ import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; import org.joda.time.DateTime; 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.criterion.ProtocolCriterion; @@ -61,6 +65,7 @@ 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 org.w3c.dom.Element; import net.shibboleth.utilities.java.support.component.ComponentInitializationException; import net.shibboleth.utilities.java.support.resolver.CriteriaSet; @@ -158,9 +163,14 @@ public class AuthResponseBuilder { final Encrypter samlEncrypter = new Encrypter(dataEncParams, keyEncParamList); samlEncrypter.setKeyPlacement(KeyPlacement.PEER); - return samlEncrypter.encrypt(assertion); + final Element assertionElement = XMLObjectProviderRegistrySupport.getMarshallerFactory() + .getMarshaller(assertion).marshall(assertion); + assertionElement.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xs", "http://www.w3.org/2001/XMLSchema"); - } catch (final EncryptionException | SamlSigningException e1) { + return samlEncrypter.encrypt((Assertion) + XMLObjectSupport.getUnmarshaller(assertionElement).unmarshall(assertionElement)); + + } catch (final EncryptionException | SamlSigningException | MarshallingException | UnmarshallingException e1) { log.warn("Can not encrypt the PVP2 assertion", e1); throw new InvalidAssertionEncryptionException(); diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/AuthenticationActionTest.java b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/AuthenticationActionTest.java new file mode 100644 index 00000000..a88fa869 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/AuthenticationActionTest.java @@ -0,0 +1,226 @@ +package at.gv.egiz.eaaf.modules.pvp2.idp.test; + +import java.util.Date; + +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.lang3.time.DateFormatUtils; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +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 at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.auth.data.IIdentityLink; +import at.gv.egiz.eaaf.core.impl.idp.module.test.DummyAuthConfig; +import at.gv.egiz.eaaf.modules.pvp2.idp.exception.ResponderErrorException; +import at.gv.egiz.eaaf.modules.pvp2.idp.impl.AuthenticationAction; +import at.gv.egiz.eaaf.modules.pvp2.idp.impl.PvpSProfilePendingRequest; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({"/spring/test_eaaf_pvp.beans.xml"}) +@TestPropertySource( + locations = {"/config/config_1.props"}) +public class AuthenticationActionTest { + + @Autowired private DummyAuthConfig authConfig; + @Autowired private PvpMetadataResolverFactory metadataResolverFactory; + @Autowired private AuthenticationAction action; + + protected MockHttpServletRequest httpReq; + protected MockHttpServletResponse httpResp; + private PvpSProfilePendingRequest 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 PvpSProfilePendingRequest(); + + } + + @Test + public void checkNeedAuthFlag() { + Assert.assertTrue("Wrong 'needAuth' flag", action.needAuthentication(pendingReq, httpReq, httpResp)); + + } + + @Test + public void noAuthnRequestInPendingRequest() { + + IAuthData authData = generateAuthData(); + + try { + action.processRequest(pendingReq, httpReq, httpResp, authData); + Assert.fail("No SAML requst not detected"); + + } catch (ResponderErrorException e) { + Assert.assertEquals("Wrong errorCode", "pvp2.01", e.getErrorId()); + } + + } + + private IAuthData generateAuthData() { + return new IAuthData() { + + @Override + public boolean isSsoSession() { + return false; + } + + @Override + public boolean isForeigner() { + return false; + } + + @Override + public boolean isBaseIdTransferRestrication() { + return true; + } + + @Override + public Date getSsoSessionValidTo() { + return null; + + } + + @Override + public String getSessionIndex() { + return null; + + } + + @Override + public String getNameIdFormat() { + return null; + + } + + @Override + public String getNameID() { + return null; + + } + + @Override + public IIdentityLink getIdentityLink() { + return null; + + } + + @Override + public String getIdentificationValue() { + return null; + + } + + @Override + public String getIdentificationType() { + return null; + + } + + @Override + public String getGivenName() { + return RandomStringUtils.randomAlphabetic(10); + + } + + @Override + public <T> T getGenericData(String key, Class<T> clazz) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getFormatedDateOfBirth() { + return DateFormatUtils.format(getDateOfBirth(), "yyyy-MM-dd"); + } + + @Override + public String getFamilyName() { + return RandomStringUtils.randomAlphabetic(10); + + } + + @Override + public String getEncryptedSourceIdType() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getEncryptedSourceId() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getEidasQaaLevel() { + return EaafConstants.EIDAS_LOA_LOW; + } + + @Override + public Date getDateOfBirth() { + return new Date(); + + } + + @Override + public String getCiticenCountryCode() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getBpkType() { + return EaafConstants.URN_PREFIX_CDID + RandomStringUtils.randomAlphabetic(2); + } + + @Override + public String getBpk() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public String getAuthenticationIssuer() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public String getAuthenticationIssueInstantString() { + return DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.format(getAuthenticationIssueInstant()); + } + + @Override + public Date getAuthenticationIssueInstant() { + return new Date(); + } + }; + + } +} 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 index 98cf5f40..b2e528c4 100644 --- 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 @@ -7,12 +7,16 @@ 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.CredentialsNotAvailableException; import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlAssertionValidationExeption; 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.impl.verification.SamlVerificationEngine; import at.gv.egiz.eaaf.modules.pvp2.test.binding.PostBindingTest; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; import org.apache.commons.lang3.RandomStringUtils; import org.joda.time.DateTime; @@ -43,6 +47,8 @@ public class AuthnResponseBuilderTest { @Autowired private DummyAuthConfig authConfig; @Autowired private PvpMetadataResolverFactory metadataResolverFactory; + @Autowired private SamlVerificationEngine verifyEngine; + @Autowired private DummyCredentialProvider credentialProvider; /** * JUnit class initializer. @@ -99,4 +105,52 @@ public class AuthnResponseBuilderTest { } + @Test + public void encryptedAssertionWithDecryption() throws InvalidAssertionEncryptionException, Pvp2MetadataException, + XMLParserException, UnmarshallingException, MarshallingException, TransformerException, IOException, + SamlAssertionValidationExeption, CredentialsNotAvailableException { + 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()); + + verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), + "https://demo.egiz.gv.at/demoportal_demologin/", "jUnitTest", false); + + } + } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/MetadataActionTest.java b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/MetadataActionTest.java new file mode 100644 index 00000000..8436a43d --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/MetadataActionTest.java @@ -0,0 +1,67 @@ +package at.gv.egiz.eaaf.modules.pvp2.idp.test; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +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 at.gv.egiz.eaaf.core.impl.idp.module.test.DummyAuthConfig; +import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl; +import at.gv.egiz.eaaf.modules.pvp2.idp.impl.MetadataAction; +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.verification.SamlVerificationEngine; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({"/spring/test_eaaf_pvp.beans.xml"}) +@TestPropertySource( + locations = {"/config/config_1.props"}) +public class MetadataActionTest { + + @Autowired private DummyAuthConfig authConfig; + @Autowired private PvpMetadataResolverFactory metadataResolverFactory; + @Autowired private SamlVerificationEngine verifyEngine; + @Autowired private DummyCredentialProvider credentialProvider; + @Autowired private MetadataAction action; + + protected MockHttpServletRequest httpReq; + protected MockHttpServletResponse httpResp; + private TestRequestImpl 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 checkNeedAuthFlag() { + Assert.assertFalse("Wrong 'needAuth' flag", action.needAuthentication(pendingReq, httpReq, httpResp)); + + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/Pvp2SProfileIdpSpringResourceProviderTest.java b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/Pvp2SProfileIdpSpringResourceProviderTest.java new file mode 100644 index 00000000..f9aafea9 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/Pvp2SProfileIdpSpringResourceProviderTest.java @@ -0,0 +1,56 @@ +package at.gv.egiz.eaaf.modules.pvp2.idp.test; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.io.IOUtils; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.BlockJUnit4ClassRunner; +import org.springframework.core.io.Resource; + +import at.gv.egiz.eaaf.core.test.TestConstants; +import at.gv.egiz.eaaf.modules.pvp2.idp.Pvp2SProfileIdpSpringResourceProvider; + + + +@RunWith(BlockJUnit4ClassRunner.class) +public class Pvp2SProfileIdpSpringResourceProviderTest { + + @Test + public void testSpringConfig() { + final Pvp2SProfileIdpSpringResourceProvider test = + new Pvp2SProfileIdpSpringResourceProvider(); + for (final Resource el : test.getResourcesToLoad()) { + try { + IOUtils.toByteArray(el.getInputStream()); + + } catch (final IOException e) { + Assert.fail("Ressouce: " + el.getFilename() + " not found"); + } + + } + + Assert.assertNotNull("no Name", test.getName()); + Assert.assertNull("Find package definitions", test.getPackagesToScan()); + + } + + @Test + public void testSpILoaderConfig() { + final InputStream el = this.getClass().getResourceAsStream(TestConstants.TEST_SPI_LOADER_PATH); + try { + final String spiFile = IOUtils.toString(el, "UTF-8"); + + Assert.assertEquals("Wrong classpath in SPI file", + Pvp2SProfileIdpSpringResourceProvider.class.getName(), spiFile); + + + } catch (final IOException e) { + Assert.fail("Ressouce: " + TestConstants.TEST_SPI_LOADER_PATH + " not found"); + + } + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyLoALevelMapper.java b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyLoALevelMapper.java new file mode 100644 index 00000000..004df86d --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyLoALevelMapper.java @@ -0,0 +1,25 @@ +package at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy; + +import at.gv.egiz.eaaf.core.api.data.ILoALevelMapper; + +public class DummyLoALevelMapper implements ILoALevelMapper { + + @Override + public String mapToEidasLoa(String qaa) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String mapToSecClass(String qaa) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String mapEidasQaaToStorkQaa(String eidasqaaLevel) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyPvpConfiguration.java b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyPvpConfiguration.java new file mode 100644 index 00000000..78e2d700 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyPvpConfiguration.java @@ -0,0 +1,43 @@ +package at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy; + +import java.util.List; + +import org.opensaml.saml.saml2.metadata.ContactPerson; +import org.opensaml.saml.saml2.metadata.Organization; + +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.modules.pvp2.api.IPvp2BasicConfiguration; + +public class DummyPvpConfiguration implements IPvp2BasicConfiguration { + + @Override + public String getIdpEntityId(String authUrl) throws EaafException { + return authUrl + "/idp"; + } + + @Override + public String getIdpSsoPostService(String authUrl) throws EaafException { + return authUrl + "/sso/post"; + } + + @Override + public String getIdpSsoRedirectService(String authUrl) throws EaafException { + return authUrl + "/sso/redirect"; + } + + @Override + public Object getIdpSsoSoapService(String authUrl) throws EaafException { + return authUrl + "/sso/soap"; + } + + @Override + public List<ContactPerson> getIdpContacts() throws EaafException { + return null; + } + + @Override + public Organization getIdpOrganisation() throws EaafException { + return null; + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyPvpMetadataConfigFactory.java b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyPvpMetadataConfigFactory.java new file mode 100644 index 00000000..3f24480b --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyPvpMetadataConfigFactory.java @@ -0,0 +1,16 @@ +package at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy; + +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataConfigurationFactory; +import at.gv.egiz.eaaf.modules.pvp2.api.utils.IPvp2CredentialProvider; +import at.gv.egiz.eaaf.modules.pvp2.test.metadata.MetadataBuilderTest; + +public class DummyPvpMetadataConfigFactory implements IPvpMetadataConfigurationFactory { + + @Override + public IPvpMetadataBuilderConfiguration generateMetadataBuilderConfiguration(String authUrl, + IPvp2CredentialProvider pvpIdpCredentials) { + return MetadataBuilderTest.idpMetadataConfig(pvpIdpCredentials, false, true); + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummySubjectNameGenerator.java b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummySubjectNameGenerator.java new file mode 100644 index 00000000..3eaa4c09 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummySubjectNameGenerator.java @@ -0,0 +1,18 @@ +package at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy; + +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +import at.gv.egiz.eaaf.modules.pvp2.idp.api.builder.ISubjectNameIdGenerator; + +public class DummySubjectNameGenerator implements ISubjectNameIdGenerator { + + @Override + public Pair<String, String> generateSubjectNameId(IAuthData authData, ISpConfiguration spConfig) + throws Pvp2Exception { + return Pair.newInstance(authData.getBpk(), authData.getBpkType()); + + } + +} 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 index 96560960..7fdbef90 100644 --- 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 @@ -71,21 +71,22 @@ ANsmjI2azWiTSFjb7Ou5fnCfbeiJUP0s66m8qS4rYl9L <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: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:KeyInfo> </md:KeyDescriptor> 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 index 8c0b8596..99552053 100644 --- 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 @@ -22,7 +22,10 @@ <bean id="httpClientFactory" class="at.gv.egiz.eaaf.core.impl.utils.HttpClientFactory" /> + <bean id="dummyRevisionLogger" + class="at.gv.egiz.eaaf.core.impl.logging.DummyRevisionsLogger" /> + <bean id="eaafKeyStoreFactory" - class="at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory" /> + class="at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory" /> </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 index aac94041..2bddd629 100644 --- 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 @@ -12,9 +12,37 @@ <import resource="test_eaaf_core.beans.xml"/> <import resource="classpath:/eaaf_pvp.beans.xml"/> + <import resource="classpath:/eaaf_pvp_idp.beans.xml"/> <bean id="dummyCredentialProvider" class="at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider" /> + + <bean id="dummyChainingMetadataResolver" + class="at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyMetadataProvider" /> + <bean id="samlVerificationEngine" + class="at.gv.egiz.eaaf.modules.pvp2.impl.verification.SamlVerificationEngine" /> + + <bean id="dummyLoALevelMapper" + class="at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy.DummyLoALevelMapper" /> + + <bean id="dummySubjectNameIdGenerator" + class="at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy.DummySubjectNameGenerator" /> + + <bean id="dummyPvpBasicConfig" + class="at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy.DummyPvpConfiguration" /> + + <bean id="dummyMetadataConfigFactor" + class="at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy.DummyPvpMetadataConfigFactory" /> + + <bean id="PVPAuthenticationRequestAction" + class="at.gv.egiz.eaaf.modules.pvp2.idp.impl.AuthenticationAction"> + <property name="pvpIdpCredentials" ref="dummyCredentialProvider" /> + </bean> + + <bean id="pvpMetadataService" + class="at.gv.egiz.eaaf.modules.pvp2.idp.impl.MetadataAction" > + <property name="pvpIdpCredentials" ref="dummyCredentialProvider" /> + </bean> </beans>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PvpAuthnRequestBuilder.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PvpAuthnRequestBuilder.java index a81d9119..c906ca43 100644 --- a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PvpAuthnRequestBuilder.java +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PvpAuthnRequestBuilder.java @@ -24,18 +24,6 @@ import java.util.List; import javax.servlet.http.HttpServletResponse; -import at.gv.egiz.eaaf.core.api.IRequest; -import at.gv.egiz.eaaf.modules.pvp2.api.binding.IEncoder; -import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute; -import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttributes; -import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; -import at.gv.egiz.eaaf.modules.pvp2.impl.binding.PostBinding; -import at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding; -import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestExtensionBuilder; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; -import at.gv.egiz.eaaf.modules.pvp2.sp.api.IPvpAuthnRequestBuilderConfiguruation; -import at.gv.egiz.eaaf.modules.pvp2.sp.exception.AuthnRequestBuildException; - import org.apache.commons.lang3.StringUtils; import org.joda.time.DateTime; import org.opensaml.messaging.encoder.MessageEncodingException; @@ -62,6 +50,17 @@ 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.modules.pvp2.api.binding.IEncoder; +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute; +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttributes; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +import at.gv.egiz.eaaf.modules.pvp2.impl.binding.PostBinding; +import at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestExtensionBuilder; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import at.gv.egiz.eaaf.modules.pvp2.sp.api.IPvpAuthnRequestBuilderConfiguruation; +import at.gv.egiz.eaaf.modules.pvp2.sp.exception.AuthnRequestBuildException; import net.shibboleth.utilities.java.support.security.SecureRandomIdentifierGenerationStrategy; /** @@ -247,10 +246,10 @@ public class PvpAuthnRequestBuilder { // select message encoder IEncoder binding = null; if (endpoint.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { - binding = springContext.getBean("PVPRedirectBinding", RedirectBinding.class); + binding = springContext.getBean("PvpRedirectBinding", RedirectBinding.class); } else if (endpoint.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) { - binding = springContext.getBean("PVPPOSTBinding", PostBinding.class); + binding = springContext.getBean("PvpPostBinding", PostBinding.class); } else { log.warn("Binding: {} is not supported", endpoint.getBinding()); |